@sap/cds 5.8.4 → 5.9.2

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 (248) hide show
  1. package/CHANGELOG.md +198 -77
  2. package/app/fiori/preview.js +16 -11
  3. package/app/fiori/routes.js +15 -8
  4. package/app/index.js +1 -1
  5. package/bin/build/buildTaskFactory.js +3 -3
  6. package/bin/build/buildTaskProviderFactory.js +1 -1
  7. package/bin/build/constants.js +1 -1
  8. package/bin/build/provider/buildTaskHandlerEdmx.js +12 -7
  9. package/bin/build/provider/buildTaskHandlerInternal.js +1 -1
  10. package/bin/build/provider/buildTaskProviderInternal.js +8 -2
  11. package/bin/build/provider/hana/2migration.js +27 -24
  12. package/bin/build/provider/hana/index.js +17 -18
  13. package/bin/build/provider/hana/migrationtable.js +9 -10
  14. package/bin/build/provider/java-cf/index.js +4 -5
  15. package/bin/build/provider/node-cf/index.js +99 -6
  16. package/bin/cds.js +17 -18
  17. package/bin/deploy/to-hana/cfUtil.js +16 -19
  18. package/bin/deploy/to-hana/hana.js +7 -24
  19. package/bin/deploy/to-hana/hdiDeployUtil.js +8 -4
  20. package/bin/mtx/in-cds.js +2 -2
  21. package/bin/serve.js +10 -3
  22. package/bin/utils/modules.js +7 -0
  23. package/bin/version.js +56 -3
  24. package/lib/compile/cdsc.js +7 -2
  25. package/lib/compile/etc/_localized.js +37 -25
  26. package/lib/compile/etc/csv.js +8 -8
  27. package/lib/compile/for/drafts.js +9 -0
  28. package/lib/compile/for/java.js +16 -0
  29. package/lib/compile/for/nodejs.js +12 -0
  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/bindings.js +1 -1
  38. package/lib/connect/index.js +3 -4
  39. package/lib/core/entities.js +15 -14
  40. package/lib/core/index.js +39 -36
  41. package/lib/core/reflect.js +4 -2
  42. package/lib/deploy.js +114 -127
  43. package/lib/env/defaults.js +1 -0
  44. package/lib/env/index.js +165 -165
  45. package/lib/env/presets.js +1 -0
  46. package/lib/env/requires.js +121 -50
  47. package/lib/index.js +2 -0
  48. package/lib/log/format/kibana.js +2 -2
  49. package/lib/ql/SELECT.js +10 -0
  50. package/lib/ql/parse.js +1 -0
  51. package/lib/req/cds-context.js +4 -1
  52. package/lib/req/context.js +50 -56
  53. package/lib/req/event.js +1 -6
  54. package/lib/req/locale.js +6 -5
  55. package/lib/req/request.js +2 -0
  56. package/lib/req/user.js +7 -5
  57. package/lib/serve/Service-api.js +10 -7
  58. package/lib/serve/Service-dispatch.js +9 -11
  59. package/lib/serve/Service-methods.js +30 -41
  60. package/lib/serve/Transaction.js +10 -7
  61. package/lib/serve/adapters.js +11 -9
  62. package/lib/serve/factory.js +14 -9
  63. package/lib/serve/index.js +28 -15
  64. package/lib/utils/data.js +1 -1
  65. package/lib/utils/index.js +27 -30
  66. package/lib/utils/resources/index.js +101 -0
  67. package/lib/utils/resources/tar.js +71 -0
  68. package/lib/utils/resources/utils.js +11 -0
  69. package/libx/_runtime/audit/Service.js +36 -39
  70. package/libx/_runtime/audit/generic/personal/access.js +3 -4
  71. package/libx/_runtime/audit/generic/personal/modification.js +3 -4
  72. package/libx/_runtime/audit/utils/v2.js +1 -2
  73. package/libx/_runtime/auth/index.js +126 -84
  74. package/libx/_runtime/auth/strategies/JWT.js +12 -19
  75. package/libx/_runtime/auth/strategies/dummy.js +1 -5
  76. package/libx/_runtime/auth/strategies/dwc.js +11 -9
  77. package/libx/_runtime/auth/strategies/mock.js +0 -4
  78. package/libx/_runtime/auth/strategies/{utils/xssec.js → xssecUtils.js} +7 -4
  79. package/libx/_runtime/auth/strategies/xsuaa.js +12 -19
  80. package/libx/_runtime/auth/utils.js +22 -1
  81. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +104 -98
  82. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +8 -3
  83. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
  84. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
  85. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/language.js +2 -8
  86. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -29
  87. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +2 -1
  88. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +3 -2
  89. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +2 -2
  90. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +4 -6
  91. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +24 -21
  92. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +8 -2
  93. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +2 -0
  94. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DispatcherCommand.js +2 -6
  95. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -12
  96. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +33 -9
  97. package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +56 -0
  98. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +2 -2
  99. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +10 -3
  100. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +9 -11
  101. package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +6 -3
  102. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +4 -2
  103. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +1 -1
  104. package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +1 -1
  105. package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +2 -3
  106. package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +6 -4
  107. package/libx/_runtime/cds-services/adapter/rest/utils/result.js +1 -0
  108. package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +8 -5
  109. package/libx/_runtime/cds-services/services/Service.js +40 -0
  110. package/libx/_runtime/cds-services/services/utils/columns.js +4 -3
  111. package/libx/_runtime/cds-services/services/utils/compareJson.js +4 -4
  112. package/libx/_runtime/cds-services/services/utils/differ.js +3 -3
  113. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +4 -4
  114. package/libx/_runtime/cds-services/util/assert.js +20 -14
  115. package/libx/_runtime/cds.js +9 -1
  116. package/libx/_runtime/common/aspects/any.js +5 -0
  117. package/libx/_runtime/common/aspects/entity.js +25 -7
  118. package/libx/_runtime/common/aspects/utils.js +2 -2
  119. package/libx/_runtime/common/composition/data.js +6 -0
  120. package/libx/_runtime/common/composition/insert.js +3 -2
  121. package/libx/_runtime/common/composition/tree.js +4 -10
  122. package/libx/_runtime/common/composition/update.js +4 -4
  123. package/libx/_runtime/common/constants/draft.js +29 -26
  124. package/libx/_runtime/common/error/constants.js +2 -2
  125. package/libx/_runtime/common/error/frontend.js +7 -15
  126. package/libx/_runtime/common/generic/auth/capabilities.js +59 -0
  127. package/libx/_runtime/common/generic/auth/constants.js +20 -0
  128. package/libx/_runtime/common/generic/auth/expand.js +54 -0
  129. package/libx/_runtime/common/generic/auth/index.js +32 -0
  130. package/libx/_runtime/common/generic/auth/insertOnly.js +15 -0
  131. package/libx/_runtime/common/generic/auth/readOnly.js +26 -0
  132. package/libx/_runtime/common/generic/auth/requires.js +34 -0
  133. package/libx/_runtime/common/generic/auth/restrict.js +298 -0
  134. package/libx/_runtime/common/generic/auth/restrictions.js +85 -0
  135. package/libx/_runtime/common/generic/auth/utils.js +213 -0
  136. package/libx/_runtime/common/generic/crud.js +8 -6
  137. package/libx/_runtime/common/generic/etag.js +1 -1
  138. package/libx/_runtime/common/generic/input.js +35 -35
  139. package/libx/_runtime/common/generic/sorting.js +2 -3
  140. package/libx/_runtime/common/generic/temporal.js +2 -2
  141. package/libx/_runtime/common/i18n/messages.properties +1 -1
  142. package/libx/_runtime/common/toggles/handler.js +21 -0
  143. package/libx/_runtime/common/utils/copy.js +10 -1
  144. package/libx/_runtime/common/utils/cqn2cqn4sql.js +111 -35
  145. package/libx/_runtime/common/utils/csn.js +63 -1
  146. package/libx/_runtime/common/utils/dollar.js +10 -1
  147. package/libx/_runtime/common/utils/draft.js +46 -7
  148. package/libx/_runtime/common/utils/entityFromCqn.js +13 -9
  149. package/libx/_runtime/common/utils/extensibilityUtils.js +18 -0
  150. package/libx/_runtime/common/utils/foreignKeyPropagations.js +88 -104
  151. package/libx/_runtime/common/utils/generateOnCond.js +4 -1
  152. package/libx/_runtime/common/utils/quotingStyles.js +2 -0
  153. package/libx/_runtime/common/utils/resolveStructured.js +25 -9
  154. package/libx/_runtime/common/utils/resolveView.js +4 -1
  155. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -16
  156. package/libx/_runtime/common/utils/structured.js +33 -37
  157. package/libx/_runtime/common/utils/template.js +17 -8
  158. package/libx/_runtime/common/utils/templateProcessor.js +28 -28
  159. package/libx/_runtime/db/data-conversion/post-processing.js +118 -412
  160. package/libx/_runtime/db/expand/expandCQNToJoin.js +45 -41
  161. package/libx/_runtime/db/expand/rawToExpanded.js +29 -8
  162. package/libx/_runtime/db/generic/index.js +1 -3
  163. package/libx/_runtime/db/generic/input.js +5 -10
  164. package/libx/_runtime/db/generic/rewrite.js +5 -2
  165. package/libx/_runtime/db/generic/structured.js +2 -2
  166. package/libx/_runtime/db/query/delete.js +2 -2
  167. package/libx/_runtime/db/query/insert.js +1 -1
  168. package/libx/_runtime/db/query/update.js +9 -14
  169. package/libx/_runtime/db/sql-builder/CreateBuilder.js +4 -3
  170. package/libx/_runtime/db/sql-builder/FunctionBuilder.js +8 -8
  171. package/libx/_runtime/db/sql-builder/InsertBuilder.js +14 -1
  172. package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -2
  173. package/libx/_runtime/db/sql-builder/dataTypes.js +3 -3
  174. package/libx/_runtime/db/utils/columns.js +3 -3
  175. package/libx/_runtime/db/utils/normalizeTimeData.js +2 -2
  176. package/libx/_runtime/db/utils/propagateForeignKeys.js +6 -2
  177. package/libx/_runtime/extensibility/mps/index.js +5 -0
  178. package/libx/_runtime/extensibility/mps/service.js +111 -0
  179. package/libx/_runtime/extensibility/mps/tar.js +42 -0
  180. package/libx/_runtime/extensibility/mps/utils.js +11 -0
  181. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformREAD.js +0 -0
  182. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformRESULT.js +17 -5
  183. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformWRITE.js +1 -0
  184. package/libx/_runtime/extensibility/uiflex/index.js +54 -0
  185. package/libx/_runtime/extensibility/uiflex/service.js +276 -0
  186. package/libx/_runtime/{fiori → extensibility}/uiflex/utils.js +22 -7
  187. package/libx/_runtime/fiori/generic/activate.js +2 -2
  188. package/libx/_runtime/fiori/generic/before.js +4 -4
  189. package/libx/_runtime/fiori/generic/new.js +3 -3
  190. package/libx/_runtime/fiori/generic/patch.js +1 -1
  191. package/libx/_runtime/fiori/generic/read.js +58 -66
  192. package/libx/_runtime/fiori/generic/readOverDraft.js +74 -16
  193. package/libx/_runtime/fiori/utils/handler.js +6 -13
  194. package/libx/_runtime/fiori/utils/where.js +6 -5
  195. package/libx/_runtime/hana/Service.js +4 -10
  196. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
  197. package/libx/_runtime/hana/driver.js +2 -2
  198. package/libx/_runtime/hana/execute.js +45 -75
  199. package/libx/_runtime/hana/pool.js +1 -1
  200. package/libx/_runtime/hana/streaming.js +2 -1
  201. package/libx/_runtime/index.js +6 -6
  202. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +5 -21
  203. package/libx/_runtime/messaging/Outbox.js +2 -2
  204. package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -14
  205. package/libx/_runtime/messaging/common-utils/connections.js +5 -7
  206. package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +30 -0
  207. package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -1
  208. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +36 -30
  209. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -12
  210. package/libx/_runtime/messaging/enterprise-messaging.js +8 -8
  211. package/libx/_runtime/messaging/file-based.js +5 -5
  212. package/libx/_runtime/messaging/message-queuing.js +14 -12
  213. package/libx/_runtime/messaging/outbox/utils.js +18 -19
  214. package/libx/_runtime/messaging/redis-messaging.js +91 -0
  215. package/libx/_runtime/messaging/service.js +8 -6
  216. package/libx/_runtime/remote/Service.js +44 -8
  217. package/libx/_runtime/remote/utils/client.js +24 -19
  218. package/libx/_runtime/remote/utils/data.js +11 -11
  219. package/libx/_runtime/sqlite/Service.js +6 -9
  220. package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +5 -2
  221. package/libx/_runtime/types/api.js +10 -2
  222. package/libx/common/utils/ucsn.js +109 -0
  223. package/libx/gql/resolvers/crud/update.js +5 -0
  224. package/libx/gql/resolvers/parse/ast2cqn/columns.js +3 -1
  225. package/libx/gql/schema/typeDefMap.js +2 -2
  226. package/libx/odata/afterburner.js +110 -16
  227. package/libx/odata/cqn2odata.js +24 -27
  228. package/libx/odata/grammar.pegjs +9 -1
  229. package/libx/odata/parseToCqn.js +39 -0
  230. package/libx/odata/parser.js +1 -1
  231. package/libx/rest/RestAdapter.js +9 -1
  232. package/libx/rest/middleware/input.js +54 -0
  233. package/libx/rest/middleware/operation.js +14 -1
  234. package/libx/rest/middleware/parse.js +11 -7
  235. package/package.json +2 -2
  236. package/server.js +34 -19
  237. package/srv/audit-log.cds +2 -2
  238. package/srv/flex.cds +8 -2
  239. package/srv/flex.js +1 -1
  240. package/srv/mps.cds +23 -0
  241. package/srv/mps.js +1 -0
  242. package/libx/_runtime/auth/strategies/utils/uaa.js +0 -21
  243. package/libx/_runtime/common/generic/auth.js +0 -874
  244. package/libx/_runtime/common/toggles/alpha.js +0 -43
  245. package/libx/_runtime/db/generic/arrayed.js +0 -33
  246. package/libx/_runtime/fiori/uiflex/index.js +0 -35
  247. package/libx/_runtime/fiori/uiflex/service.js +0 -150
  248. package/libx/rest/utils/data.js +0 -60
