@sap/cds 7.6.3 → 7.7.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 (94) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/_i18n/i18n.properties +3 -0
  3. package/app/index.js +18 -12
  4. package/bin/serve.js +51 -19
  5. package/common.cds +16 -0
  6. package/lib/auth/ias-auth.js +2 -2
  7. package/lib/auth/index.js +1 -1
  8. package/lib/auth/jwt-auth.js +1 -1
  9. package/lib/compile/cdsc.js +23 -11
  10. package/lib/compile/for/nodejs.js +2 -2
  11. package/lib/compile/for/odata.js +4 -0
  12. package/lib/compile/load.js +7 -2
  13. package/lib/compile/to/sql.js +3 -0
  14. package/lib/dbs/cds-deploy.js +197 -220
  15. package/lib/env/defaults.js +2 -1
  16. package/lib/index.js +8 -2
  17. package/lib/linked/types.js +1 -0
  18. package/lib/log/format/json.js +1 -1
  19. package/lib/plugins.js +2 -2
  20. package/lib/ql/Query.js +1 -1
  21. package/lib/ql/SELECT.js +8 -8
  22. package/lib/req/context.js +22 -13
  23. package/lib/req/request.js +10 -4
  24. package/lib/srv/cds-connect.js +9 -3
  25. package/lib/srv/cds-serve.js +5 -3
  26. package/lib/srv/middlewares/ctx-model.js +1 -1
  27. package/lib/srv/protocols/odata-v4.js +38 -9
  28. package/lib/srv/srv-api.js +98 -140
  29. package/lib/srv/srv-models.js +2 -2
  30. package/lib/srv/srv-tx.js +1 -0
  31. package/lib/utils/cds-utils.js +32 -23
  32. package/lib/utils/data.js +1 -1
  33. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -3
  34. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +0 -2
  35. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +18 -1
  36. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -1
  37. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +7 -3
  38. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +2 -1
  39. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/http/HttpHeaderReader.js +4 -2
  40. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/index.js +5 -0
  41. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +71 -25
  42. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +10 -2
  43. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +6 -1
  44. package/libx/_runtime/cds-services/util/assert.js +50 -240
  45. package/libx/_runtime/cds.js +5 -0
  46. package/libx/_runtime/common/aspects/any.js +53 -45
  47. package/libx/_runtime/common/generic/input.js +14 -10
  48. package/libx/_runtime/common/generic/paging.js +1 -1
  49. package/libx/_runtime/common/utils/cqn2cqn4sql.js +1 -1
  50. package/libx/_runtime/common/utils/keys.js +1 -1
  51. package/libx/_runtime/common/utils/quotingStyles.js +1 -1
  52. package/libx/_runtime/common/utils/resolveStructured.js +4 -1
  53. package/libx/_runtime/common/utils/rewriteAsterisks.js +5 -12
  54. package/libx/_runtime/common/utils/stream.js +2 -16
  55. package/libx/_runtime/common/utils/streamProp.js +16 -6
  56. package/libx/_runtime/common/utils/ucsn.js +1 -0
  57. package/libx/_runtime/db/utils/columns.js +6 -1
  58. package/libx/_runtime/fiori/generic/activate.js +11 -3
  59. package/libx/_runtime/fiori/generic/edit.js +8 -2
  60. package/libx/_runtime/fiori/lean-draft.js +99 -30
  61. package/libx/_runtime/hana/execute.js +2 -5
  62. package/libx/_runtime/messaging/service.js +6 -2
  63. package/libx/common/assert/index.js +232 -0
  64. package/libx/common/assert/type.js +109 -0
  65. package/libx/common/assert/utils.js +125 -0
  66. package/libx/common/assert/validation.js +109 -0
  67. package/libx/odata/index.js +5 -5
  68. package/libx/odata/middleware/create.js +83 -0
  69. package/libx/odata/middleware/delete.js +38 -0
  70. package/libx/odata/middleware/error.js +8 -0
  71. package/libx/odata/{metadata.js → middleware/metadata.js} +8 -6
  72. package/libx/odata/middleware/operation.js +78 -0
  73. package/libx/odata/middleware/parse.js +11 -0
  74. package/libx/odata/{read.js → middleware/read.js} +42 -20
  75. package/libx/odata/{service-document.js → middleware/service-document.js} +2 -1
  76. package/libx/odata/middleware/stream.js +237 -0
  77. package/libx/odata/middleware/update.js +165 -0
  78. package/libx/odata/{afterburner.js → parse/afterburner.js} +79 -29
  79. package/libx/odata/{cqn2odata.js → parse/cqn2odata.js} +5 -3
  80. package/libx/odata/{parseToCqn.js → parse/parseToCqn.js} +3 -6
  81. package/libx/odata/{utils.js → utils/index.js} +91 -9
  82. package/libx/outbox/index.js +5 -4
  83. package/libx/rest/RestAdapter.js +0 -1
  84. package/libx/rest/middleware/operation.js +6 -4
  85. package/libx/rest/middleware/parse.js +20 -2
  86. package/package.json +1 -1
  87. package/server.js +43 -71
  88. package/libx/odata/create.js +0 -44
  89. package/libx/odata/delete.js +0 -25
  90. package/libx/odata/error.js +0 -12
  91. package/libx/odata/update.js +0 -110
  92. /package/libx/odata/{grammar.peggy → parse/grammar.peggy} +0 -0
  93. /package/libx/odata/{parser.js → parse/parser.js} +0 -0
  94. /package/libx/odata/{result.js → utils/result.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,43 @@
4
4
  - The format is based on [Keep a Changelog](http://keepachangelog.com/).
5
5
  - This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## Version 7.7.0 - 2024-02-26
8
+
9
+ ### Added
10
+
11
+ - Improved trace output for bootstrap phase. For example try that:
12
+ ```js
13
+ DEBUG=trace cds w bookshop | grep trace
14
+ ```
15
+ - Support for `@odata.draft.bypass` to allow direct modifications of active instances.
16
+ - `req.user.tokenInfo` for `@sap/xssec`-based authentication (`ias`, `jwt`, `xsuaa`)
17
+ - `cds.fiori.draft_lock_timeout` as successor of `cds.drafts.cancellationTimeout`.
18
+ + Possible values are /^([0-9]+)(h|hrs|min)$/ or a number in milliseconds.
19
+ - There is a new `sap.common.Timezones` entity with a basic time zone definition. There will be accompanying data in package `@sap/cds-common-content`.
20
+ - Deprecation warnings for configuration options `cds.drafts.cancellationTimeout`, `cds.features.serve_on_root`, `cds.features.stream_compat`, `cds.fiori.lean_draft` and `cds.requires.middlewares`, as well as for the properties `req.user.locale` and `req.user.tenant`. The deprecation warnings can be turned off by setting `cds.features.deprecated` to `off`.
21
+
22
+ ### Changed
23
+
24
+ - The index page now lists all service endpoints, which is important for services that are exposed through multiple protocols.
25
+ - `cds.deploy` improves error diagnostics with deeper `Query` object inspection.
26
+ - Slightly changed the default export for ESM compatibility. This fixed failing ESM imports in Vitest tests.
27
+
28
+ ### Fixed
29
+
30
+ - Persistent outbox must not be used for `t0` tenant.
31
+ - Second `await cds.connect.to('X')`, where initialization of `X` results in an error, did not return.
32
+ - Support additional draft requests.
33
+ - `cds.log` with `null` as argument.
34
+
35
+ ## Version 7.6.4 - 2024-02-21
36
+
37
+ ### Fixed
38
+
39
+ - Emitting multiple message with an in-memory outbox
40
+ - Occasional crash for invalid draft requests
41
+ - On the index page, aditional links now show up again for non-OData services.
42
+ - Handling of thenables for queries
43
+
7
44
  ## Version 7.6.3 - 2024-02-13
8
45
 
9
46
  ### Fixed
@@ -47,7 +84,7 @@
47
84
  - Use new CDS schema for validation and code completion in `package.json` and `.cdsrc.json` files
48
85
  - Media Data Streaming
49
86
  + OData: Large binaries without `@Core.MediaType` annotation were previously returned as base64-encoded buffer. Starting from this `@sap/cds` version also not-annotated large binaries are ignored by OData. It is strongly recommended to annotate all large binary properties with `@Core.MediaType` and use it according to streaming scenarios.
50
- + Custom Handlers: `SELECT` with explicitely listed `SELECT.columns` of type `cds.LargeBinary` returns them as Readable streams. Large binary columns requested implicitely by `SELECT` (for example, with `.columns('*')`) are ignored.
87
+ + Custom Handlers: `SELECT` with explicitly listed `SELECT.columns` of type `cds.LargeBinary` returns them as Readable streams. Large binary columns requested implicitly by `SELECT` (for example, with `.columns('*')`) are ignored.
51
88
  + Streaming API: `cds.stream()` and `srv.stream()` are deprecated and will be removed with the next major release. Use `SELECT` with a single `cds.LargeBinary` column instead. The resulting object will contain the name of the column and a stream value. For example, `SELECT.one.from(E).columns(['image']).where(...)` returns `{ image: <media stream> }`.
52
89
  + Backward Compatibility: To restore previous behavior use `stream_compat`.
53
90
 
@@ -70,6 +70,9 @@ LanguageCode=Language Code
70
70
  #XTIT: Language Code Description
71
71
  LanguageCode.Description=A language code as specified in ISO 639-1
72
72
 
73
+ #XTIT Time zone code
74
+ TimeZoneCode=Time Zone Code
75
+
73
76
  #XTIT: User Identifier
74
77
  UserID=User ID
75
78
 
package/app/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  const cds = require('../lib')
2
2
  const { find, path, fs } = cds.utils
3
3
 
4
- const odata = srv => srv.endpoints?.[0]?.kind.startsWith('odata')
5
- const metadata = srv => odata(srv) ? ` / <a href="${srv.path}/$metadata">$metadata</a>` : ``
4
+ const odata = endpoint => endpoint.kind.startsWith('odata')
5
+ const metadata = endpoint => odata(endpoint) ? ` / <a href="${endpoint.path}/$metadata">$metadata</a>` : ``
6
+ const asHtmlId = s => s.replace(/[.:/$&?@]/g, '_').toLowerCase()
6
7
 
7
8
  module.exports = { get html(){
8
9
 
@@ -14,16 +15,21 @@ module.exports = { get html(){
14
15
  html => `\n<li><a href="${html}">/${html.replace(/^\//,'').replace('/index.html','')}</a></li>`
15
16
  ).join('\n') || '— none —'
16
17
  )
17
- .replace ('{{services}}', cds.service.providers.map (srv => srv._is_dark ? '' : `
18
+ .replace ('{{services}}', cds.service.providers
19
+ .filter(srv => !srv._is_dark)
20
+ .flatMap(srv => srv.endpoints.map(endpoint => ({srv, endpoint})))
21
+ .map (({srv, endpoint}) => `
22
+ <div id="${asHtmlId(srv.name)}-${endpoint.kind}">
18
23
  <h3>
19
- <a href="${srv.path}">${srv.path}</a>${metadata(srv)} ${_moreLinks(srv)}
24
+ <a href="${endpoint.path}">${endpoint.path}</a>${metadata(endpoint)} ${_moreLinks(srv, endpoint)}
20
25
  </h3>
21
26
  <ul>${_entities_in(srv).map (e => {
22
27
  return `
23
- <li>
24
- <a href="${srv.path}/${e.replace(/\./g, '_')}">${e}</a> ${_moreLinks(srv, e)}
28
+ <li id="${asHtmlId(srv.name)}-${endpoint.kind}-${asHtmlId(e)}">
29
+ <a href="${endpoint.path}/${e.replace(/\./g, '_')}">${e}</a> ${_moreLinks(srv, endpoint, e)}
25
30
  </li>`}).join('')}
26
31
  </ul>
32
+ </div>
27
33
  `).join(''))
28
34
 
29
35
  Object.defineProperty (this,'html',{value:html})
@@ -52,13 +58,13 @@ function _entities_in (service) {
52
58
  return exposed
53
59
  }
54
60
 
55
- function _moreLinks (srv, entity) {
56
- return odata(srv) ? (srv.$linkProviders || [])
57
- .map (linkProv => linkProv(entity))
58
- .filter (l => l && l.href && l.name)
59
- .sort ((l1, l2) => l1.name.localeCompare(l2))
61
+ function _moreLinks (srv, endpoint, entity) {
62
+ return (srv.$linkProviders || [])
63
+ .map (linkProv => linkProv(entity, endpoint))
64
+ .filter (l => l?.href && l?.name)
65
+ .sort ((l1, l2) => l1.name.localeCompare(l2.name))
60
66
  .map (l => ` <a class="preview" href="${l.href}" title="${l.title||l.name}"> &rarr; ${l.name}</a>`)
61
- .join (' ') : ''
67
+ .join (' ')
62
68
  }
63
69
 
64
70
  function _project(){
package/bin/serve.js CHANGED
@@ -159,11 +159,12 @@ async function serve (all=[], o={}) {
159
159
  await cds.plugins
160
160
 
161
161
  const TRACE = cds.debug('trace')
162
- // if (TRACE) {
163
- // TRACE?.time('load express '); require('express') // eslint-disable-line cds/no-missing-dependencies
164
- // TRACE?.timeEnd('load express ')
165
- // }
166
- TRACE?.time('cds bootstrap ')
162
+ TRACE?.time('total startup time'.padEnd(22))
163
+ if (TRACE) {
164
+ TRACE?.time('require express'.padEnd(22))
165
+ require('express') // eslint-disable-line cds/no-missing-dependencies
166
+ TRACE?.timeEnd('require express'.padEnd(22))
167
+ }
167
168
 
168
169
  // Load local server.js early in order to allow setting custom cds.log.Loggers
169
170
  const cds_server = await _local_server_js() || cds.server
@@ -186,8 +187,6 @@ async function serve (all=[], o={}) {
186
187
 
187
188
  }
188
189
 
189
- TRACE?.timeEnd('cds bootstrap ')
190
-
191
190
  // bootstrap server from project-local server.js or from @sap/cds/server.js
192
191
  const server = await cds_server(o)
193
192
 
@@ -210,8 +209,10 @@ async function serve (all=[], o={}) {
210
209
 
211
210
  const LOG = cds.log('cli|server')
212
211
  cds.shutdown = _shutdown //> for programmatic invocation
213
- process.on('unhandledRejection', e => _shutdown (e, cds.log().error('❗️Uncaught',e))) //> using std logger to have it labelled with [cds] - instead of [cli] -
214
- process.on('uncaughtException', e => _shutdown (e, cds.log().error('❗️Uncaught',e))) //> using std logger to have it labelled with [cds] - instead of [cli] -
212
+ if (!cds.repl) {
213
+ process.on('unhandledRejection', e => _shutdown (e, cds.log().error('❗️Uncaught',e))) //> using std logger to have it labelled with [cds] - instead of [cli] -
214
+ process.on('uncaughtException', e => _shutdown (e, cds.log().error('❗️Uncaught',e))) //> using std logger to have it labelled with [cds] - instead of [cli] -
215
+ }
215
216
  process.on('SIGINT', cds.watched ? _shutdown : (s,n)=>_shutdown(s,n,console.log())) //> newline after ^C
216
217
  process.on('SIGHUP', _shutdown)
217
218
  process.on('SIGHUP2', _shutdown)
@@ -236,6 +237,7 @@ async function serve (all=[], o={}) {
236
237
  process.on('message', msg => msg.close && _shutdown()) // by `cds watch` on Windows
237
238
  }
238
239
 
240
+ TRACE?.timeEnd('total startup time'.padEnd(22))
239
241
  return server
240
242
  })
241
243
  }
@@ -259,13 +261,13 @@ function _prepare_logging () { // NOSONAR
259
261
  console.time (_timer)
260
262
 
261
263
  // print information when model is loaded
262
- cds.on ('loaded', (model)=>{
263
- LOG.info (`loaded model from ${model.$sources.length} file(s):\n${COLORS ? '\x1b[2m' : ''}`)
264
- const limit = 30, shown = model.$sources.length === limit + 1 ? limit + 1 : limit // REVISIT: configurable limit?
265
- for (let each of model.$sources.slice(0, shown)) console.log (' ', local(each))
266
- if (model.$sources.length > shown) {
267
- if (LOG._debug) for (let each of model.$sources.slice(shown)) console.log (' ', local(each))
268
- else console.log (` ...${model.$sources.length-shown} more. Run with DEBUG=serve to show all files.`)
264
+ cds.on ('loaded', ({$sources:srcs})=>{
265
+ LOG.info (`loaded model from ${srcs.length} file(s):\n${COLORS ? '\x1b[2m' : ''}`)
266
+ const limit = 30, shown = srcs.length === limit + 1 ? limit + 1 : limit // REVISIT: configurable limit?
267
+ for (let each of srcs.slice(0, shown)) console.log (' ', local(each))
268
+ if (srcs.length > shown) {
269
+ if (LOG._debug) for (let each of srcs.slice(shown)) console.log (' ', local(each))
270
+ else console.log (` ...${srcs.length-shown} more. Run with DEBUG=serve to show all files.`)
269
271
  }
270
272
  COLORS && console.log ('\x1b[0m')
271
273
  })
@@ -278,10 +280,13 @@ function _prepare_logging () { // NOSONAR
278
280
  // print information about each provided service
279
281
  cds.on ('serving', (srv) => {
280
282
  const details = {}
281
- if (srv.path) details.path = srv.path
282
283
  if (srv._source && !srv._source.startsWith('@sap'))
283
284
  details.impl = local(srv._source)
284
- LOG.info (`${srv.mocked ? 'mocking' : 'serving'} ${srv.name}`, details)
285
+ if (srv.endpoints.length === 1)
286
+ details.path = srv.endpoints[0].path // for brevity, omit 'kind' if there is only one protocol
287
+ else if (srv.endpoints.length > 1)
288
+ details.endpoints = srv.endpoints // full endpoint details if more than one
289
+ LOG.info (`${srv.mocked ? 'mocking' : 'serving'} ${srv.name}`, details)
285
290
  })
286
291
 
287
292
  // print info when we are finally on air
@@ -291,8 +296,35 @@ function _prepare_logging () { // NOSONAR
291
296
  _timer && console.timeEnd (_timer)
292
297
  if (process.stdin.isTTY) LOG.info (`[ terminate with ^C ]\n`)
293
298
  })
294
- }
295
299
 
300
+ // print config deprecation warnings
301
+ if (cds.env.features.deprecated !== 'off') {
302
+ cds.once ('listening', () => {
303
+ // Remove with cds 8
304
+ if (cds.env.drafts?.cancellationTimeout)
305
+ cds.utils.deprecated({
306
+ old: 'cds.drafts.cancellationTimeout',
307
+ use: 'cds.fiori.draft_lock_timeout with adapted value'
308
+ })
309
+
310
+ // Remove with cds 8
311
+ if (!cds.env.fiori.lean_draft)
312
+ cds.utils.deprecated({ old: 'cds.fiori.lean_draft' })
313
+
314
+ // Remove with cds 8
315
+ if (!cds.requires.middlewares)
316
+ cds.utils.deprecated({ old: 'cds.requires.middlewares' })
317
+
318
+ // Remove with cds 8
319
+ if (cds.env.features.serve_on_root)
320
+ cds.utils.deprecated({ old: 'cds.features.serve_on_root', use: '@path annotation or adapt your consumers' })
321
+
322
+ // Remove with cds 8
323
+ if (cds.env.features.stream_compat)
324
+ cds.utils.deprecated({ old: 'cds.features.stream_compat' })
325
+ })
326
+ }
327
+ }
296
328
 
297
329
  /** handles --watch option */
298
330
  function _watch (project,o) {
package/common.cds CHANGED
@@ -19,6 +19,13 @@ type Currency : Association to sap.common.Currencies;
19
19
  */
20
20
  type Country : Association to sap.common.Countries;
21
21
 
22
+ /**
23
+ * Type for an association to Timezones
24
+ *
25
+ * See https://cap.cloud.sap/docs/cds/common#type-timezone
26
+ */
27
+ type Timezone : Association to sap.common.Timezones;
28
+
22
29
  /**
23
30
  * Entities to serve the reuse types with extensible code lists
24
31
  * including built-in support for value lists in Fiori.
@@ -61,6 +68,15 @@ context sap.common {
61
68
  minorUnit : Int16 @(title : '{i18n>CurrencyMinorUnit}');
62
69
  }
63
70
 
71
+ /**
72
+ * Code list for time zones
73
+ *
74
+ * See https://cap.cloud.sap/docs/cds/common#entity-timezones
75
+ */
76
+ entity Timezones : CodeList {
77
+ key code : String(100) @(title: '{i18n>TimeZoneCode}');
78
+ }
79
+
64
80
  /**
65
81
  * Aspect for a code list with name and description
66
82
  *
@@ -25,7 +25,7 @@ module.exports = function ias_auth(config) {
25
25
  //> grant_type === client_credentials or x509
26
26
  const roles = ['system-user']
27
27
  if (clientid === credentials.clientid) roles.push('internal-user')
28
- return new cds.User({ id: 'system', roles })
28
+ return new cds.User({ id: 'system', roles, tokenInfo })
29
29
  }
30
30
 
31
31
  // add all unknown attributes to req.user.attr in order to keep public API small
@@ -38,7 +38,7 @@ module.exports = function ias_auth(config) {
38
38
  if (attr.given_name) attr.givenName = attr.given_name
39
39
  if (attr.family_name) attr.familyName = attr.family_name
40
40
 
41
- return new cds.User({ id: payload.sub, attr })
41
+ return new cds.User({ id: payload.sub, attr, tokenInfo })
42
42
  }
43
43
 
44
44
  return (req, _, next) => {
package/lib/auth/index.js CHANGED
@@ -55,7 +55,7 @@ module.exports = function auth_factory (o) {
55
55
  function ctx_auth (req, res, next) {
56
56
  const ctx = cds.context
57
57
  ctx.user = req.user
58
- ctx.tenant = req.tenant || ctx.user?.tenant
58
+ ctx.tenant = req.tenant || req.user?.tenant
59
59
  next()
60
60
  }
61
61
 
@@ -40,7 +40,7 @@ module.exports = function jwt_auth(config) {
40
40
  attr.email = payload.email
41
41
  }
42
42
 
43
- return new cds.User({ id, roles, attr })
43
+ return new cds.User({ id, roles, attr, tokenInfo })
44
44
  }
45
45
 
46
46
  return (req, _, next) => {
@@ -76,8 +76,8 @@ const _options = {for: Object.assign (_options4, {
76
76
 
77
77
  hana(o) {
78
78
  let cdsc = this.sql (o, cds.env.hana) // returns clone
79
- cdsc.sqlChangeMode = cdsc.journal && cdsc.journal['change-mode']
80
- cdsc.disableHanaComments = !cdsc.comments
79
+ cdsc.sqlChangeMode ??= cdsc.journal && cdsc.journal['change-mode']
80
+ cdsc.disableHanaComments ??= !cdsc.comments
81
81
  delete cdsc.journal // cleanup avoiding side effects
82
82
  delete cdsc.comments
83
83
  return cdsc
@@ -125,15 +125,27 @@ module.exports = exports = {__proto__:compile, _options,
125
125
  edm: Object.assign ((csn,o) => compile.to.edm (csn, _options.for.edm(o)), {
126
126
  all: (csn,o) => compile.to.edm.all (csn, _options.for.edm(o))
127
127
  }),
128
- hdi: Object.assign ((csn,o) => compile.to.hdi (csn, _options.for.hana(o)), {
129
- migration: (csn,o,...etc) => {
130
- o = Object.assign ({...o},_options.for.hana(o)) //> REVISIT: need to flatten as compiler seems to clone options in that impl
131
- return compile.to.hdi.migration (csn, o, ...etc)
132
- }
133
- }),
134
- hdbcds: (csn,o) => compile.to.hdbcds (csn, _options.for.hana(o) ),
135
- sql: (csn,o) => compile.to.sql (csn, _options.for.sql(o) ),
128
+ hdi: Object.assign ((csn,o) => compile.to.hdi (csn, _options.for.hana(o)),
129
+ compile.to.hdi, // keywords
130
+ {
131
+ migration: (csn,o,...etc) => {
132
+ o = Object.assign ({...o},_options.for.hana(o)) //> REVISIT: need to flatten as compiler seems to clone options in that impl
133
+ return compile.to.hdi.migration (csn, o, ...etc)
134
+ }
135
+ },
136
+ ),
137
+ hdbcds: Object.assign(
138
+ (csn,o) => compile.to.hdbcds (csn, _options.for.hana(o)),
139
+ compile.to.hdbcds // keywords
140
+ ),
141
+ sql: Object.assign(
142
+ (csn,o) => compile.to.sql (csn, _options.for.sql(o)),
143
+ compile.to.sql // smart* functions
144
+ ),
136
145
  deltaSql: (csn, o, beforeCsn) => compile.to.sql.migration(csn, o, beforeCsn), // or like hdi.migration
137
- cdl: (csn,o) => compile.to.cdl (csn, _options4(o||{}) ),
146
+ cdl: Object.assign(
147
+ (csn,o) => compile.to.cdl (csn, _options4(o||{})),
148
+ compile.to.cdl // smart* functions
149
+ ),
138
150
  },
139
151
  }
@@ -4,7 +4,7 @@ const TRACE = cds.debug('trace')
4
4
 
5
5
  module.exports = function cds_compile_for_nodejs (csn,o) {
6
6
  if ('_4nodejs' in csn) return csn._4nodejs
7
- TRACE?.time('cds.compile 4n ')
7
+ TRACE?.time('cds.compile 4nodejs'.padEnd(22))
8
8
  let dsn = csn // cds.minify (csn)
9
9
  dsn = cds.compile.for.drafts (csn,o) //> creates a partial copy -> avoid any cds.linked() before
10
10
  dsn = unfold_csn (dsn)
@@ -12,6 +12,6 @@ module.exports = function cds_compile_for_nodejs (csn,o) {
12
12
  if (cds.env.fiori.lean_draft) cds.compile.for.lean_drafts(dsn, o)
13
13
  Object.defineProperty (csn, '_4nodejs', {value:dsn})
14
14
  Object.defineProperty (dsn, '_4nodejs', {value:dsn})
15
- TRACE?.timeEnd('cds.compile 4n ')
15
+ TRACE?.timeEnd('cds.compile 4nodejs'.padEnd(22))
16
16
  return dsn
17
17
  }
@@ -1,11 +1,15 @@
1
1
  const compile = require ('../cdsc')
2
+ const cds = require('../../index')
3
+ const TRACE = cds.debug('trace')
2
4
 
3
5
  module.exports = function cds_compile_for_odata (csn,_o) {
4
6
  if ('_4odata' in csn) return csn._4odata
7
+ TRACE?.time('cdsc.compile 4odata'.padEnd(22))
5
8
  let o = compile._options.for.odata(_o) //> required to inspect .sql_mapping below
6
9
  let dsn = compile.for.odata (csn,o)
7
10
  if (o.sql_mapping) dsn['@sql_mapping'] = o.sql_mapping //> compat4 old Java stack
8
11
  Object.defineProperty (csn, '_4odata', {value:dsn})
9
12
  Object.defineProperty (dsn, '_4odata', {value:dsn})
13
+ TRACE?.timeEnd('cdsc.compile 4odata'.padEnd(22))
10
14
  return dsn
11
15
  }
@@ -1,5 +1,10 @@
1
1
  const cds = require('..')
2
2
  const TRACE = cds.debug('trace')
3
+ if (TRACE) {
4
+ TRACE?.time('require cds.compiler'.padEnd(22))
5
+ require('@sap/cds-compiler/lib/compiler')
6
+ TRACE?.timeEnd('require cds.compiler'.padEnd(22))
7
+ }
3
8
 
4
9
  module.exports = exports = function load (files, options) {
5
10
  const any = cds.resolve(files,options)
@@ -16,7 +21,7 @@ exports.parsed = function cds_get (files, options, _flavor) {
16
21
  if (!files) files = ['*']; else if (!Array.isArray(files)) files = [files]
17
22
  if (o.files || o.flavor === 'files') return cds.resolve(files,o)
18
23
  if (o.sources || o.flavor === 'sources') return _sources4 (cds.resolve(files,o))
19
- if (!o.silent) TRACE?.time('cds.load model')
24
+ if (!o.silent) TRACE?.time('cdsc.compile *.cds'.padEnd(22))
20
25
 
21
26
  const csn = cds.compile (files,o,
22
27
  o.parse ? 'parsed' :
@@ -27,7 +32,7 @@ exports.parsed = function cds_get (files, options, _flavor) {
27
32
  return csn.then?.(_finalize) || _finalize(csn)
28
33
  function _finalize (csn) {
29
34
  if (!o.silent) cds.emit ('loaded', csn)
30
- if (!o.silent) TRACE?.timeEnd('cds.load model ')
35
+ if (!o.silent) TRACE?.timeEnd('cdsc.compile *.cds'.padEnd(22))
31
36
  return csn
32
37
  }
33
38
  }
@@ -2,13 +2,16 @@ const cds = require ('../..')
2
2
  const cdsc = require ('../cdsc')
3
3
  const keywords = require("@sap/cds-compiler").to.sql.sqlite.keywords
4
4
  const { unfold_ddl } = require ('../etc/_localized')
5
+ const TRACE = cds.debug('trace')
5
6
 
6
7
  function cds_compile_to_sql (csn,_o) {
8
+ TRACE?.time('cdsc.compile 2sql'.padEnd(22))
7
9
  csn = cds.minify(csn)
8
10
  csn = _extended(csn)
9
11
  const o = cdsc._options.for.sql(_o) //> used twice below...
10
12
  const all = cdsc.to.sql(csn,o) .map (each => each.replace(/^-- .+\n/,'')) //> strip comments
11
13
  const sql = unfold_ddl(all, csn, o)
14
+ TRACE?.timeEnd('cdsc.compile 2sql'.padEnd(22))
12
15
  if (o.as === 'str') return `\n${sql.join('\n\n')}\n`
13
16
  return sql
14
17
  }