@sap/cds 7.9.2 → 8.0.3

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 (279) hide show
  1. package/CHANGELOG.md +139 -3656
  2. package/_i18n/i18n_en_US_saptrc.properties +113 -0
  3. package/_i18n/i18n_zh_CN.properties +7 -4
  4. package/app/index.css +129 -0
  5. package/app/index.html +16 -64
  6. package/app/index.js +14 -9
  7. package/bin/args.js +34 -0
  8. package/bin/serve.js +18 -24
  9. package/bin/test.js +97 -0
  10. package/common.cds +5 -12
  11. package/eslint.config.mjs +133 -0
  12. package/lib/auth/basic-auth.js +16 -20
  13. package/lib/auth/dummy-auth.js +1 -1
  14. package/lib/auth/ias-auth.js +12 -30
  15. package/lib/auth/index.js +1 -14
  16. package/lib/auth/jwt-auth.js +14 -30
  17. package/lib/compile/cds-compile.js +1 -2
  18. package/lib/compile/cdsc.js +21 -26
  19. package/lib/compile/etc/_localized.js +1 -6
  20. package/lib/compile/etc/csv.js +1 -1
  21. package/lib/compile/etc/properties.js +1 -1
  22. package/lib/compile/for/java.js +1 -1
  23. package/lib/compile/for/lean_drafts.js +4 -6
  24. package/lib/compile/for/nodejs.js +1 -1
  25. package/lib/compile/parse.js +4 -0
  26. package/lib/compile/resolve.js +4 -4
  27. package/lib/compile/to/edm-files.js +16 -23
  28. package/lib/compile/to/hana.js +27 -0
  29. package/lib/compile/to/json.js +1 -1
  30. package/lib/compile/to/sql.js +5 -1
  31. package/lib/compile/to/srvinfo.js +1 -1
  32. package/lib/compile/to/yaml.js +3 -3
  33. package/lib/dbs/cds-deploy.js +4 -2
  34. package/lib/env/cds-env.js +10 -14
  35. package/lib/env/cds-requires.js +29 -13
  36. package/lib/env/defaults.js +46 -16
  37. package/lib/env/plugins.js +1 -1
  38. package/lib/env/schemas/cds-rc.js +8 -4
  39. package/lib/env/schemas/index.js +7 -7
  40. package/lib/env/serviceBindings.js +1 -1
  41. package/lib/index.js +12 -10
  42. package/lib/lazy.js +1 -1
  43. package/lib/linked/classes.js +36 -8
  44. package/lib/linked/entities.js +2 -10
  45. package/lib/linked/models.js +2 -1
  46. package/lib/linked/validate.js +292 -0
  47. package/lib/log/cds-error.js +0 -6
  48. package/lib/log/cds-log.js +3 -3
  49. package/lib/log/format/json.js +1 -1
  50. package/lib/log/service/index.js +0 -1
  51. package/lib/plugins.js +3 -3
  52. package/lib/ql/Query.js +2 -10
  53. package/lib/ql/SELECT.js +1 -1
  54. package/lib/ql/Whereable.js +3 -2
  55. package/lib/req/cds-context.js +14 -25
  56. package/lib/req/context.js +23 -25
  57. package/lib/req/request.js +1 -34
  58. package/lib/req/user.js +47 -35
  59. package/lib/srv/bindings.js +1 -1
  60. package/lib/srv/cds-connect.js +4 -4
  61. package/lib/srv/cds-serve.js +2 -2
  62. package/lib/srv/factory.js +1 -1
  63. package/lib/srv/middlewares/cds-context.js +11 -22
  64. package/lib/srv/middlewares/ctx-model.js +2 -3
  65. package/lib/srv/middlewares/errors.js +41 -8
  66. package/lib/srv/middlewares/index.js +3 -3
  67. package/lib/srv/middlewares/trace.js +0 -2
  68. package/lib/srv/protocols/hcql.js +15 -10
  69. package/lib/srv/protocols/http.js +44 -49
  70. package/lib/srv/protocols/index.js +1 -23
  71. package/lib/srv/protocols/odata-v4.js +12 -74
  72. package/lib/srv/protocols/rest.js +1 -13
  73. package/lib/srv/srv-api.js +0 -20
  74. package/lib/srv/srv-dispatch.js +3 -2
  75. package/lib/srv/srv-handlers.js +22 -11
  76. package/lib/srv/srv-methods.js +2 -2
  77. package/lib/srv/srv-models.js +3 -36
  78. package/lib/test/expect.js +343 -0
  79. package/lib/test/index.js +2 -0
  80. package/lib/test/reporter.js +176 -0
  81. package/lib/utils/axios.js +10 -9
  82. package/lib/utils/cds-test.js +86 -37
  83. package/lib/utils/cds-utils.js +54 -7
  84. package/lib/utils/check-version.js +0 -4
  85. package/lib/utils/colors.js +49 -0
  86. package/lib/utils/data.js +5 -4
  87. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -7
  88. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +3 -30
  89. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +6 -12
  90. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -3
  91. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +0 -1
  92. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +4 -7
  93. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +12 -6
  94. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +2 -4
  95. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +1 -0
  96. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
  97. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +0 -1
  98. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -3
  99. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +1 -1
  100. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/AbstractEdmStructuredType.js +1 -2
  101. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +5 -0
  102. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +1 -1
  103. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +9 -43
  104. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +0 -1
  105. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +8 -3
  106. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +4 -2
  107. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +1 -3
  108. package/libx/_runtime/cds-services/util/assert.js +1 -1
  109. package/libx/_runtime/cds.js +10 -3
  110. package/libx/_runtime/common/Service.js +12 -32
  111. package/libx/_runtime/common/aspects/any.js +1 -0
  112. package/libx/_runtime/common/code-ext/execute.js +1 -1
  113. package/libx/_runtime/common/code-ext/worker.js +0 -1
  114. package/libx/_runtime/common/composition/data.js +0 -1
  115. package/libx/_runtime/common/composition/delete.js +0 -1
  116. package/libx/_runtime/common/composition/insert.js +2 -2
  117. package/libx/_runtime/common/composition/tree.js +0 -1
  118. package/libx/_runtime/common/composition/update.js +3 -3
  119. package/libx/_runtime/common/error/frontend.js +21 -12
  120. package/libx/_runtime/common/error/log.js +36 -0
  121. package/libx/_runtime/common/error/utils.js +2 -5
  122. package/libx/_runtime/common/generic/auth/autoexpose.js +18 -17
  123. package/libx/_runtime/common/generic/auth/expand.js +1 -1
  124. package/libx/_runtime/common/generic/auth/readOnly.js +1 -2
  125. package/libx/_runtime/common/generic/auth/restrict.js +23 -42
  126. package/libx/_runtime/common/generic/auth/restrictions.js +2 -7
  127. package/libx/_runtime/common/generic/auth/utils.js +91 -88
  128. package/libx/_runtime/common/generic/crud.js +6 -5
  129. package/libx/_runtime/common/generic/etag.js +7 -12
  130. package/libx/_runtime/common/generic/input.js +70 -68
  131. package/libx/_runtime/common/generic/paging.js +1 -0
  132. package/libx/_runtime/common/generic/sorting.js +1 -0
  133. package/libx/_runtime/common/generic/temporal.js +8 -2
  134. package/libx/_runtime/common/i18n/index.js +1 -1
  135. package/libx/_runtime/common/i18n/messages.properties +3 -1
  136. package/libx/_runtime/common/utils/binary.js +8 -2
  137. package/libx/_runtime/common/utils/compareJson.js +5 -1
  138. package/libx/_runtime/common/utils/copy.js +6 -11
  139. package/libx/_runtime/common/utils/cqn2cqn4sql.js +16 -14
  140. package/libx/_runtime/common/utils/differ.js +3 -6
  141. package/libx/_runtime/common/utils/keys.js +77 -18
  142. package/libx/_runtime/common/utils/postProcess.js +12 -15
  143. package/libx/_runtime/common/utils/propagateForeignKeys.js +0 -1
  144. package/libx/_runtime/common/utils/resolveView.js +2 -3
  145. package/libx/_runtime/common/utils/restrictions.js +45 -17
  146. package/libx/_runtime/common/utils/rewriteAsterisks.js +1 -8
  147. package/libx/_runtime/common/utils/stream.js +3 -16
  148. package/libx/_runtime/common/utils/streamProp.js +8 -18
  149. package/libx/_runtime/common/utils/structured.js +1 -1
  150. package/libx/_runtime/common/utils/ucsn.js +0 -2
  151. package/libx/_runtime/db/Service.js +0 -72
  152. package/libx/_runtime/db/data-conversion/post-processing.js +0 -1
  153. package/libx/_runtime/db/expand/expandCQNToJoin.js +9 -9
  154. package/libx/_runtime/db/expand/rawToExpanded.js +0 -8
  155. package/libx/_runtime/db/generic/input.js +3 -8
  156. package/libx/_runtime/db/generic/rewrite.js +27 -4
  157. package/libx/_runtime/db/query/read.js +2 -2
  158. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -1
  159. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
  160. package/libx/_runtime/db/utils/columns.js +2 -6
  161. package/libx/_runtime/fiori/lean-draft.js +138 -56
  162. package/libx/_runtime/hana/Service.js +0 -1
  163. package/libx/_runtime/hana/driver.js +1 -1
  164. package/libx/_runtime/hana/dynatrace.js +1 -2
  165. package/libx/_runtime/hana/pool.js +11 -21
  166. package/libx/_runtime/hana/streaming.js +0 -1
  167. package/libx/_runtime/messaging/common-utils/AMQPClient.js +0 -1
  168. package/libx/_runtime/messaging/common-utils/authorizedRequest.js +1 -1
  169. package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +1 -1
  170. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +1 -1
  171. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -33
  172. package/libx/_runtime/messaging/event-broker.js +0 -12
  173. package/libx/_runtime/messaging/file-based.js +3 -3
  174. package/libx/_runtime/messaging/http-utils/token.js +1 -1
  175. package/libx/_runtime/messaging/kafka.js +2 -2
  176. package/libx/_runtime/messaging/redis-messaging.js +0 -1
  177. package/libx/_runtime/remote/Service.js +25 -25
  178. package/libx/_runtime/remote/utils/client.js +4 -5
  179. package/libx/_runtime/remote/utils/cloudSdkProvider.js +0 -3
  180. package/libx/_runtime/remote/utils/data.js +0 -1
  181. package/libx/_runtime/sqlite/Service.js +1 -2
  182. package/libx/_runtime/ucl/Service.js +37 -78
  183. package/libx/common/assert/index.js +22 -21
  184. package/libx/common/assert/type-relaxed.js +39 -0
  185. package/libx/common/assert/utils.js +3 -2
  186. package/libx/common/assert/validation.js +3 -8
  187. package/libx/common/utils/index.js +5 -0
  188. package/libx/common/utils/path.js +51 -0
  189. package/libx/odata/ODataAdapter.js +126 -0
  190. package/libx/odata/index.js +15 -2
  191. package/libx/odata/middleware/batch.js +261 -72
  192. package/libx/odata/middleware/body-parser.js +33 -0
  193. package/libx/odata/middleware/create.js +44 -59
  194. package/libx/odata/middleware/delete.js +23 -12
  195. package/libx/odata/middleware/error.js +30 -6
  196. package/libx/odata/middleware/metadata.js +38 -26
  197. package/libx/odata/middleware/operation.js +93 -69
  198. package/libx/odata/middleware/parse.js +6 -8
  199. package/libx/odata/middleware/read.js +117 -93
  200. package/libx/odata/middleware/service-document.js +22 -19
  201. package/libx/odata/middleware/stream.js +54 -56
  202. package/libx/odata/middleware/update.js +79 -87
  203. package/libx/odata/parse/afterburner.js +191 -175
  204. package/libx/odata/parse/cqn2odata.js +8 -8
  205. package/libx/odata/parse/grammar.peggy +27 -20
  206. package/libx/odata/parse/multipartToJson.js +17 -9
  207. package/libx/odata/parse/parser.js +1 -1
  208. package/libx/odata/utils/etag.js +14 -6
  209. package/libx/odata/utils/index.js +84 -12
  210. package/libx/odata/utils/metadata.js +161 -0
  211. package/libx/odata/utils/postProcess.js +89 -0
  212. package/libx/odata/utils/readAfterWrite.js +134 -17
  213. package/libx/odata/utils/result.js +36 -142
  214. package/libx/outbox/index.js +5 -4
  215. package/libx/rest/RestAdapter.js +115 -182
  216. package/libx/rest/middleware/create.js +28 -24
  217. package/libx/rest/middleware/delete.js +7 -10
  218. package/libx/rest/middleware/error.js +19 -16
  219. package/libx/rest/middleware/operation.js +48 -41
  220. package/libx/rest/middleware/parse.js +128 -126
  221. package/libx/rest/middleware/read.js +20 -27
  222. package/libx/rest/middleware/update.js +26 -31
  223. package/package.json +16 -12
  224. package/server.js +4 -2
  225. package/tasks/enterprise-messaging-deploy.js +1 -1
  226. package/apis/cds.d.ts +0 -3
  227. package/apis/core.d.ts +0 -21
  228. package/apis/cqn.d.ts +0 -18
  229. package/apis/csn.d.ts +0 -21
  230. package/apis/events.d.ts +0 -18
  231. package/apis/internal/inference.d.ts +0 -18
  232. package/apis/linked.d.ts +0 -18
  233. package/apis/log.d.ts +0 -20
  234. package/apis/models.d.ts +0 -18
  235. package/apis/ql.d.ts +0 -18
  236. package/apis/reflect.d.ts +0 -32
  237. package/apis/server.d.ts +0 -18
  238. package/apis/services.d.ts +0 -22
  239. package/bin/cds-serve.js +0 -56
  240. package/lib/compile/to/gql.js +0 -15
  241. package/lib/srv/protocols/_legacy.js +0 -44
  242. package/lib/utils/jest.js +0 -43
  243. package/libx/_runtime/auth/index.js +0 -193
  244. package/libx/_runtime/auth/strategies/JWT.js +0 -37
  245. package/libx/_runtime/auth/strategies/basic.js +0 -20
  246. package/libx/_runtime/auth/strategies/dummy.js +0 -14
  247. package/libx/_runtime/auth/strategies/ias-auth.js +0 -1
  248. package/libx/_runtime/auth/strategies/mock.js +0 -77
  249. package/libx/_runtime/auth/strategies/xssecUtils.js +0 -93
  250. package/libx/_runtime/auth/strategies/xsuaa.js +0 -38
  251. package/libx/_runtime/common/perf/index.js +0 -19
  252. package/libx/_runtime/common/utils/ensureIEEE754.js +0 -29
  253. package/libx/_runtime/fiori/draft.js +0 -2
  254. package/libx/_runtime/fiori/generic/activate.js +0 -190
  255. package/libx/_runtime/fiori/generic/before.js +0 -201
  256. package/libx/_runtime/fiori/generic/cancel.js +0 -19
  257. package/libx/_runtime/fiori/generic/delete.js +0 -21
  258. package/libx/_runtime/fiori/generic/edit.js +0 -157
  259. package/libx/_runtime/fiori/generic/index.js +0 -25
  260. package/libx/_runtime/fiori/generic/new.js +0 -82
  261. package/libx/_runtime/fiori/generic/patch.js +0 -101
  262. package/libx/_runtime/fiori/generic/prepare.js +0 -57
  263. package/libx/_runtime/fiori/generic/read.js +0 -1340
  264. package/libx/_runtime/fiori/generic/readOverDraft.js +0 -146
  265. package/libx/_runtime/fiori/utils/csn.js +0 -13
  266. package/libx/_runtime/fiori/utils/delete.js +0 -114
  267. package/libx/_runtime/fiori/utils/handler.js +0 -264
  268. package/libx/_runtime/fiori/utils/lockInfo.js +0 -27
  269. package/libx/_runtime/fiori/utils/req.js +0 -23
  270. package/libx/_runtime/fiori/utils/stream.js +0 -36
  271. package/libx/_runtime/fiori/utils/where.js +0 -254
  272. package/libx/_runtime/index.js +0 -22
  273. package/libx/odata/utils/handler.js +0 -120
  274. package/libx/odata/utils/metaInfo.js +0 -410
  275. package/libx/odata/utils/path.js +0 -75
  276. package/libx/rest/RestRequest.js +0 -32
  277. package/libx/rest/index.js +0 -3
  278. package/libx/rest/readme.md +0 -1
  279. /package/libx/common/assert/{type.js → type-strict.js} +0 -0
