@sap/cds 5.8.4 → 5.9.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 (244) hide show
  1. package/CHANGELOG.md +174 -77
  2. package/app/fiori/preview.js +16 -11
  3. package/app/index.js +1 -1
  4. package/bin/build/buildTaskFactory.js +3 -3
  5. package/bin/build/buildTaskProviderFactory.js +1 -1
  6. package/bin/build/constants.js +1 -1
  7. package/bin/build/provider/buildTaskHandlerEdmx.js +12 -7
  8. package/bin/build/provider/buildTaskHandlerInternal.js +1 -1
  9. package/bin/build/provider/buildTaskProviderInternal.js +8 -2
  10. package/bin/build/provider/hana/2migration.js +27 -24
  11. package/bin/build/provider/hana/index.js +17 -18
  12. package/bin/build/provider/hana/migrationtable.js +9 -10
  13. package/bin/build/provider/java-cf/index.js +4 -5
  14. package/bin/build/provider/node-cf/index.js +99 -6
  15. package/bin/cds.js +17 -18
  16. package/bin/deploy/to-hana/cfUtil.js +16 -19
  17. package/bin/deploy/to-hana/hana.js +7 -24
  18. package/bin/deploy/to-hana/hdiDeployUtil.js +8 -4
  19. package/bin/mtx/in-cds.js +2 -2
  20. package/bin/serve.js +10 -3
  21. package/bin/utils/modules.js +7 -0
  22. package/bin/version.js +56 -3
  23. package/lib/compile/cdsc.js +26 -3
  24. package/lib/compile/etc/_localized.js +36 -25
  25. package/lib/compile/etc/csv.js +8 -8
  26. package/lib/compile/for/drafts.js +9 -0
  27. package/lib/compile/for/java.js +16 -0
  28. package/lib/compile/for/nodejs.js +12 -0
  29. package/lib/compile/for/odata.js +1 -1
  30. package/lib/compile/index.js +3 -0
  31. package/lib/compile/minify.js +16 -2
  32. package/lib/compile/parse.js +2 -2
  33. package/lib/compile/resolve.js +35 -18
  34. package/lib/compile/to/json.js +3 -1
  35. package/lib/compile/to/sql.js +2 -2
  36. package/lib/compile/to/srvinfo.js +4 -2
  37. package/lib/connect/index.js +1 -1
  38. package/lib/core/entities.js +15 -14
  39. package/lib/core/index.js +39 -36
  40. package/lib/core/reflect.js +4 -2
  41. package/lib/deploy.js +114 -127
  42. package/lib/env/defaults.js +1 -0
  43. package/lib/env/index.js +165 -165
  44. package/lib/env/presets.js +1 -0
  45. package/lib/env/requires.js +120 -49
  46. package/lib/index.js +1 -0
  47. package/lib/log/format/kibana.js +2 -2
  48. package/lib/ql/SELECT.js +10 -0
  49. package/lib/ql/parse.js +1 -0
  50. package/lib/req/cds-context.js +4 -1
  51. package/lib/req/context.js +50 -56
  52. package/lib/req/event.js +1 -6
  53. package/lib/req/locale.js +6 -5
  54. package/lib/req/request.js +2 -0
  55. package/lib/req/user.js +7 -5
  56. package/lib/serve/Service-api.js +10 -7
  57. package/lib/serve/Service-dispatch.js +9 -11
  58. package/lib/serve/Service-methods.js +30 -41
  59. package/lib/serve/Transaction.js +10 -7
  60. package/lib/serve/adapters.js +7 -5
  61. package/lib/serve/index.js +24 -12
  62. package/lib/utils/data.js +1 -1
  63. package/lib/utils/index.js +27 -30
  64. package/lib/utils/resources/index.js +101 -0
  65. package/lib/utils/resources/tar.js +71 -0
  66. package/lib/utils/resources/utils.js +11 -0
  67. package/libx/_runtime/audit/Service.js +36 -39
  68. package/libx/_runtime/audit/generic/personal/access.js +3 -4
  69. package/libx/_runtime/audit/generic/personal/modification.js +3 -4
  70. package/libx/_runtime/audit/utils/v2.js +1 -2
  71. package/libx/_runtime/auth/index.js +126 -84
  72. package/libx/_runtime/auth/strategies/JWT.js +12 -19
  73. package/libx/_runtime/auth/strategies/dummy.js +1 -5
  74. package/libx/_runtime/auth/strategies/dwc.js +11 -9
  75. package/libx/_runtime/auth/strategies/mock.js +0 -4
  76. package/libx/_runtime/auth/strategies/{utils/xssec.js → xssecUtils.js} +7 -4
  77. package/libx/_runtime/auth/strategies/xsuaa.js +12 -19
  78. package/libx/_runtime/auth/utils.js +22 -1
  79. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +104 -98
  80. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -2
  81. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
  82. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
  83. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/language.js +2 -8
  84. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -29
  85. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +2 -1
  86. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +3 -2
  87. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +2 -2
  88. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +4 -6
  89. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +24 -21
  90. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +8 -2
  91. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +2 -0
  92. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DispatcherCommand.js +2 -6
  93. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -12
  94. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +33 -9
  95. package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +50 -0
  96. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +2 -2
  97. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +10 -3
  98. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +9 -11
  99. package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +6 -3
  100. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +4 -2
  101. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +1 -1
  102. package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +1 -1
  103. package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +2 -3
  104. package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +6 -4
  105. package/libx/_runtime/cds-services/adapter/rest/utils/result.js +1 -0
  106. package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +8 -5
  107. package/libx/_runtime/cds-services/services/Service.js +40 -0
  108. package/libx/_runtime/cds-services/services/utils/columns.js +4 -3
  109. package/libx/_runtime/cds-services/services/utils/compareJson.js +4 -4
  110. package/libx/_runtime/cds-services/services/utils/differ.js +3 -3
  111. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +4 -4
  112. package/libx/_runtime/cds-services/services/utils/restrictions.js +78 -0
  113. package/libx/_runtime/cds-services/util/assert.js +20 -14
  114. package/libx/_runtime/cds.js +9 -1
  115. package/libx/_runtime/common/aspects/any.js +5 -0
  116. package/libx/_runtime/common/aspects/entity.js +25 -7
  117. package/libx/_runtime/common/aspects/utils.js +2 -2
  118. package/libx/_runtime/common/composition/data.js +6 -0
  119. package/libx/_runtime/common/composition/insert.js +3 -2
  120. package/libx/_runtime/common/composition/tree.js +4 -10
  121. package/libx/_runtime/common/composition/update.js +4 -4
  122. package/libx/_runtime/common/constants/draft.js +29 -26
  123. package/libx/_runtime/common/error/constants.js +2 -2
  124. package/libx/_runtime/common/error/frontend.js +7 -15
  125. package/libx/_runtime/common/generic/auth/capabilities.js +59 -0
  126. package/libx/_runtime/common/generic/auth/constants.js +20 -0
  127. package/libx/_runtime/common/generic/auth/expand.js +54 -0
  128. package/libx/_runtime/common/generic/auth/index.js +32 -0
  129. package/libx/_runtime/common/generic/auth/insertOnly.js +15 -0
  130. package/libx/_runtime/common/generic/auth/readOnly.js +26 -0
  131. package/libx/_runtime/common/generic/auth/requires.js +34 -0
  132. package/libx/_runtime/common/generic/auth/restrict.js +296 -0
  133. package/libx/_runtime/common/generic/auth/utils.js +213 -0
  134. package/libx/_runtime/common/generic/crud.js +8 -6
  135. package/libx/_runtime/common/generic/etag.js +1 -1
  136. package/libx/_runtime/common/generic/input.js +35 -35
  137. package/libx/_runtime/common/generic/sorting.js +2 -3
  138. package/libx/_runtime/common/generic/temporal.js +2 -2
  139. package/libx/_runtime/common/i18n/messages.properties +1 -1
  140. package/libx/_runtime/common/toggles/handler.js +21 -0
  141. package/libx/_runtime/common/utils/copy.js +10 -1
  142. package/libx/_runtime/common/utils/cqn2cqn4sql.js +100 -29
  143. package/libx/_runtime/common/utils/csn.js +63 -1
  144. package/libx/_runtime/common/utils/dollar.js +10 -1
  145. package/libx/_runtime/common/utils/draft.js +46 -7
  146. package/libx/_runtime/common/utils/entityFromCqn.js +13 -9
  147. package/libx/_runtime/common/utils/extensibilityUtils.js +18 -0
  148. package/libx/_runtime/common/utils/foreignKeyPropagations.js +88 -104
  149. package/libx/_runtime/common/utils/generateOnCond.js +4 -1
  150. package/libx/_runtime/common/utils/quotingStyles.js +2 -0
  151. package/libx/_runtime/common/utils/resolveStructured.js +25 -9
  152. package/libx/_runtime/common/utils/resolveView.js +4 -1
  153. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -16
  154. package/libx/_runtime/common/utils/structured.js +33 -37
  155. package/libx/_runtime/common/utils/template.js +17 -8
  156. package/libx/_runtime/common/utils/templateProcessor.js +28 -28
  157. package/libx/_runtime/db/data-conversion/post-processing.js +118 -417
  158. package/libx/_runtime/db/expand/expandCQNToJoin.js +45 -41
  159. package/libx/_runtime/db/expand/rawToExpanded.js +29 -8
  160. package/libx/_runtime/db/generic/index.js +1 -3
  161. package/libx/_runtime/db/generic/input.js +5 -10
  162. package/libx/_runtime/db/generic/rewrite.js +5 -2
  163. package/libx/_runtime/db/generic/structured.js +2 -2
  164. package/libx/_runtime/db/query/delete.js +2 -2
  165. package/libx/_runtime/db/query/insert.js +1 -1
  166. package/libx/_runtime/db/query/update.js +9 -14
  167. package/libx/_runtime/db/sql-builder/CreateBuilder.js +4 -3
  168. package/libx/_runtime/db/sql-builder/InsertBuilder.js +14 -1
  169. package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -2
  170. package/libx/_runtime/db/sql-builder/dataTypes.js +3 -3
  171. package/libx/_runtime/db/utils/columns.js +3 -3
  172. package/libx/_runtime/db/utils/normalizeTimeData.js +2 -2
  173. package/libx/_runtime/db/utils/propagateForeignKeys.js +6 -2
  174. package/libx/_runtime/extensibility/mps/index.js +5 -0
  175. package/libx/_runtime/extensibility/mps/service.js +111 -0
  176. package/libx/_runtime/extensibility/mps/tar.js +42 -0
  177. package/libx/_runtime/extensibility/mps/utils.js +11 -0
  178. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformREAD.js +0 -0
  179. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformRESULT.js +17 -5
  180. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformWRITE.js +1 -0
  181. package/libx/_runtime/extensibility/uiflex/index.js +54 -0
  182. package/libx/_runtime/extensibility/uiflex/service.js +276 -0
  183. package/libx/_runtime/{fiori → extensibility}/uiflex/utils.js +22 -7
  184. package/libx/_runtime/fiori/generic/activate.js +2 -2
  185. package/libx/_runtime/fiori/generic/before.js +4 -4
  186. package/libx/_runtime/fiori/generic/new.js +3 -3
  187. package/libx/_runtime/fiori/generic/patch.js +1 -1
  188. package/libx/_runtime/fiori/generic/read.js +58 -66
  189. package/libx/_runtime/fiori/generic/readOverDraft.js +71 -16
  190. package/libx/_runtime/fiori/utils/handler.js +6 -13
  191. package/libx/_runtime/fiori/utils/where.js +6 -5
  192. package/libx/_runtime/hana/Service.js +4 -10
  193. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
  194. package/libx/_runtime/hana/driver.js +2 -2
  195. package/libx/_runtime/hana/execute.js +27 -74
  196. package/libx/_runtime/hana/pool.js +1 -1
  197. package/libx/_runtime/hana/streaming.js +2 -1
  198. package/libx/_runtime/index.js +6 -6
  199. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +5 -21
  200. package/libx/_runtime/messaging/Outbox.js +2 -2
  201. package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -14
  202. package/libx/_runtime/messaging/common-utils/connections.js +5 -7
  203. package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +30 -0
  204. package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -1
  205. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +36 -30
  206. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -12
  207. package/libx/_runtime/messaging/enterprise-messaging.js +8 -8
  208. package/libx/_runtime/messaging/file-based.js +5 -5
  209. package/libx/_runtime/messaging/message-queuing.js +14 -12
  210. package/libx/_runtime/messaging/outbox/utils.js +18 -19
  211. package/libx/_runtime/messaging/redis-messaging.js +91 -0
  212. package/libx/_runtime/messaging/service.js +8 -6
  213. package/libx/_runtime/remote/Service.js +44 -8
  214. package/libx/_runtime/remote/utils/client.js +20 -13
  215. package/libx/_runtime/remote/utils/data.js +11 -11
  216. package/libx/_runtime/sqlite/Service.js +6 -9
  217. package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +5 -2
  218. package/libx/_runtime/types/api.js +10 -2
  219. package/libx/common/utils/ucsn.js +109 -0
  220. package/libx/gql/resolvers/crud/update.js +5 -0
  221. package/libx/gql/resolvers/parse/ast2cqn/columns.js +3 -1
  222. package/libx/gql/schema/typeDefMap.js +2 -2
  223. package/libx/odata/afterburner.js +110 -16
  224. package/libx/odata/grammar.pegjs +9 -1
  225. package/libx/odata/parseToCqn.js +39 -0
  226. package/libx/odata/parser.js +1 -1
  227. package/libx/rest/RestAdapter.js +9 -1
  228. package/libx/rest/middleware/input.js +54 -0
  229. package/libx/rest/middleware/operation.js +14 -1
  230. package/libx/rest/middleware/parse.js +11 -7
  231. package/package.json +1 -1
  232. package/server.js +34 -19
  233. package/srv/audit-log.cds +2 -2
  234. package/srv/flex.cds +8 -2
  235. package/srv/flex.js +1 -1
  236. package/srv/mps.cds +23 -0
  237. package/srv/mps.js +1 -0
  238. package/libx/_runtime/auth/strategies/utils/uaa.js +0 -21
  239. package/libx/_runtime/common/generic/auth.js +0 -874
  240. package/libx/_runtime/common/toggles/alpha.js +0 -43
  241. package/libx/_runtime/db/generic/arrayed.js +0 -33
  242. package/libx/_runtime/fiori/uiflex/index.js +0 -35
  243. package/libx/_runtime/fiori/uiflex/service.js +0 -150
  244. package/libx/rest/utils/data.js +0 -60