@@ -1,43 +0,0 @@
1
- /*
2
- * additions for feature toggles
3
- */
4
- module.exports = cds => {
5
- if (!cds.env.features.alpha_toggles) return (req, res, next) => next()
6
-
7
- return (req, res, next) => {
8
- // attach _getHash helper to mtx
9
- if (!cds.mtx._getHash) {
10
- cds.mtx._getHash = req => {
11
- let hash = req.tenant
12
- if (req.features) hash += ':' + Object.keys(req.features).join(';')
13
- return hash
14
- }
15
- }
16
-
17
- // inject features from dwc header
18
- const fth = req.headers['dwc-product-configuration']
19
- if (fth) {
20
- const { features } = JSON.parse(Buffer.from(fth, 'base64').toString('utf-8'))
21
- req.features = features
22
- .sort((a, b) => a.name.localeCompare(b.name))
23
- .reduce((acc, cur) => {
24
- if (cur.enabled) acc[cur.name] = 1
25
- return acc
26
- }, {})
27
- }
28
-
29
- // extend @sap/cds's dispatch listener
30
- const {
31
- eventEmitter: mtx,
32
- events: { TENANT_UPDATED }
33
- } = cds.mtx
34
- req.on('dispatch', req => {
35
- // clear ext map for next request as soon as it was dispatched
36
- mtx.emit(TENANT_UPDATED, cds.mtx._getHash(req._.req))
37
- // set cds.context.features here so we don't need to touch @sap/cds
38
- cds.context.features = req._.req.features
39
- })
40
-
41
- next()
42
- }
43
- }
@@ -1,33 +0,0 @@
1
- const { getEntityFromCQN } = require('../../common/utils/entityFromCqn')
2
- const getTemplate = require('../../common/utils/template')
3
- const templateProcessor = require('../../common/utils/templateProcessor')
4
-
5
- const _pick = element => {
6
- if (element.kind === 'element' && element.items) return 'arrayed'
7
- }
8
-
9
- const _processFn = ({ row, key, plain }) => {
10
- if (plain === 'arrayed' && row && row[key] && (typeof row[key] === 'string' || Buffer.isBuffer(row[key]))) {
11
- row[key] = JSON.parse(row[key])
12
- }
13
- }
14
-
15
- /**
16
- * Formats JSON Strings to arrayed data
17
- *
18
- * @param result - the result of the DB query
19
- * @param req - the context object
20
- * @returns {Promise}
21
- */
22
- module.exports = function (result, req) {
23
- if (!this.model) return
24
-
25
- const entity = getEntityFromCQN(req, this)
26
- if (!entity) return
27
-
28
- const template = getTemplate('db-arrayed', this, entity, { pick: _pick })
29
- if (template.elements.size === 0) return
30
-
31
- for (const row of Array.isArray(result) ? result : [result])
32
- templateProcessor({ processFn: _processFn, row, template })
33
- }
@@ -1,35 +0,0 @@
1
- module.exports = async () => {
2
- const cds = require('../../cds')
3
- if (!cds.requires.db) return
4
-
5
- const db = await cds.connect.to({ ...cds.requires.db, model: null, silent: true })
6
- const rs = await db.read('cds_r.Extensions')
7
- if (rs.length !== 0) {
8
- const extensions = []
9
- rs.forEach(row => extensions.push(...JSON.parse(row.csn).extensions))
10
- cds.once('loaded', csn => {
11
- if (cds.model) return // extend cds.model only
12
- const extended = cds.compile({
13
- 'base.csn': cds.compile.to.json(csn),
14
- 'ext.csn': cds.compile.to.json({ extensions })
15
- })
16
- csn.definitions = extended.definitions
17
- })
18
- }
19
- await db.disconnect()
20
-
21
- if (cds.db) return // because of tests
22
- cds.once('served', () => {
23
- const { transformExtendedFieldsCREATE, transformExtendedFieldsUPDATE } = require('./handler/transformWRITE')
24
- const { transformExtendedFieldsREAD } = require('./handler/transformREAD')
25
- const { transformExtendedFieldsRESULT } = require('./handler/transformRESULT')
26
- cds.db
27
- .before('CREATE', transformExtendedFieldsCREATE)
28
- .before('UPDATE', transformExtendedFieldsUPDATE)
29
- .before('READ', transformExtendedFieldsREAD)
30
- .after('READ', transformExtendedFieldsRESULT)
31
- if ('cds_r.ExtensibilityService' in cds.services) return
32
- const model = require('path').join(__dirname, '../../../..', 'srv/flex.cds')
33
- return cds.serve(model, { silent: true }).to('odata').in(cds.app)
34
- })
35
- }
@@ -1,150 +0,0 @@
1
- const cds = require('../../cds')
2
- const { ensureDraftsSuffix } = require('../../common/utils/draft')
3
-
4
- const { EXT_BACK_PACK } = require('./utils')
5
-
6
- const _getDraftTable = (view, cds) => {
7
- return cds.model.definitions[view]._isDraftEnabled ? ensureDraftsSuffix(view) : undefined
8
- }
9
-
10
- const _addAnnotation = extension => {
11
- Object.values(extension.elements).forEach(el => {
12
- el['@cds.extension'] = true
13
- })
14
- }
15
-
16
- const _isProjection = target => target && target.query && target.query._target
17
-
18
- const _resolveViews = (target, views_ = []) => {
19
- if (_isProjection(target)) {
20
- views_.push(target)
21
- return _resolveViews(target.query._target, views_)
22
- }
23
-
24
- return target
25
- }
26
-
27
- const _getCsn = req => {
28
- const csn = {
29
- extensions: req.data.extensions.map(ext => JSON.parse(ext))
30
- }
31
-
32
- return csn
33
- }
34
-
35
- const _addViews = csn => {
36
- csn.extensions.forEach(extension => {
37
- const target = cds.model.definitions[extension.extend]
38
- const views_ = []
39
- const view = _resolveViews(target, views_)
40
- extension.extend = view && view.name
41
- _addAnnotation(extension)
42
-
43
- // All projection views leading to the db entity are extended with back pack in case view columns are explicitly listed.
44
- // The views using projections with '*' obtain the back pack automatically.
45
- views_.forEach(view => {
46
- if (!view.projection || (view.projection.columns && !view.projection.columns.some(col => col === '*'))) {
47
- csn.extensions.push({
48
- extend: view.name,
49
- columns: Object.keys(extension.elements).map(key => {
50
- return { ref: [key] }
51
- })
52
- })
53
- }
54
- })
55
- })
56
- }
57
-
58
- const _needsQuotations = t => t instanceof cds.builtin.classes.string || t instanceof cds.builtin.classes.date
59
-
60
- const _handleDefaults = async (extension, dbEntity, req, cds, draftEntity) => {
61
- const ext = Object.keys(extension.elements)
62
- .filter(key => extension.elements[key].default)
63
- .map(key => {
64
- const element = extension.elements[key]
65
- const t = cds.model.definitions[element.type] || cds.builtin.types[element.type]
66
- const value = t && _needsQuotations(t) ? `"${element.default.val}"` : element.default.val
67
- return `"${key}":${value}`
68
- })
69
-
70
- if (ext.length !== 0) {
71
- const extStr = ext.join(',')
72
- const changed = `'{${extStr},' || substr(${EXT_BACK_PACK}, 2, length(${EXT_BACK_PACK})-1)`
73
- const assign = `${EXT_BACK_PACK} = CASE WHEN ${EXT_BACK_PACK} IS NULL THEN '{${extStr}}' ELSE ${changed} END`
74
- await UPDATE(dbEntity).with(assign)
75
- if (draftEntity) await UPDATE(draftEntity).with(assign)
76
- }
77
- }
78
-
79
- const _validateCsn = (csn, req) => {
80
- csn.extensions.forEach(extension => {
81
- if (!extension.extend || !cds.model.definitions[extension.extend]) {
82
- req.reject(400, 'Invalid extension. Parameter "extend" missing or malformed')
83
- }
84
-
85
- if (!extension.elements) {
86
- req.reject(400, 'Invalid extension. Missing parameter "elements"')
87
- }
88
- })
89
- }
90
-
91
- const _validateExtensionFields = async (csn, req) => {
92
- csn.extensions.forEach(extension => {
93
- if (extension.elements) {
94
- Object.keys(extension.elements).forEach(name => {
95
- if (!/^[A-Za-z]\w*$/.test(name)) {
96
- req.reject(400, `Invalid extension. Bad element name "${name}"`)
97
- }
98
-
99
- if (Object.keys(cds.model.definitions[extension.extend].elements).includes(name)) {
100
- req.reject(400, `Invalid extension. Element "${name}" already exists`)
101
- }
102
- })
103
- }
104
- })
105
- }
106
-
107
- const _getCompilerError = messages => {
108
- const defaultMsg = 'Error while compiling extension'
109
- if (!messages) return defaultMsg
110
-
111
- for (const msg of messages) {
112
- if (msg.severity === 'Error') return msg.message
113
- }
114
-
115
- return defaultMsg
116
- }
117
-
118
- const _validateExtension = async (csn, req) => {
119
- try {
120
- const base = await cds.load('*', cds.options)
121
- const baseCsn = await cds.compile.to.json(base)
122
- const extCsn = await cds.compile.to.json(csn)
123
- await cds.compile.to.csn({ 'base.csn': baseCsn, 'ext.csn': extCsn })
124
- } catch (err) {
125
- req.reject(400, _getCompilerError(err.messages))
126
- }
127
- }
128
-
129
- module.exports = function () {
130
- this.on('addExtension', async req => {
131
- const csn = _getCsn(req, cds)
132
- _validateCsn(csn, req)
133
- await _validateExtensionFields(csn, req)
134
- _addViews(csn, cds)
135
- await _validateExtension(csn, req)
136
-
137
- const ID = cds.utils.uuid()
138
- await INSERT.into('cds_r.Extensions').entries([{ ID, csn: JSON.stringify(csn) }])
139
-
140
- for (const ext of req.data.extensions) {
141
- const extension = JSON.parse(ext)
142
- const draft = _getDraftTable(extension.extend, cds)
143
- const target = cds.model.definitions[extension.extend]
144
- const dbEntity = _resolveViews(target).name
145
- await _handleDefaults(extension, dbEntity, req, cds, draft)
146
- }
147
-
148
- setTimeout(() => process.send('restart'), 1111)
149
- })
150
- }
@@ -1,60 +0,0 @@
1
- const { deepCopyObject } = require('../../_runtime/common/utils/copy')
2
- const { checkKeys, checkStatic } = require('../../_runtime/cds-services/util/assert')
3
- const { MULTIPLE_ERRORS } = require('../../_runtime/common/error/constants')
4
-
5
- // this can be reused for flattening data on db layer, if necessary
6
- // const _getFlattenedCopy = (data, key, entity) => {
7
- // const d = {}
8
- // const prefix = key + '_'
9
- // // TODO: ignore or preserve unknown?
10
- // const matches = Object.keys(entity.elements)
11
- // .filter(ele => ele.startsWith(prefix))
12
- // .map(ele => ele.replace(prefix, ''))
13
- // if (matches.length) {
14
- // const current = data[key]
15
- // for (const k of matches) if (current[k] !== undefined) d[prefix + k] = current[k]
16
- // const nested = Object.keys(current).filter(k => current[k] && typeof current[k] === 'object')
17
- // for (const k of nested) Object.assign(d, _getFlattenedCopy({ [prefix + k]: current[k] }, prefix + k, entity))
18
- // }
19
- // return d
20
- // }
21
-
22
- const _getDeepCopy = (data, definition, model, validations, skipKeys) => {
23
- skipKeys || (definition.keys && validations.push(...checkKeys(definition, data)))
24
- validations.push(...checkStatic(definition, data, true))
25
-
26
- const d = {}
27
- for (const k in data) {
28
- const element = (definition.elements && definition.elements[k]) || (definition.params && definition.params[k])
29
- if (!element) {
30
- if (!definition['@open']) {
31
- // ignore input (the default)
32
- } else {
33
- d[k] = data[k] && typeof data[k] === 'object' ? deepCopyObject(data[k]) : data[k]
34
- }
35
- } else if (element.isAssociation) {
36
- d[k] = Array.isArray(data[k])
37
- ? data[k].map(d => _getDeepCopy(d, model.definitions[element.target], model, validations))
38
- : _getDeepCopy(data[k], model.definitions[element.target], model, validations)
39
- } else if (element._isStructured) {
40
- d[k] = _getDeepCopy(data[k], element, model, validations)
41
- } else {
42
- d[k] = data[k]
43
- }
44
- }
45
- return d
46
- }
47
-
48
- const getDeepCopy = (data, definition, model, skipKeys) => {
49
- const validations = []
50
- const copy = Array.isArray(data)
51
- ? data.map(d => _getDeepCopy(d, definition, model, validations, skipKeys))
52
- : _getDeepCopy(data, definition, model, validations, skipKeys)
53
- if (!validations.length) return [undefined, copy]
54
- if (validations.length === 1) return [validations[0]]
55
- return [Object.assign(new Error(MULTIPLE_ERRORS), { details: validations })]
56
- }
57
-
58
- module.exports = {
59
- getDeepCopy
60
- }