@@ -68,25 +68,22 @@ const handleAliasInResult = (columns, result) => {
68
68
  // REVISIT: todo renaming for expanded entities
69
69
  // REVISIT: todo renaming for deep operations
70
70
  const postProcess = (query, result, service, onlySelectAliases = false) => {
71
+ if (!result) return result //> null and other falsy values must be returned
72
+
73
+ if (query.DELETE) return result
74
+
71
75
  if (query.SELECT) {
72
- if (query.SELECT.columns && query.SELECT.columns.find(col => col.func === 'count' && col.as === '$count')) {
73
- return [{ $count: result }]
74
- }
75
- handleAliasInResult(query.SELECT.columns, result)
76
+ if (query.SELECT.columns?.find(col => col.func === 'count' && col.as === '$count')) return [{ $count: result }]
76
77
 
77
- if (!onlySelectAliases) {
78
- const transition =
79
- query.SELECT && query.SELECT._transitions && query.SELECT._transitions[query.SELECT._transitions.length - 1]
80
- if (transition && result) return revertData(result, transition, service)
81
- }
78
+ handleAliasInResult(query.SELECT.columns, result)
82
79
 
83
- return result
80
+ if (onlySelectAliases) return result
84
81
  }
85
- if (query.DELETE) return result
86
- let transition
87
- if (query.INSERT) transition = query.INSERT._transitions[query.INSERT._transitions.length - 1]
88
- if (query.UPDATE) transition = query.UPDATE._transitions[query.UPDATE._transitions.length - 1]
89
- return revertData(result, transition, service)
82
+
83
+ const transitions = query.SELECT?._transitions || query.INSERT?._transitions || query.UPDATE?._transitions
84
+ if (transitions) return revertData(result, transitions[transitions.length - 1], service)
85
+
86
+ return result
90
87
  }
91
88
 
92
89
  module.exports = postProcess
@@ -81,7 +81,6 @@ const _propagateToParent = ({ parentElement, childElement, deep }, childRow, row
81
81
  }
82
82
  }