package/bin/cds.js CHANGED
@@ -13,19 +13,22 @@ const cli = { //NOSONAR
13
13
  }
14
14
  require('util').inspect.defaultOptions = { colors: !!process.stderr.isTTY, depth:11 }
15
15
  if (!argv.length) argv = process.argv.slice(3)
16
- if (cmd in this.Shortcuts) cmd = process.argv[2] = this.Shortcuts[cmd]
17
16
  if (process.env.NODE_ENV !== 'test') this.errorHandlers()
18
- const task = this.load(cmd)
19
- if (!task) return _requires_cdsdk (cmd)
20
- return task.apply (this, this.args(task,argv))
17
+ if (cmd in this.Shortcuts) cmd = process.argv[2] = this.Shortcuts[cmd]
18
+ let task = this.load ('./'+cmd)
19
+ if (task) return task.apply (this, this.args(task,argv))
20
+
21
+ // delegate to cds-dk for rest of commands (usually shortcuts like `cds c`)
22
+ const dk = _requireDk('cds')
23
+ return dk ? dk.exec(cmd, ...argv) : _die_needsDk (cmd)
21
24
  },
22
25
 
23
26
  load (cmd) {
24
- return _require ('./'+cmd)
25
- || _require ('@sap/cds-dk/bin/'+cmd) // if dk is in installed modules
26
- || _require (_npmGlobalModules()+'/@sap/cds-dk/bin/'+cmd) // needed for running cds in npm scripts
27
+ return _require ('./'+cmd) || _requireDk (cmd)
27
28
  },