83
83
 
84
- /* eslint-disable complexity */
85
84
  module.exports = (
86
85
  tKey,
87
86
  row,
@@ -106,7 +106,6 @@ const _newNestedData = (queryTarget, newData, ref, value) => {
106
106
  }
107
107
  }
108
108
 
109
- // eslint-disable-next-line complexity
110
109
  const _newData = (data, transition, inverse, service) => {
111
110
  if (data === null) return null
112
111
 
@@ -592,7 +591,7 @@ const _checkForForbiddenViews = queryTarget => {
592
591
  const _getTransitionData = (target, columns, service, skipForbiddenViewCheck) => {
593
592
  // REVISIT: Find less param polluting way to skip forbidden view check for reads
594
593
  if (!skipForbiddenViewCheck) _checkForForbiddenViews(target)
595
- const targetStartsWithSrvName = service.namespace && target.name.startsWith(`${service.namespace}.`)
594
+ const targetStartsWithSrvName = service.definition?.name && target.name.startsWith(`${service.definition.name}.`)
596
595
  const persistenceTable = _isPersistenceTable(target)
597
596
  const isDatabaseService = service.isDatabaseService
598
597
  columns = _queryColumns(target, columns, persistenceTable, !isDatabaseService && !targetStartsWithSrvName)
@@ -611,7 +610,7 @@ const _getTransitionData = (target, columns, service, skipForbiddenViewCheck) =>
611
610
  if (target.query && target.query._target) {
612
611
  const newTarget = target.query._target
613
612
 
614
- if (isDatabaseService || !(service.namespace && newTarget.name.startsWith(`${service.namespace}.`))) {
613
+ if (isDatabaseService || !(service.definition?.name && newTarget.name.startsWith(`${service.definition.name}.`))) {
615
614
  return _getTransitionData(newTarget, columns, service, skipForbiddenViewCheck)
616
615
  }
617
616
 
@@ -1,27 +1,55 @@
1
+ // CLEANUP: This is only used in our Okra-based stuff now -> should move over there
1
2
  const cds = require('../../cds')
2
3
 
3
- // REVISIT: This is a perfect example of the expensive-check-before-doing anti pattern
4
+ const $cache = Symbol('service contains any restrictions cache')
5
+
4
6
  const containsAnyRestrictions = srv => {
5
- const accessRestrictions = getAccessRestrictions(srv)
6
- if (accessRestrictions.length > 1 || accessRestrictions[0] !== 'any') return true
7
-
8
- const entities = srv.entities
9
- const entitiesKeys = Object.keys(entities)
10
-
11
- return !!(
12
- entitiesKeys.some(entity => entities[entity]['@requires'] || entities[entity]['@restrict']) ||
13
- entitiesKeys.some(entity => {
14
- const actions = entities[entity].actions
15
- actions && Object.keys(actions).some(action => actions[action]['@requires'] || actions[action]['@restrict'])
16
- }) ||
17
- Object.keys(srv.operations).some(
18
- operation => srv.operations[operation]['@requires'] || srv.operations[operation]['@restrict']
7
+ let { model } = srv
8
+ if (srv.isExtensible) model = cds.context?.model || srv.model // REVISIT: extensions are not allowed to add or change restrictions, are they?
9
+
10
+ if (!model[$cache]) model[$cache] = new Map() // REVIST: reuse model._cached instead of introducing a separate one
11
+ const cache = model[$cache]
12
+
13
+ if (cache.has(srv.name)) return cache.get(srv.name)
14
+
15
+ cache.set(srv.name, false)
16
+
17
+ const accessRestrictions = getAccessRestrictions(model.definitions[srv.definition.name])
18
+ if (accessRestrictions.length > 1 || accessRestrictions[0] !== 'any') {
19
+ cache.set(srv.name, true)
20
+ } else {
21
+ // REVISIT: Use srv.definiton.entities instead
22
+ const entities = Object.keys(model.definitions).filter(k => {
23
+ const d = model.definitions[k]
24
+ return d.kind === 'entity' && d.name.startsWith(srv.definition.name + '.')
25
+ })
26
+ // REVISIT: Use srv.definiton.actions instead
27
+ const operations = Object.keys(model.definitions).filter(k => {
28
+ const d = model.definitions[k]
29
+ return (d.kind === 'action' || d.kind === 'function') && d.name.startsWith(srv.definition.name + '.')
30
+ })
31
+ // REVISIT: @requires and @restrict on single entities or operations DOES NOT mean that all service is restricted !
32
+ cache.set(
33
+ srv.name,
34
+ !!(
35
+ entities.some(ek => model.definitions[ek]['@requires'] || model.definitions[ek]['@restrict']) ||
36
+ entities.some(ek => {
37
+ const actions = model.definitions[ek].actions
38
+ actions && Object.keys(actions).some(action => actions[action]['@requires'] || actions[action]['@restrict'])
39
+ }) ||
40
+ operations.some(ok => model.definitions[ok]['@requires'] || model.definitions[ok]['@restrict'])
41
+ )
19
42
  )
20
- )
43
+ }
44
+
45
+ return cache.get(srv.name)
21
46
  }
22
47
 
48
+ // REVISIT: this is the legacy variant of HttpAdapter.early_access_check4, isn't it?
23
49
  const getAccessRestrictions = srv => {
24
- let restrictions = srv.definition['@restrict'] || srv.definition['@requires']
50
+ const srvDefinition = srv.definition || srv
51
+
52
+ let restrictions = srvDefinition['@restrict'] || srvDefinition['@requires']
25
53
  if (restrictions) {
26
54
  if (typeof restrictions === 'string') return [restrictions]
27
55
  return restrictions.map(r => r.to || r).flat()
@@ -1,6 +1,6 @@
1
1
  const { getNavigationIfStruct } = require('./structured')
2
2
  const getColumns = require('../../db/utils/columns')
3
- const { ensureNoDraftsSuffix, getDraftColumnsCQNForActive } = require('./draft')
3
+ const { ensureNoDraftsSuffix } = require('./draft')
4
4
  const { getEntityNameFromCQN } = require('./entityFromCqn')
5
5
  const cds = require('../../cds')
6
6
 
@@ -14,11 +14,6 @@ const isDuplicate = newColumn => column => {
14
14
  return newColumn.ref ? newColumn.ref.join('_') === column.ref.join('_') : newColumn === column.ref.join('_')
15
15
  }
16
16
 
17
- const _cqlDraftColumns = target => {
18
- if (target.name.endsWith('DraftAdministrativeData')) return []
19
- return getDraftColumnsCQNForActive(target)
20
- }
21
-
22
17
  const _expandColumn = (column, target, _4db) => {
23
18
  if (!(column.ref && column.expand)) return
24
19
  const nextTarget = getNavigationIfStruct(target, column.ref)
@@ -146,8 +141,6 @@ const rewriteAsterisks = (query, model, options) => {
146
141
  query.SELECT.columns = getColumns(target, { _4db, omitStream: !cds.env.features.stream_compat }).map(col => ({
147
142
  ref: [col.name]
148
143
  }))
149
- if (_4db && target._isDraftEnabled && !cds.env.fiori.lean_draft)
150
- query.SELECT.columns.push(..._cqlDraftColumns(target))
151
144
  }
152
145
  }
153
146
 
@@ -1,14 +1,10 @@
1
1
  const cds = require('../../cds')
2
2
  const LOG = cds.log('odata')
3
3
  const { SELECT } = cds.ql
4
- const { deepCopyArray } = require('./copy')
4
+ const { deepCopy } = require('./copy')
5
5
  const { getTransition } = require('./resolveView')
6
- const { cqn2cqn4sql } = require('./cqn2cqn4sql')
7
- const { adaptStreamCQN } = require('../../fiori/utils/stream.js')
8
- const { isPathToDraft } = require('./cqn')
9
6
 
10
- // eslint-disable-next-line complexity
11
- const _getStreamProperties = (req, query, model) => {
7
+ const _getStreamProperties = (req, query) => {
12
8
  // new odata parser sets streaming property in SELECT.from
13
9
  const ref = (query.SELECT.columns && query.SELECT.columns[0].ref) || query.SELECT.from.ref
14
10
  const propertyName = ref[ref.length - 1]
@@ -74,17 +70,8 @@ const _getStreamProperties = (req, query, model) => {
74
70
 
75
71
  if (columns.length && cds.db && !req.target._hasPersistenceSkip) {
76
72
  // used cloned path
77
- let select = SELECT.one
78
- .from({ ref: deepCopyArray(query.SELECT.from.ref), as: query.SELECT.from.as })
79
- .columns(columns)
73
+ let select = SELECT.one.from({ ref: deepCopy(query.SELECT.from.ref), as: query.SELECT.from.as }).columns(columns)
80
74
  if (query.SELECT.where?.length) select.SELECT.where = query.SELECT.where
81
- if (!cds.env.fiori.lean_draft) {
82
- const draft = req.target._isDraftEnabled && isPathToDraft(select.SELECT.from.ref, model)
83
- if (draft) {
84
- select = cqn2cqn4sql(select, model)
85
- adaptStreamCQN(select, draft)
86
- }
87
- }
88
75
 
89
76
  return cds
90
77
  .tx(req)
@@ -1,23 +1,16 @@
1
1
  const cds = require('../../cds')
2
- const { ensureNoDraftsSuffix, ensureUnlocalized } = require('../../fiori/utils/handler')
2
+ const { ensureNoDraftsSuffix, ensureUnlocalized } = require('./draft')
3
3
  const { isDuplicate } = require('./rewriteAsterisks')
4
4
 
5
5
  const _addColumn = (name, type, columns, url) => {
6
- // we do not want to return these additional odata properties with new adapter
7
- if (cds.env.features.odata_new_adapter) return
8
-
9
- if (typeof type === 'object') {
10
- let mType = type['='].replaceAll(/\./g, '_')
11
- const ref = {
12
- ref: [mType],
13
- as: `${name}@odata.mediaContentType`
14
- }
15
- if (!columns.find(isDuplicate(ref))) columns.push(ref)
16
- } else {
17
- const val = { val: type, as: `${name}@odata.mediaContentType` }
18
- if (!columns.find(isDuplicate(val))) columns.push(val)
6
+ const mediaType = typeof type === 'object' ? { ref: [type['='].replaceAll(/\./g, '_')] } : { val: type }
7
+ const col = {
8
+ xpr: ['case', 'when', { ref: [name] }, '=', { val: null }, 'then', 'NULL', 'else', mediaType, 'end'],
9
+ as: `${name}@odata.mediaContentType`
19
10
  }
20
11
 
12
+ if (!columns.find(isDuplicate(col))) columns.push(col)
13
+
21
14
  if (url) {
22
15
  const ref = {
23
16
  ref: [name],
@@ -28,17 +21,14 @@ const _addColumn = (name, type, columns, url) => {
28
21
  }
29
22
 
30
23
  const _addColumns = (target, columns) => {
31
- if (cds.env.features.odata_new_adapter) return
32
-
33
24
  for (const k in target.elements) {
34
25
  const el = target.elements[k]
35
26
  if (el['@Core.MediaType']) {
36
- _addColumn(el.name, el['@Core.MediaType'], columns, el['@Core.IsURL'])
27
+ _addColumn(el.name, el['@Core.MediaType'], columns, el['@Core.IsURL'] && el.type === 'cds.String')
37
28
  }
38
29
  }
39
30
  }
40
31
 
41
- // eslint-disable-next-line complexity
42
32
  const handleStreamProperties = (target, columns, model) => {
43
33
  if (!target || !model || !columns) return
44
34
 
@@ -160,7 +160,7 @@ const _transformStructToFlatWhereHaving = ([first, op, second], resArray, struct
160
160
  let structData = val
161
161
  try {
162
162
  structData = JSON.parse(val)
163
- } catch (e) {
163
+ } catch {
164
164
  /* since val === string */
165
165
  }
166
166
  if (flattenedElement && (structData === val || `${structData}` === val)) {
@@ -62,8 +62,6 @@ const _processor = ({ row, key, plain: { category }, element }) => {
62
62
  }
63
63
  }
64
64
 
65
- // REVISIT: check function complexity
66
- // eslint-disable-next-line complexity
67
65
  const _cleanup = (row, definition, cleanupNull, cleanupStruct, errors, prefix = []) => {
68
66
  if (!row || !definition) return
69
67
  const elements = definition.elements || definition.params
@@ -1,6 +1,4 @@
1
1
  const cds = require('../cds')
2
- const { SELECT } = cds.ql
3
- const { Transform } = require('stream')
4
2
 
5
3
  /*
6
4
  * generic queries
@@ -12,10 +10,6 @@ const queries = require('./query')
12
10
  */
13
11
  const generic = require('./generic')
14
12
 
15
- // not able to pass in stream method into cds.utils.deprecated for unknown reason
16
- // workaround: extract and deprecate helper function
17
- const _streamDeprecation = () => {}
18
-
19
13
  class DatabaseService extends cds.Service {
20
14
  constructor(...args) {
21
15
  super(...args)
@@ -93,72 +87,6 @@ class DatabaseService extends cds.Service {
93
87
  }
94
88
  })
95
89
  }
96
-
97
- stream(query) {
98
- cds.utils.deprecated(_streamDeprecation, { old: 'cds.stream' })()
99
- // aynchronous API: cds.stream(query)
100
- if (typeof query === 'object') {
101
- // eslint-disable-next-line no-async-promise-executor
102
- return new Promise(async (resolve, reject) => {
103
- try {
104
- if (cds.env.features.stream_compat) {
105
- const res = await this.run(Object.assign(query, { _streaming: true }))
106
- resolve(res && res.value)
107
- } else {
108
- const res = await this.run(query)
109
- // rely on query returning correct column (as documented for srv.stream(query))
110
- if (Array.isArray(res)) {
111
- resolve(res.length ? Object.values(res[0])[0] : undefined)
112
- } else {
113
- resolve(res && Object.values(res)[0])
114
- }
115
- }
116
- } catch (e) {
117
- reject(e)
118
- }
119
- })
120
- }
121
-
122
- // synchronous API: cds.stream('column').from(entity).where(...)
123
- return {
124
- from: (...args) => {
125
- const streamQuery = SELECT.one.from(...args)
126
- if (query && (!streamQuery.SELECT.columns || streamQuery.SELECT.columns.length !== 0)) {
127
- streamQuery.columns([query])
128
- }
129
-
130
- if (cds.env.features.stream_compat) streamQuery._streaming = true
131
-
132
- const result = new Transform({
133
- transform(chunk, encoding, callback) {
134
- this.push(chunk)
135
- callback()
136
- }
137
- })
138
-
139
- if (
140
- !streamQuery.SELECT.where &&
141
- !(
142
- streamQuery.SELECT.from &&
143
- streamQuery.SELECT.from.ref &&
144
- streamQuery.SELECT.from.ref[streamQuery.SELECT.from.ref.length - 1].where
145
- )
146
- ) {
147
- return {
148
- where: (...args) => {
149
- streamQuery.where(...args)
150
- this._runStream(streamQuery, result)
151
- return result
152
- }
153
- }
154
- }
155
-
156
- this._runStream(streamQuery, result)
157
-
158
- return result
159
- }
160
- }
161
- }
162
90
  }
163
91
 
164
92
  DatabaseService.prototype.isDatabaseService = true
@@ -53,7 +53,6 @@ const _addConverter = (mapper, name, converter) => {
53
53
  * @returns {Map<any, any>}
54
54
  * @private
55
55
  */
56
- // eslint-disable-next-line complexity
57
56
  const _getMapperForListedElements = (conversionMap, csn, cqn) => {
58
57
  const mapper = new Map()
59
58
 
@@ -1,8 +1,10 @@
1
1
  const cds = require('../../cds')
2
2
 
3
+ const { Object_keys } = cds.utils
4
+
3
5
  const { getAllKeys } = require('../../cds-services/adapter/odata-v4/odata-to-cqn/utils')
4
6
 
5
- const { deepCopyObject } = require('../../common/utils/copy')
7
+ const { deepCopy } = require('../../common/utils/copy')
6
8
  const { getNavigationIfStruct } = require('../../common/utils/structured')
7
9
  const { ensureNoDraftsSuffix, ensureDraftsSuffix, ensureUnlocalized } = require('../../common/utils/draft')
8
10
  const { isAsteriskColumn } = require('../../common/utils/rewriteAsterisks')
@@ -10,8 +12,6 @@ const { getCQNUnionFrom } = require('../../common/utils/union')
10
12
 
11
13
  const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
12
14
 
13
- const { entity_keys } = require('../../fiori/utils/handler')
14
-
15
15
  const getError = require('../../common/error')
16
16
 
17
17
  // Symbols are used to add extra information in response structure
@@ -26,7 +26,7 @@ const CLEANUP_KEYS = Symbol.for('sap.cds.cleanupKeys')
26
26
 
27
27
  function getCqnCopy(readToOneCQN) {
28
28
  // REVISIT: Use query.clone() instead
29
- const readToOneCQNCopy = deepCopyObject(readToOneCQN)
29
+ const readToOneCQNCopy = deepCopy(readToOneCQN)
30
30
  if (readToOneCQN[GET_KEY_VALUE] !== undefined) readToOneCQNCopy[GET_KEY_VALUE] = readToOneCQN[GET_KEY_VALUE]
31
31
  if (readToOneCQN[TO_MANY] !== undefined) readToOneCQNCopy[TO_MANY] = readToOneCQN[TO_MANY]
32
32
  if (readToOneCQN[TO_ACTIVE] !== undefined) readToOneCQNCopy[TO_ACTIVE] = readToOneCQN[TO_ACTIVE]
@@ -38,6 +38,9 @@ function getCqnCopy(readToOneCQN) {
38
38
  return readToOneCQNCopy
39
39
  }
40
40
 
41
+ const entity_keys = entity =>
42
+ Object_keys(entity.keys).filter(key => key !== 'IsActiveEntity' && !entity.keys[key].isAssociation)
43
+
41
44
  class JoinCQNFromExpanded {
42
45
  constructor(cqn, csn, locale) {
43
46
  this._SELECT = {}
@@ -493,7 +496,6 @@ class JoinCQNFromExpanded {
493
496
  * @param {boolean} arg.defaultLanguage - Use default language for localized fields
494
497
  * @private
495
498
  */
496
- // eslint-disable-next-line complexity
497
499
  _expandedToFlat({ entity, givenColumns, readToOneCQN, tableAlias, toManyTree, defaultLanguage }) {
498
500
  const toManyColumns = []
499
501
  const mappings = this._getMappingObject(toManyTree)
@@ -654,7 +656,6 @@ class JoinCQNFromExpanded {
654
656
  * @param args.defaultLanguage
655
657
  * @private
656
658
  */
657
- // eslint-disable-next-line complexity
658
659
  _addJoinAndElements({ column, entity, readToOneCQN, toManyTree, parentAlias, defaultLanguage }) {
659
660
  const extendedToManyTree = toManyTree.concat(column.ref[0] === parentAlias ? column.ref.slice(1) : column.ref)
660
661
  const tableAlias = this._createAlias(extendedToManyTree.join(':'))
@@ -702,7 +703,7 @@ class JoinCQNFromExpanded {
702
703
  const ks = Object.keys(expandedEntity.keys).filter(
703
704
  c => !expandedEntity.keys[c].isAssociation && !(c in DRAFT_COLUMNS_MAP)
704
705
  )
705
- const user = (cds.context && cds.context.user && cds.context.user.id) || 'anonymous'
706
+ const user = cds.context?.user.id
706
707
 
707
708
  const assoc = entity.associations[column.ref[0]]
708
709
  if (assoc.is2one && assoc.on) {
@@ -1157,7 +1158,6 @@ class JoinCQNFromExpanded {
1157
1158
  * @returns {object}
1158
1159
  * @private
1159
1160
  */
1160
- // eslint-disable-next-line complexity
1161
1161
  _buildExpandedCQN({ column, entity, readToOneCQN, toManyTree, mappings, parentAlias, defaultLanguage }) {
1162
1162
  const isUnion = !!readToOneCQN.from.SET
1163
1163
  const colRef = parentAlias === column.ref[0] ? column.ref.slice(1) : column.ref.slice(0)
@@ -1233,7 +1233,7 @@ class JoinCQNFromExpanded {
1233
1233
  const ks = Object.keys(expandedEntity.keys).filter(
1234
1234
  c => !expandedEntity.keys[c].isAssociation && !(c in DRAFT_COLUMNS_MAP)
1235
1235
  )
1236
- const user = (cds.context && cds.context.user && cds.context.user.id) || 'anonymous'
1236
+ const user = cds.context?.user.id
1237
1237
  const unionFrom = getCQNUnionFrom(cols, ref.replace(/_drafts$/, ''), ref, ks, user)
1238
1238
 
1239
1239
  for (const each of cqn.columns) {
@@ -1,6 +1,5 @@
1
1
  const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
2
2
  const DRAFT_COLUMNS_ARRAY = Object.keys(DRAFT_COLUMNS_MAP)
3
- const cds = require('../../cds')
4
3
 
5
4
  const EXPAND = Symbol.for('sap.cds.expand')
6
5
  const GET_KEY_VALUE = Symbol.for('sap.cds.getKeyValue')
@@ -85,7 +84,6 @@ class RawToExpanded {
85
84
  * @returns {object}
86
85
  * @private
87
86
  */
88
- // eslint-disable-next-line complexity
89
87
  _parseRaw({ mappings, toManyTree, conversionMapper, entry }) {
90
88
  let isEntityNull
91
89
 
@@ -110,12 +108,6 @@ class RawToExpanded {
110
108
  if (mapping[TO_MANY]) {
111
109
  let expandedItems = this._getResultCache(toManyTree.concat(key))[mapping[GET_KEY_VALUE](false, entry)] || []
112
110
 
113
- // the expanded items may include the actives of the deleted drafts -> filter out
114
- if (!cds.env.fiori.lean_draft && rootIsActiveEntity !== null) {
115
- if (mapping[TO_ACTIVE]) expandedItems = expandedItems.filter(ele => ele.IsActiveEntity !== false)
116
- else expandedItems = expandedItems.filter(ele => !!ele.IsActiveEntity === rootIsActiveEntity)
117
- }
118
-
119
111
  row[key] = !mapping[CLEANUP_KEYS]
120
112
  ? expandedItems
121
113
  : expandedItems.map(item => {
@@ -87,8 +87,8 @@ const _processCategory = (req, category, { row, key, element }) => {
87
87
  req.error({
88
88
  code: 'MUST_NOT_BE_NULL',
89
89
  message: 'Value is required',
90
- target: key + '[' + k + ']',
91
- args: [key + '[' + k + ']']
90
+ target: key + '[' + k.name + ']',
91
+ args: [key + '[' + k.name + ']']
92
92
  })
93
93
  return
94
94
  }
@@ -102,12 +102,7 @@ const _processCategory = (req, category, { row, key, element }) => {
102
102
  }
103
103
 
104
104
  // generate UUIDs
105
- if (
106
- category === 'uuid' &&
107
- !val &&
108
- req.event === 'CREATE' &&
109
- !element.parent.elements[element._foreignKey4]?._isAssociationStrict
110
- ) {
105
+ if (category === 'uuid' && !val && req.event === 'CREATE' && !element._foreignKey4) {
111
106
  row[key] = cds.utils.uuid()
112
107
  }
113
108
  }
@@ -2,13 +2,33 @@ const cds = require('../../cds')
2
2
  const { cqn2cqn4sql } = require('../../common/utils/cqn2cqn4sql')
3
3
  const { generateAliases } = require('../utils/generateAliases')
4
4
 
5
+ /**
6
+ * Restores the link of `req.data` and `req.query` in case `req.query` was overwritten.
7
+ * Only applicable for `UPDATE`s and `INSERT`s.
8
+ *
9
+ * @param { import('@sap/cds').Request } req
10
+ */
5
11
  const _restoreLink = req => {
6
12
  if (req.query.INSERT?.entries) {
7
- return (req.data = Array.isArray(req.query.INSERT.entries) ? req.query.INSERT.entries[0] : req.query.INSERT.entries)
13
+ if (Array.isArray(req.query.INSERT.entries)) req.data = req.query.INSERT.entries[0]
14
+ else req.data = req.query.INSERT.entries
15
+ } else if (req.query.UPDATE?.data) {
16
+ req.data = req.query.UPDATE.data
8
17
  }
18
+ }
19
+
20
+ const _isLinked = req => {
21
+ if (req.query.INSERT?.entries) {
22
+ // in case of more than one entry, the array reference stays in tact
23
+ if (Array.isArray(req.query.INSERT.entries)) return req.data === req.query.INSERT.entries[0]
24
+ return req.data === req.query.INSERT.entries
25
+ }
26
+
9
27
  if (req.query.UPDATE?.data) {
10
- return (req.data = req.query.UPDATE.data)
28
+ return req.data === req.query.UPDATE.data
11
29
  }
30
+
31
+ return false
12
32
  }
13
33
 
14
34
  function handler(req) {
@@ -30,14 +50,17 @@ function handler(req) {
30
50
 
31
51
  const _streaming = cds.env.features.stream_compat && req.query._streaming
32
52
 
53
+ // for restore link to req.data
54
+ const linked = _isLinked(req)
55
+
33
56
  // convert to sql cqn
34
57
  req.query = cqn2cqn4sql(req.query, this.model, { service: this })
35
58
 
59
+ // REVISIT: should not be necessary
36
60
  // restore link to req.data
37
- _restoreLink(req)
61
+ if (linked) _restoreLink(req)
38
62
 
39
63
  if (_streaming) req.query._streaming = _streaming
40
-
41
64
  generateAliases(req.query)
42
65
  }
43
66
 
@@ -1,6 +1,6 @@
1
1
  const cds = require('../../cds')
2
2
  const normalizeTimestamp = require('../../common/utils/normalizeTimestamp')
3
- const { deepCopyObject } = require('../../common/utils/copy')
3
+ const { deepCopy } = require('../../common/utils/copy')
4
4
  const getError = require('../../common/error')
5
5
 
6
6
  function _arrayWithCount(a, count) {
@@ -14,7 +14,7 @@ function _arrayWithCount(a, count) {
14
14
 
15
15
  function _createCountQuery(query) {
16
16
  // REVISIT: Use query.clone() instead
17
- let _query = { SELECT: deepCopyObject(query.SELECT) }
17
+ let _query = { SELECT: deepCopy(query.SELECT) }
18
18
  delete _query.SELECT.orderBy // not necessary to keep that
19
19
  delete _query.SELECT.limit
20
20
  // Also change columns in sub queries
@@ -139,7 +139,6 @@ class ExpressionBuilder extends BaseBuilder {
139
139
  * @returns {number}
140
140
  * @private
141
141
  */
142
- // eslint-disable-next-line complexity
143
142
  _reseverdKeyWords(objects, i) {
144
143
  const NOT_EQUAL = { '!=': 1, '<>': 1 }
145
144
  if (objects[i] === 'not' && objects[i + 1].func) {
@@ -161,7 +161,7 @@ class InsertBuilder extends BaseBuilder {
161
161
  const uuidKeys = []
162
162
  if (this._csn && this._csn.definitions[entityName] && this._csn.definitions[entityName].keys) {
163
163
  for (const key of Object.values(this._csn.definitions[entityName].keys)) {
164
- if (key.isUUID) {
164
+ if (key.isUUID && !key._foreignKey4) {
165
165
  uuidKeys.push(key.name)
166
166
  }
167
167
  }
@@ -1,10 +1,8 @@
1
1
  const cds = require('../../cds')
2
2
  const resolveStructured = require('../../common/utils/resolveStructured')
3
3
 
4
- const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
5
-
6
4
  const _isStreamProperty = element => {
7
- return element.type === 'cds.LargeBinary' || element['@Core.IsURL']
5
+ return element.type === 'cds.LargeBinary' || (element['@Core.MediaType'] && element['@Core.IsURL'])
8
6
  }
9
7
 
10
8
  /**
@@ -15,13 +13,12 @@ const _isStreamProperty = element => {
15
13
  * @param entity - the csn entity
16
14
  * @returns {Array} - array of columns
17
15
  */
18
- const getColumns = (entity, { _4db, onlyKeys, omitStream } = { _4db: true, onlyKeys: false, omitStream: false }) => {
16
+ const getColumns = (entity, { onlyKeys, omitStream } = { onlyKeys: false, omitStream: false }) => {
19
17
  // REVISIT is this correct or just a problem that occurs because of new structure we do not deal with yet?
20
18
  if (!(entity && entity.elements)) return []
21
19
  const columnNames = []
22
20
  // REVISIT!!!
23
21
  const { structs = cds.env.features.ucsn_struct_conversion } = cds.env.effective.odata
24
- const { lean_draft } = cds.env.fiori
25
22
  const elements = entity.elements
26
23
  for (const elementName in elements) {
27
24
  const element = elements[elementName]
@@ -29,7 +26,6 @@ const getColumns = (entity, { _4db, onlyKeys, omitStream } = { _4db: true, onlyK
29
26
  if (onlyKeys && !element.key) continue
30
27
  if (omitStream && _isStreamProperty(element)) continue
31
28
  if (element.isAssociation) continue
32
- if (!lean_draft && _4db && entity._isDraftEnabled && elementName in DRAFT_COLUMNS_MAP) continue
33
29
  if (structs && element.elements) {
34
30
  columnNames.push(...resolveStructured({ element, structProperties: [] }, false))
35
31
  continue