28
29
 
30
+ help (cmd) { return this.exec ('help', cmd) },
31
+
29
32
  args (task, argv) {
30
33
 
31
34
  const { options:o=[], flags:f=[], shortcuts:s=[] } = task
@@ -62,10 +65,6 @@ const cli = { //NOSONAR
62
65
  const _exit = (c) => { console.log(); process.exit(c) }
63
66
  cds.repl || process.on ('unhandledRejection', _error)
64
67
  cds.repl || process.on ('uncaughtException', _error)
65
- process.on ('SIGTERM',_exit)
66
- process.on ('SIGHUP',_exit)
67
- process.on ('SIGINT',_exit)
68
- process.on ('SIGUSR2',_exit) // by nodemon
69
68
  },
70
69
 
71
70
  get log() { return this.log = require('./utils/log') }
@@ -76,7 +75,13 @@ const _require = (id,o) => {
76
75
  return require (resolved)
77
76
  }
78
77
 
79
- const _requires_cdsdk = (cmd) => {
78
+ const _requireDk = (cmd) => {
79
+ const { npmGlobalModules } = require('./utils/modules')
80
+ return _require ('@sap/cds-dk/bin/'+cmd) // if dk is in installed modules
81
+ || _require (npmGlobalModules()+'/@sap/cds-dk/bin/'+cmd) // needed for running cds in npm scripts
82
+ }
83
+
84
+ const _die_needsDk = (cmd) => {
80
85
  const dk = {add:1,build:1,compile:1,deploy:1,env:1,eval:1,help:1,import:1,init:1,repl:1,watch:1}
81
86
  let message
82
87
  if (!cmd) { message = `
@@ -95,12 +100,6 @@ const _requires_cdsdk = (cmd) => {
95
100
  return console.error (message)
96
101
  }
97
102
 
98
- const _npmGlobalModules = () => {
99
- try {
100
- return require ('child_process').execSync('npm root -g').toString().trim()
101
- } catch (err) { return }
102
- }
103
-
104
103
  module.exports = Object.assign ((..._) => cli.exec(..._), cli)
105
104
  if (!module.parent) cli.exec()
106
105
  /* eslint no-console:off */
@@ -26,7 +26,10 @@ class CfUtil {
26
26
 
27
27
  async _cfRun(...args) {
28
28
  const cmdLine = `${CF_COMMAND} ${args.join(' ')}`;
29
- DEBUG && console.time(cmdLine);
29
+ if (DEBUG) {
30
+ console.time(cmdLine);
31
+ LOG.debug('>>> ' + cmdLine);
32
+ }
30
33
 
31
34
  try {
32
35
  return await new Promise((resolve, reject) => {
@@ -43,6 +46,7 @@ class CfUtil {
43
46
  });
44
47
 
45
48
  child.on('error', (err) => {
49
+ DEBUG && LOG.debug(`${stdout}\n${stderr}`);
46
50
  if (err.code === 'ENOENT') {
47
51
  reject(new Error(`Command ${bold(CF_COMMAND)} not found. Make sure to install the Cloud Foundry Command Line Interface.`));
48
52
  } else {
@@ -51,6 +55,7 @@ class CfUtil {
51
55
  });
52
56
 
53
57
  child.on('close', (code) => {
58
+ DEBUG && LOG.debug(`${stdout}\n${stderr}`);
54
59
  if (!code) {
55
60
  resolve(stdout.trim());
56
61
  } else {
@@ -87,36 +92,28 @@ class CfUtil {
87
92
  return result;
88
93
  }
89
94
 
90
- _extract(string, pattern, defaultValue) {
91
- const array = string.split(/[\n\r]+/);
92
- for (let line of array) {
93
- const match = line.match(pattern);
94
- if (match) {
95
- return match[1];
96
- }
97
- }
98
-
99
- if (typeof defaultValue === 'undefined') {
100
- throw Error(`Pattern not found: ${pattern}`);
101
- } else {
102
- return defaultValue;
95
+ _extract(string, pattern, errorMsg) {
96
+ const match = string.match(pattern);
97
+ if (!match || !match[1]) {
98
+ throw new Error(errorMsg);
103
99
  }
100
+ return match[1];
104
101
  }
105
102
 
106
103
  async getCfTargetFromCli() {
107
104
  const result = await this._cfRun('target');
108
105
 
109
106
  return {
110
- apiEndpoint: this._extract(result, /api endpoint:\s+(.*)$/i),
111
- user: this._extract(result, /user:\s+(.*)$/i),
112
- org: this._extract(result, /org:\s+(.*)$/i),
113
- space: this._extract(result, /space:\s+(.*)$/i),
107
+ apiEndpoint: this._extract(result, /api endpoint\s*:\s*(.*)/i, `CF API endpoint is missing. Use 'cf login' to login.`),
108
+ user: this._extract(result, /user\s*:\s*(.*)/i, `CF user is missing. Use 'cf login' to login.`),
109
+ org: this._extract(result, /org\s*:\s*(.*)/i, `CF org is missing. Use 'cf target -o <ORG> to specify.`),
110
+ space: this._extract(result, /space\s*:\s*(.*)/i, `CF space is missing. Use 'cf target -s <SPACE>' to specify.`),
114
111
  };
115
112
  }
116
113
 
117
114
  async getCfSpaceInfo() {
118
115
  if (!this.spaceInfo) {
119
- LOG.debug('getting space info');
116
+ DEBUG && LOG.debug('getting space info');
120
117
 
121
118
  const target = await this.getCfTargetFromCli();
122
119
 
@@ -36,7 +36,7 @@ class HanaDeployer {
36
36
 
37
37
  this.logger.log(`${bold('Starting deploy to SAP HANA ...')}`);
38
38
  if (bindCallback) {
39
- this.logger.log('Using advanced mode');
39
+ this.logger.log('Using cds bind');
40
40
  }
41
41
  this.logger.log();
42
42
 
@@ -181,7 +181,10 @@ class HanaDeployer {
181
181
  async _build(buildTaskOptions, model) {
182
182
  buildTaskOptions = buildTaskOptions || {
183
183
  root: process.env._TEST_CWD || process.cwd(),
184
- cli: true
184
+ cli: true,
185
+ cmdOptions: {
186
+ for: buildConstants.BUILD_TASK_HANA
187
+ }
185
188
  };
186
189
 
187
190
  if (typeof model === 'string') {
@@ -190,31 +193,11 @@ class HanaDeployer {
190
193
 
191
194
  this.logger.log(`Creating build tasks`);
192
195
  const buildTaskFactory = new BuildTaskFactory(null, cds);
193
- const allTasks = await buildTaskFactory.getTasks(buildTaskOptions);
194
-
195
- const hanaTasks = allTasks.filter((task => {
196
- return task.for === buildConstants.BUILD_TASK_HANA && (!model || model.includes(task.src));
197
- }));
198
-
199
- let srcFolder = cds.env.folders.db || 'db';
200
- if (Array.isArray(srcFolder)) {
201
- srcFolder = srcFolder[0] || 'db';
202
- }
203
-
204
- if (hanaTasks.length === 0) {
205
- hanaTasks.push({
206
- for: buildConstants.BUILD_TASK_HANA,
207
- src: srcFolder,
208
- options: {
209
- model: cds.env.requires.db && cds.env.requires.db.model || cds.resolve('*', false)
210
- }
211
- });
212
- }
213
-
196
+ const hanaTasks = await buildTaskFactory.getTasks(buildTaskOptions);
214
197
  this.logger.log(`Running build`);
215
198
 
216
199
  const buildResults = await new BuildTaskEngine().processTasks(hanaTasks, buildTaskOptions);
217
- return { buildResults, allTasks }
200
+ return { buildResults, hanaTasks }
218
201
  }
219
202
 
220
203
 
@@ -16,6 +16,10 @@ class HdiDeployUtil {
16
16
  this.deployerVersionSpec = '^4'
17
17
  }
18
18
 
19
+ async deployTenant(dbDir, env, logger) {
20
+ await this._executeDeploy(dbDir, env, logger);
21
+ }
22
+
19
23
  async deploy(dbDir, vcapServices, options = {}) {
20
24
  LOG.log();
21
25
  LOG.log(`Deploying to HANA from ${dbDir}`);
@@ -85,18 +89,18 @@ Add it either as a devDependency using 'npm install -D ${this.deployerName}' or
85
89
  async _npmSearchPaths(cwd) {
86
90
  const npmRootCall = await execAsync('npm root -g');
87
91
  const globalNodeModules = npmRootCall.stdout.toString().trim();
88
- return [cwd, globalNodeModules]
92
+ return [cwd, globalNodeModules, '@sap/hdi-deploy']
89
93
  }
90
94
 
91
95
 
92
- async _executeDeploy(dbDir, env) {
96
+ async _executeDeploy(dbDir, env, logger) {
93
97
  const hdiDeployLib = await this._getHdiDeployLib(dbDir);
94
98
  return new Promise((resolve, reject) => {
95
99
  const callbacks = {
96
- stderrCB: error => LOG.error(error.toString())
100
+ stderrCB: error => (logger || LOG).error(error.toString())
97
101
  }
98
102
  if (LOG.level !== SILENT) {
99
- callbacks.stdoutCB = (data) => console.log(data.toString());
103
+ callbacks.stdoutCB = (data) => (logger || LOG).log(data.toString());
100
104
  }
101
105
 
102
106
  hdiDeployLib.deploy(dbDir, env, (error, response) => {
package/bin/mtx/in-cds.js CHANGED
@@ -1,9 +1,9 @@
1
1
  const cds = require('../build/cds')
2
- if (cds.requires.multitenancy) try {
2
+ if (cds.requires.multitenancy && !cds.env.features.streamlined_mtx) try {
3
3
  const mtx = module.exports = require ('@sap/cds-mtx')()
4
4
  mtx.inject (cds)
5
5
  cds.on('served', () => cds.emit('mtx'))
6
- } catch(e) {
6
+ } catch(e) {
7
7
  if (e.code === 'MODULE_NOT_FOUND') throw new Error('Error serving MTX APIs: @sap/cds-mtx is not installed')
8
8
  else throw e
9
9
  }
package/bin/serve.js CHANGED
@@ -9,7 +9,7 @@ module.exports = Object.assign ( serve, {
9
9
  '--mocked', '--with-mocks', '--with-bindings',
10
10
  '--watch',
11
11
  ],
12
- shortcuts: [ '-s', undefined, '-2', '-a', '-w', '-p' ],
12
+ shortcuts: [ '-s', undefined, '-2', '-a', '-w', undefined, '-p' ],
13
13
  help: `
14
14
  # SYNOPSIS
15
15
 
@@ -183,6 +183,13 @@ async function serve (all=[], o={}) { // NOSONAR
183
183
  }
184
184
  server.listening ? _started(server) : server.once('listening',_started)
185
185
  server.on ('error',_reject) // startup errors like EADDRINUSE
186
+
187
+ // graceful server shutdown
188
+ const close = () => server.close()
189
+ process.once('SIGTERM', close)
190
+ process.once('SIGINT', close)
191
+ process.once('SIGHUP', close)
192
+ process.once('SIGUSR2', close) // by nodemon
186
193
  return server
187
194
  })
188
195
  }
@@ -216,8 +223,8 @@ function _prepare_logging () { // NOSONAR
216
223
  })
217
224
 
218
225
  // print information about each connected service
219
- cds.on ('connect', ({name,kind,options:{use,credentials}})=>{
220
- log (`connect to ${name} > ${use||kind}`, credentials ? _redacted(credentials) : '')
226
+ cds.on ('connect', ({name,kind,options:{use,credentials,impl}})=>{
227
+ log (`connect to ${name} > ${use||kind||impl}`, credentials ? _redacted(credentials) : '')
221
228
  })
222
229
 
223
230
  // print information about each provided service
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ npmGlobalModules: function() {
3
+ try {
4
+ return require ('child_process').execSync('npm root -g').toString().trim()
5
+ } catch (err) { return }
6
+ }
7
+ }
package/bin/version.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable no-console */
2
2
  const { dirname, join, resolve } = require ('path')
3
+ const { cwd } = require('process')
3
4
  module.exports = Object.assign(list_versions, {
4
5
  flags: [ '--info', '--markdown', '--all', '--npm-list', '--npm-tree' ],
5
6
  shortcuts: [ '-i', '-m','-a', '-ls', '-ll' ],
@@ -31,6 +32,8 @@ module.exports = Object.assign(list_versions, {
31
32
 
32
33
  `})
33
34
 
35
+ const MISSING = '-- missing --'
36
+
34
37
  function list_versions(args, options) { //NOSONAR
35
38
  if (options['npm-list'] || options['npm-tree']) {
36
39
  let [pattern] = args, re = pattern ? RegExp(pattern) : /@sap\/cd[rs]|@sap\/eslint-plugin-cds/
@@ -51,13 +54,16 @@ function list_versions(args, options) { //NOSONAR
51
54
  }
52
55
 
53
56
  function info(o) {
57
+ const { npmGlobalModules } = require('./utils/modules');
54
58
  const main = _findPackage (require.main.filename)
55
59
  return {
56
60
  ..._versions4(main, {}, true), // usually sap/cds-dk or sap/cds
57
61
  ..._versions4('@sap/cds-dk', {}, null, o), // make sure cds-dk is there, cds-maven-plugin uses it
62
+ ..._versions4('@sap/cds-dk', {}, null, {...o, label: '@sap/cds-dk (global)', pkg: join(npmGlobalModules(), '@sap/cds-dk')}),
58
63
  ..._versions4('@sap/eslint-plugin-cds', {}, null, o),
59
64
  ..._versions4(process.cwd(), {}, null, o),
60
65
  ..._versions4('..', {}, null, o),
66
+ ..._findMTX(),
61
67
  'Node.js': process.version,
62
68
  'home': __dirname.slice(0,-4)
63
69
  }
@@ -66,13 +72,21 @@ function info(o) {
66
72
  function _versions4 (pkg_name, info, parent, o={}) {
67
73
  if (!pkg_name) return info
68
74
  try {
69
- const pkg = require(join(pkg_name, 'package.json'))
70
- info[pkg.name] = pkg.version
75
+ let path = join(o.pkg || pkg_name, 'package.json')
76
+ if(o.here) {
77
+ // path.join(['./', x]) is immediately resolved to x.
78
+ // Calling require() on that will then follow the standard (global) module resolution strategy.
79
+ // If we want to look into a directory relative to CWD,
80
+ // turning it into a global path is the most convenient way.
81
+ path = join(cwd(), path)
82
+ }
83
+ const pkg = require(path)
84
+ info[o.label || pkg.name] = pkg.version
71
85
  if (!parent || o.all) for (let d in pkg.dependencies) { // recurse sap packages in dependencies...
72
86
  if (!(d in info) && d.startsWith('@sap/')) _versions4(d, info, pkg.name, o)
73
87
  }
74
88
  } catch (e) {
75
- if (e.code !== 'MODULE_NOT_FOUND') info[pkg_name] = '-- missing --' // unknown error
89
+ if (e.code !== 'MODULE_NOT_FOUND') info[pkg_name] = MISSING // unknown error
76
90
  // require fails for indirect packages if node_modules layout is nested, e.g. on Windows.
77
91
  // Try one more time with nested node_modules dir.
78
92
  else if (parent) _versions4(parent + '/node_modules/' + pkg_name, info)
@@ -117,3 +131,42 @@ function _findPackage (dir) {
117
131
  return _findPackage (dirname (dir))
118
132
  }
119
133
  }
134
+
135
+ function _findMTX() {
136
+ // looks for any occurrence of cds-mtx.
137
+ // In node projects, cds-mtx can be resolved via _versions4 like all the other SAP modules
138
+ // In Java-flavoured projects cds-mtx may be deployed through a separate node project
139
+ // with just sidecar in it. So we can not rely on the global require() resolution strategy
140
+ // and will as a fallback...
141
+ // (1) ...look for an MTX project within cds.env
142
+ // (2) ...look within a few preselected subdirectories which often contain MTX projects
143
+ const cds = require('../lib')
144
+ const cdsmtx = '@sap/cds-mtx'
145
+ let res = _versions4 (cdsmtx, {}, null)
146
+
147
+ if (res[cdsmtx] === undefined) {
148
+ // not resolvable -> look in cds.env
149
+ if ('build' in cds.env && 'tasks' in cds.env.build) {
150
+ let i = 0
151
+ while (res[cdsmtx] === undefined && i < cds.env.build.tasks.length) {
152
+ const task = cds.env.build.tasks[i]
153
+ if ('for' in task && task.for === 'mtx' && 'dest' in task) {
154
+ res = _versions4 (join(task.dest, 'node_modules', cdsmtx), {}, null, {here: true})
155
+ }
156
+ i++
157
+ }
158
+ }
159
+
160
+ // mtx still not found via cds.env? Try looking in well-known subdirectories
161
+ const folders = cds.env.folders
162
+ ? [cds.env.folders.db, cds.env.folders.srv].filter(d => d)
163
+ : []
164
+ let i = 0
165
+ while(res[cdsmtx] === undefined && i < folders.length) {
166
+ res = _versions4 (join(folders[i], 'node_modules', cdsmtx), {}, null, {here: true})
167
+ i++
168
+ }
169
+ res[cdsmtx] = res[cdsmtx] || MISSING
170
+ }
171
+ return res
172
+ }
@@ -1,4 +1,5 @@
1
- const {cdsc,odata,sql,hana,features} = require ('../index').env
1
+ const cds = require ('../index')
2
+ const {cdsc,odata,sql,features} = cds.env
2
3
  const constraints = {
3
4
  assertIntegrity: features.assert_integrity,
4
5
  assertIntegrityType: features.assert_integrity_type
@@ -75,7 +76,11 @@ const _options = {for: Object.assign (_options4, {
75
76
  },
76
77
 
77
78
  hana(o) {
78
- let cdsc = this.sql (o,hana)
79
+ let cdsc = this.sql (o, cds.env.hana) // returns clone
80
+ cdsc.sqlChangeMode = cdsc.journal && cdsc.journal['change-mode']
81
+ cdsc.disableHanaComments = !cdsc.comments
82
+ delete cdsc.journal // cleanup avoiding side effects
83
+ delete cdsc.comments
79
84
  return cdsc
80
85
  },
81
86
 
@@ -100,7 +105,25 @@ const _options = {for: Object.assign (_options4, {
100
105
  */
101
106
  module.exports = exports = {__proto__:compile, _options,
102
107
  for: {__proto__: compile.for,
103
- odata: (csn,o) => compile.for.odata (csn, _options.for.odata(o)),
108
+ odata: (csn,o) => {
109
+ if (features.ucsn) {
110
+ const { cloneCsn } = require('@sap/cds-compiler/lib/model/csnUtils') // REVISIT: This should be done by the compiler
111
+ if (compile.version() >= "2.12.1") {
112
+ const generateDrafts = require('@sap/cds-compiler/lib/transform/draft/odata')
113
+ const compiled = generateDrafts(cloneCsn(csn, {}), { messages: [] })
114
+ compiled.meta._4odata = true
115
+ return compiled
116
+ } else {
117
+ // not yet in compiler branch, can't add drafts
118
+ const cloned = cloneCsn(csn, {})
119
+ cloned.meta._4odata = true
120
+ return cloned
121
+ }
122
+ }
123
+ const compiled = compile.for.odata (csn, _options.for.odata(o))
124
+ compiled.meta._4odata = true
125
+ return compiled
126
+ },
104
127
  },
105
128
  to: {__proto__: compile.to,
106
129
  edmx: Object.assign ((csn,o) => compile.to.edmx (csn, _options.for.edm(o)), {
@@ -5,10 +5,11 @@ const _locales_4sql = {
5
5
  plain : env.i18n.for_sql || [],
6
6
  }
7
7
 
8
- // FIXME: we reliably need to now if we'll be on sqlite even before the connect happened
9
- const _on_sqlite = (env.requires.db || env.requires.sql).dialect === 'sqlite'
10
8
  const { _texts_entries, _localized_entries } = env.cdsc.cv2 || {}
11
9
  const _been_here = Symbol('is _localized')
10
+ const _conf = env.requires.db || env.requires.sql
11
+ const _on_sqlite = _conf.kind === 'sqlite' || _conf.dialect === 'sqlite'
12
+ //> FIXME: we reliably need to now if we'll be on sqlite even before the connect happened
12
13
 
13
14
 
14
15
 
@@ -18,11 +19,11 @@ const _been_here = Symbol('is _localized')
18
19
  */
19
20
  function unfold_ddl (ddl, csn, o={}) { // NOSONAR
20
21
  const _locales = _locales_4sql[o.dialect]; if (!_locales) return ddl
21
- const localized_views = ddl.filter (each => each.startsWith ('CREATE VIEW localized_'))
22
- for (let localized_view of localized_views) {
23
- for (let locale of _locales) ddl.push (localized_view
22
+ const localized_views = ddl.filter (each => each.startsWith('CREATE VIEW localized_'))
23
+ for (const localized_view of localized_views) {
24
+ for (const locale of _locales) ddl.push (localized_view
24
25
  .replace (/localized_/g, `localized_${locale}_`)
25
- .replace (/\.locale = 'en'/, `.locale = '${locale}'`)
26
+ .replace (/\.locale = 'en'/g, `.locale = '${locale}'`)
26
27
  )
27
28
  }
28
29
  DEBUG && localized_views.length && DEBUG ('Added localized views to DDL for', csn.$sources)
@@ -48,33 +49,31 @@ function unfold_csn (m) { // NOSONAR
48
49
  const _locales = _on_sqlite && _locales_4sql.sqlite
49
50
 
50
51
  // Pass 1 - add localized.<locale> entities and views
51
- for (let each in cds.linked(m).definitions) {
52
+ for (const each in cds.linked(m).definitions) {
52
53
  const d = m.definitions [each]
53
54
  // Add <entry>_texts proxies for all <entry>.texts entities
54
55
  if (_texts_entries !== false && each.endsWith('.texts')) {
55
56
  _add_proxy4 (d, each.slice(0,-6)+'_texts')
56
57
  }
57
- // Add localized.<entry> for all entities marked as .$localized
58
- if (_localized_entries !== false && d.own('$localized')) {
59
- let x = _add_proxy4 (d,`localized.${each}`)
60
- if (x) pass2.push ([x])
58
+ // Add localized.<entry> for all entities having localized views in db
59
+ if (_localized_entries !== false && _is_localized(d)) {
60
+ _add_proxy4 (d,`localized.${each}`, x => pass2.push([x]))
61
61
  // if running on sqlite add additional localized.<locale>. views
62
- if (_locales) for (let locale of _locales) {
63
- let x = _add_proxy4 (d,`localized.${locale}.${each}`)
64
- if (x) pass2.push ([x,locale])
62
+ if (_locales) for (const locale of _locales) {
63
+ _add_proxy4 (d,`localized.${locale}.${each}`, x => pass2.push([x,locale]))
65
64
  }
66
65
  }
67
66
  }
68
67
 
69
68
  // Pass 2 - redirect associations/compositions in elements to localized.<locale> targets
70
- for (let [x,locale] of pass2) {
69
+ for (const [x,locale] of pass2) {
71
70
  let overlayed = null
72
- for (let each in x.elements) {
73
- let e = x.elements [each]
74
- if (e._target && e._target.$localized) {
75
- let elements = overlayed || (overlayed = x.elements = {__proto__:x.elements})
76
- let target = locale ? `localized.${locale}.${e.target}` : `localized.${e.target}`
77
- let _target = m.definitions[target]
71
+ for (const each in x.elements) {
72
+ const e = x.elements [each]
73
+ if (e._target && _is_localized(e._target)) {
74
+ const elements = overlayed || (overlayed = x.elements = {__proto__:x.elements})
75
+ const target = locale ? `localized.${locale}.${e.target}` : `localized.${e.target}`
76
+ const _target = m.definitions[target]
78
77
  if (_target) {
79
78
  elements[each] = Object.defineProperty ({__proto__:e,target},'_target',{value:_target})
80
79
  DEBUG && DEBUG ('overriding:', each, ':', elements[each], 'in', { entity: x.name })
@@ -88,12 +87,24 @@ function unfold_csn (m) { // NOSONAR
88
87
  DEBUG && pass2.length && DEBUG ('Added localized views for sqlite to csn for', m.$sources)
89
88
  return Object.defineProperty (m, _been_here, {value:true})
90
89
 
91
- function _add_proxy4 (d, name) {
90
+ function _add_proxy4 (d, name, callback) {
92
91
  if (name in m.definitions) return DEBUG && DEBUG ('NOT overriding existing:', name)
93
- let x = {__proto__:d, name }
94
- DEBUG && DEBUG ('adding proxy:', x)
92
+ const x = {__proto__:d, name }; DEBUG && DEBUG ('adding proxy:', x)
95
93
  Object.defineProperty (m.definitions, name, {value:x,writable:true,configurable:true})
96
- return x
94
+ if (callback) callback(x)
95
+ }
96
+ }
97
+
98
+
99
+ const $localized = '$$localized', _is_localized = (d,_path) => {
100
+ if (d.own($localized)) return true
101
+ if (!d.elements || d.name.endsWith('.texts')) return false
102
+ // if (d.elements.texts && d.elements.texts.target === `${d.name}.texts`) return d.set($localized,true)
103
+ for (let each in d.elements) {
104
+ const e = d.elements [each]
105
+ if (e.localized || e._target && !(_path && e._target.name in _path) && _is_localized(e._target,{..._path, [d.name]:1 })) {
106
+ return d.set($localized,true)
107
+ }
97
108
  }
98
109
  }
99
110
 
@@ -17,14 +17,14 @@ function parse (csv) {
17
17
  for (let line of lines) {
18
18
  if (!rows.length && _ignoreLine (line)) continue
19
19
  if (!sep) [sep] = SEPARATOR.exec(line)||[';']
20
- const values=[]; let val, currCol=0, c, inString=false
20
+ const values=[]; let val, currCol=0, c, inString=false, quoted=false
21
21
  for (let i=0; i<line.length; ) {
22
22
  c = line[i++]
23
23
  if (c === sep && !inString) { // separator
24
24
  currCol++
25
25
  if (!rows.length && val !== undefined) headers.push (currCol) // skip column if header value is empty
26
- if (headers.includes(currCol)) values.push (_value4(val)) // skip value if column was skipped
27
- val = undefined //> start new val
26
+ if (headers.includes(currCol)) values.push (_value4(val, quoted)) // skip value if column was skipped
27
+ val = undefined, quoted = false //> start new val
28
28
  }
29
29
  else if (c === '"' && val === undefined) { // start quoted string
30
30
  val = ''
@@ -32,7 +32,7 @@ function parse (csv) {
32
32
  }
33
33
  else if (c === '"' && inString) { // within quoted string
34
34
  if (line[i] === '"') val += line[i++] // escape quote: "" > "
35
- else inString = false // stop string
35
+ else inString = false, quoted = true // stop string
36
36
  }
37
37
  else { // normal char
38
38
  if (val === undefined) val = ''
@@ -42,16 +42,16 @@ function parse (csv) {
42
42
  // remaining value
43
43
  currCol++
44
44
  if (!rows.length && val !== undefined) headers.push(currCol) // skip column if header value is empty
45
- if ((val !== undefined || c === sep) && headers.includes(currCol)) values.push (_value4(val))
45
+ if ((val !== undefined || c === sep) && headers.includes(currCol)) values.push (_value4(val, quoted))
46
46
  if (values.length > 0) rows.push (values)
47
47
  }
48
48
  return rows
49
49
  }
50
50
 
51
- function _value4 (val) { //NOSONAR
51
+ function _value4 (val, quoted = false) { //NOSONAR
52
52
  if (val) val = val.trim()
53
- if (val === 'true') return true
54
- if (val === 'false') return false
53
+ if (!quoted && val === 'true') return true
54
+ if (!quoted && val === 'false') return false
55
55
  else return val
56
56
  }
57
57
 
@@ -0,0 +1,9 @@
1
+ const cds = require ('../../index')
2
+ module.exports = function cds_compile_for_drafts (csn,o) {
3
+ if (!cds.env.features._ucsn_) return cds.compile.for.odata (csn,o)
4
+ const unfold = cds_compile_for_drafts.unfold || (
5
+ cds_compile_for_drafts.unfold = require ('@sap/cds-compiler/lib/transform/draft/odata')
6
+ )
7
+ // csn = JSON.parse (JSON.stringify (csn)) // REVISIT: workaround for bad test setup
8
+ return unfold (csn,o||{})
9
+ }
@@ -0,0 +1,16 @@
1
+ const cds = require ('../../index')
2
+ const _cached = Symbol('for Java')
3
+
4
+ module.exports = function cds_compile_for_java (csn,o) {
5
+ if (!csn) return
6
+ const cached = csn[_cached]; if (cached) return cached
7
+ csn = cds.minify (csn)
8
+ csn = cds.compile.for.drafts (csn,o)
9
+ // Add a parsed _where clause for @restrict.{grant,where} annotations
10
+ if (csn.definitions) for (let {'@restrict':rr} of Object.values(csn.definitions)) if (rr) {
11
+ for (let r of rr) if (r.grant && r.where) try {
12
+ r._where = JSON.stringify (cds.parse.xpr(r.where))
13
+ } catch(e){/* ignored */}
14
+ }
15
+ return csn[_cached] = csn
16
+ }
@@ -0,0 +1,12 @@
1
+ const cds = require ('../../index')
2
+ const _cached = Symbol('for Node.js')
3
+
4
+ module.exports = function cds_compile_for_nodejs (csn,o) {
5
+ if (!csn) return
6
+ const cached = csn[_cached]; if (cached) return cached
7
+ csn = cds.minify (csn)
8
+ csn = cds.compile.for.drafts (csn,o) //> creates a partial copy -> avoid any cds.linked() before
9
+ csn = cds.compile._localized.unfold_csn (csn)
10
+ csn = cds.linked (csn)
11
+ return csn[_cached] = csn
12
+ }
@@ -13,4 +13,4 @@ module.exports = function cds_compile_for_odata (csn,_o) {
13
13
  return _4odata
14
14
  }
15
15
 
16
- const _is_odata = csn => csn.meta && csn.meta.transformation === 'odata'
16
+ const _is_odata = csn => csn.meta && csn.meta._4odata
@@ -9,6 +9,9 @@ const {lazified} = require ('../lazy'); require = lazified (module) // eslint-d
9
9
  const compile = module.exports = Object.assign (cds_compile, {
10
10
 
11
11
  for: lazified ({
12
+ java: require('./for/java'),
13
+ nodejs: require('./for/nodejs'),
14
+ drafts: require('./for/drafts'),
12
15
  odata: require('./for/odata'),
13
16
  sql: require('./for/sql'),
14
17
  }),