@sap/cds 9.0.4 → 9.2.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 (77) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/bin/deploy.js +29 -0
  3. package/bin/serve.js +1 -5
  4. package/lib/compile/etc/csv.js +11 -6
  5. package/lib/compile/for/lean_drafts.js +29 -7
  6. package/lib/compile/load.js +8 -5
  7. package/lib/compile/to/hdbtabledata.js +1 -1
  8. package/lib/dbs/cds-deploy.js +5 -34
  9. package/lib/env/cds-env.js +2 -1
  10. package/lib/env/cds-requires.js +4 -1
  11. package/lib/env/defaults.js +0 -11
  12. package/lib/env/schemas/cds-rc.js +218 -6
  13. package/lib/index.js +38 -38
  14. package/lib/log/cds-error.js +12 -11
  15. package/lib/log/format/json.js +1 -1
  16. package/lib/ql/SELECT.js +31 -0
  17. package/lib/ql/resolve.js +1 -1
  18. package/lib/req/context.js +1 -1
  19. package/lib/req/request.js +1 -1
  20. package/lib/req/validate.js +17 -19
  21. package/lib/srv/cds.Service.js +18 -28
  22. package/lib/srv/middlewares/auth/ias-auth.js +29 -2
  23. package/lib/srv/middlewares/auth/jwt-auth.js +11 -1
  24. package/lib/srv/middlewares/auth/xssec.js +1 -1
  25. package/lib/srv/srv-models.js +1 -1
  26. package/lib/srv/srv-tx.js +2 -2
  27. package/lib/utils/cds-utils.js +35 -2
  28. package/lib/utils/csv-reader.js +1 -1
  29. package/lib/utils/inflect.js +2 -2
  30. package/lib/utils/tar.js +60 -23
  31. package/lib/utils/version.js +18 -0
  32. package/libx/_runtime/cds.js +1 -1
  33. package/libx/_runtime/common/aspects/any.js +1 -23
  34. package/libx/_runtime/common/generic/crud.js +1 -3
  35. package/libx/_runtime/common/generic/input.js +113 -52
  36. package/libx/_runtime/common/generic/sorting.js +1 -1
  37. package/libx/_runtime/common/generic/temporal.js +0 -6
  38. package/libx/_runtime/common/utils/draft.js +1 -1
  39. package/libx/_runtime/common/utils/entityFromCqn.js +1 -1
  40. package/libx/_runtime/common/utils/propagateForeignKeys.js +1 -1
  41. package/libx/_runtime/common/utils/resolveView.js +2 -2
  42. package/libx/_runtime/common/utils/structured.js +2 -2
  43. package/libx/_runtime/common/utils/templateProcessor.js +0 -5
  44. package/libx/_runtime/common/utils/vcap.js +1 -1
  45. package/libx/_runtime/fiori/lean-draft.js +529 -143
  46. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +3 -2
  47. package/libx/_runtime/messaging/service.js +1 -1
  48. package/libx/_runtime/remote/utils/client.js +2 -1
  49. package/libx/common/assert/utils.js +2 -12
  50. package/libx/common/utils/streaming.js +4 -9
  51. package/libx/http/location.js +1 -0
  52. package/libx/odata/ODataAdapter.js +47 -43
  53. package/libx/odata/index.js +1 -1
  54. package/libx/odata/middleware/batch.js +6 -2
  55. package/libx/odata/middleware/create.js +1 -1
  56. package/libx/odata/middleware/error.js +27 -17
  57. package/libx/odata/middleware/operation.js +15 -21
  58. package/libx/odata/middleware/stream.js +1 -1
  59. package/libx/odata/parse/afterburner.js +22 -8
  60. package/libx/odata/parse/cqn2odata.js +16 -10
  61. package/libx/odata/parse/grammar.peggy +185 -134
  62. package/libx/odata/parse/parser.js +1 -1
  63. package/libx/odata/utils/index.js +1 -36
  64. package/libx/odata/utils/metadata.js +34 -1
  65. package/libx/odata/utils/odataBind.js +2 -1
  66. package/libx/odata/utils/result.js +22 -20
  67. package/libx/queue/index.js +7 -4
  68. package/libx/rest/RestAdapter.js +1 -2
  69. package/libx/rest/middleware/create.js +5 -2
  70. package/package.json +2 -2
  71. package/server.js +1 -1
  72. package/bin/deploy/to-hana.js +0 -1
  73. package/lib/utils/check-version.js +0 -9
  74. package/lib/utils/unit.js +0 -19
  75. package/libx/_runtime/cds-services/util/assert.js +0 -181
  76. package/libx/_runtime/types/api.js +0 -129
  77. package/libx/common/assert/validation.js +0 -109
package/lib/utils/tar.js CHANGED
@@ -1,3 +1,4 @@
1
+ const { PassThrough } = require('stream')
1
2
  const child_process = require('child_process')
2
3
  const spawn = /\btar\b/.test(process.env.DEBUG) ? (cmd, args, options) => {
3
4
  Error.captureStackTrace(spawn,spawn)
@@ -8,26 +9,36 @@ const spawn = /\btar\b/.test(process.env.DEBUG) ? (cmd, args, options) => {
8
9
  const cds = require('../index'), { fs, path, mkdirp, exists, rimraf } = cds.utils
9
10
  const _resolve = (...x) => path.resolve (cds.root,...x)
10
11
 
11
- // tar does not work properly on Windows (by npm/jest tests) w/o this change
12
+ // ======= ONLY_FOR_WINDOWS ======
13
+ // This section contains logic relevant for Windows OS.
14
+
15
+ // tar does not work properly on Windows w/o this change
12
16
  const win = path => {
13
17
  if (!path) return path
14
18
  if (typeof path === 'string') return path.replace('C:', '//localhost/c$').replace(/\\+/g, '/')
15
19
  if (Array.isArray(path)) return path.map(el => win(el))
16
20
  }
17
21
 
18
- async function copyDir(src, dest) {
22
+ // spawn tar on Windows, using the cli version
23
+ const winSpawnDir = (dir, args) => {
24
+ if (args.some(arg => arg === '-f')) return spawn ('tar', ['c', '-C', win(dir), ...win(args)])
25
+ else return spawn ('tar', ['cf', '-', '-C', win(dir), ...win(args)])
26
+ }
27
+
28
+ // copy a directory recursively on Windows, using fs.promises
29
+ async function winCopyDir(src, dest) {
19
30
  if ((await fs.promises.stat(src)).isDirectory()) {
20
31
  const entries = await fs.promises.readdir(src)
21
- return Promise.all(entries.map(async each => copyDir(path.join(src, each), path.join(dest, each))))
32
+ return Promise.all(entries.map(async each => winCopyDir(path.join(src, each), path.join(dest, each))))
22
33
  } else {
23
34
  await fs.promises.mkdir(path.dirname(dest), { recursive: true })
24
35
  return fs.promises.copyFile(src, dest)
25
36
  }
26
37
  }
27
38
 
28
- // Copy resources containing files and folders to temp dir on Windows and pack temp dir.
29
- // cli tar has a size limit on Windows.
30
- const createTemp = async (root, resources) => {
39
+ // copy resources containing files and folders to temp dir on Windows
40
+ // cli tar has a size limit on Windows
41
+ const winCreateTemp = async (root, resources) => {
31
42
  // Asynchronously copies the entire content from src to dest.
32
43
  const temp = await fs.promises.mkdtemp(`${fs.realpathSync(require('os').tmpdir())}${path.sep}tar-`)
33
44
  for (let resource of resources) {
@@ -43,7 +54,7 @@ const createTemp = async (root, resources) => {
43
54
  await fs.promises.cp(resource, destination, { recursive: true })
44
55
  } else {
45
56
  // node < 16
46
- await copyDir(resource, destination)
57
+ await winCopyDir(resource, destination)
47
58
  }
48
59
  }
49
60
  }
@@ -51,6 +62,43 @@ const createTemp = async (root, resources) => {
51
62
  return temp
52
63
  }
53
64
 
65
+ // spawn tar on Windows, using a temp dir, which is copied from the original dir
66
+ // cli tar has a size limit on Windows
67
+ const winSpawnTempDir = (dir, args) => {
68
+ // Synchronous trick: use a PassThrough as placeholder
69
+ const stdout = new PassThrough()
70
+ const stderr = new PassThrough()
71
+ const c = {
72
+ stdout,
73
+ stderr,
74
+ on: (...a) => { stdout.on(...a); stderr.on(...a); return c },
75
+ once: (...a) => { stdout.once(...a); stderr.once(...a); return c },
76
+ kill: () => {},
77
+ }
78
+
79
+ // async copy, then swap streams/events
80
+ winCreateTemp(dir, args.shift()).then(tempPath => {
81
+ const real = winSpawnDir(tempPath, args)
82
+ real.stdout.pipe(stdout)
83
+ real.stderr && real.stderr.pipe(stderr)
84
+ const cleanup = () => exists(tempPath) && rimraf(tempPath)
85
+ real.on('close', (...ev) => {
86
+ stdout.emit('close', ...ev)
87
+ stderr.emit('close', ...ev)
88
+ cleanup()
89
+ })
90
+ real.on('error', (...ev) => {
91
+ stdout.emit('error', ...ev)
92
+ stderr.emit('error', ...ev)
93
+ cleanup()
94
+ })
95
+ c.kill = (...ev) => real.kill(...ev)
96
+ })
97
+ return c
98
+ }
99
+
100
+ // ====== END ONLY_FOR_WINDOWS ======
101
+
54
102
  const tarInfo = async (info) => {
55
103
  let cmd, param
56
104
  if (info === 'version') {
@@ -118,19 +166,12 @@ exports.create = (dir='.', ...args) => {
118
166
  if (typeof dir === 'string') dir = _resolve(dir)
119
167
  if (Array.isArray(dir)) [ dir, ...args ] = [ cds.root, dir, ...args ]
120
168
 
121
- let c, temp
169
+ let c
122
170
  args = args.filter(el => el)
123
- if (process.platform === 'win32') {
124
- const spawnDir = (dir, args) => {
125
- if (args.some(arg => arg === '-f')) return spawn ('tar', ['c', '-C', win(dir), ...win(args)])
126
- else return spawn ('tar', ['cf', '-', '-C', win(dir), ...win(args)])
127
- }
171
+ if (process.platform === 'win32') {
128
172
  args.push('.')
129
- if (Array.isArray(args[0])) {
130
- c = createTemp(dir, args.shift()) .then (t => spawnDir(t,args))
131
- } else {
132
- c = spawnDir(dir, args)
133
- }
173
+ if (Array.isArray(args[0])) c = winSpawnTempDir(dir, args)
174
+ else c = winSpawnDir(dir, args)
134
175
  } else {
135
176
  if (Array.isArray(args[0])) {
136
177
  args.push (...args.shift().map (f => path.isAbsolute(f) ? path.relative(dir,f) : f))
@@ -153,11 +194,7 @@ exports.create = (dir='.', ...args) => {
153
194
  c.stdout.on('data', d => data.push(d))
154
195
  c.stderr.on('data', d => stderr += d)
155
196
  c.on('close', code => code ? reject(new Error(stderr)) : resolve(Buffer.concat(data)))
156
- c.on('error', reject)
157
- if (process.platform === 'win32') {
158
- c.on('close', () => temp && exists(temp) && rimraf(temp))
159
- c.on('error', () => temp && exists(temp) && rimraf(temp))
160
- }
197
+ c.on('error', reject)
161
198
  },
162
199
 
163
200
  /**
@@ -0,0 +1,18 @@
1
+ const semver = exports = module.exports = (x,y,z) => {
2
+ if (typeof x === 'string') [ x,y,z ] = String(x).split('.')
3
+ return 1e6 * (x||0) + 1e3 * (y||0) + +(z||0)
4
+ }
5
+
6
+ exports.checkNodeVersion = (cds = require ('../../package.json')) => {
7
+ let required = cds.engines?.node?.slice(2) //> e.g. >=22
8
+ let current = process.version.slice(1) //> e.g. v24.4.1
9
+ if (semver(current) >= semver(required)) return; else process.stderr.write (`
10
+ Node.js version ${required} or higher is required for @sap/cds v${cds.version}.
11
+ Current version ${current} does not satisfy this. \n\n`)
12
+ return process.exit(1)
13
+ }
14
+
15
+ exports.check = (x, min, max) => {
16
+ let v = semver(x)
17
+ return (!min || semver(min) <= v) && (!max || v <= semver(max))
18
+ }
@@ -16,7 +16,7 @@ cds.extend(service).with(require('./common/aspects/service'))
16
16
  */
17
17
  cds.Service.prototype._requires_resolving = function (req) {
18
18
  if (req._resolved) return false
19
- if (!this.model) return false
19
+ if (!this.definition) return false
20
20
  if (!req.query || typeof req.query !== 'object') return false
21
21
  if (Array.isArray(req.query)) return false
22
22
  if (Object.keys(req.query).length === 0) return false
@@ -1,20 +1,10 @@
1
- const { foreignKey4 } = require('../../common/utils/foreignKeyPropagations')
1
+ const { foreignKey4 } = require('../utils/foreignKeyPropagations')
2
2
 
3
3
  const _getCommonFieldControl = e => {
4
4
  const cfr = e['@Common.FieldControl']
5
5
  return cfr && cfr['#']
6
6
  }
7
7
 
8
- const _isMandatory = e => {
9
- return (
10
- e['@assert.mandatory'] !== false &&
11
- (e['@mandatory'] ||
12
- e['@Common.FieldControl.Mandatory'] ||
13
- e['@FieldControl.Mandatory'] ||
14
- _getCommonFieldControl(e) === 'Mandatory')
15
- )
16
- }
17
-
18
8
  const _isReadOnly = e => {
19
9
  return (
20
10
  e['@readonly'] ||
@@ -34,22 +24,10 @@ module.exports = class {
34
24
  return this.own('__isStructured', () => !!this.elements && this.kind !== 'entity')
35
25
  }
36
26
 
37
- get _isMandatory() {
38
- return this.own('__isMandatory', () => !this.isAssociation && _isMandatory(this))
39
- }
40
-
41
27
  get _isReadOnly() {
42
28
  return this.own('__isReadOnly', () => !this.key && _isReadOnly(this))
43
29
  }
44
30
 
45
- get _mandatories() {
46
- return this.own(
47
- '__mandatories',
48
- // eslint-disable-next-line no-unused-vars
49
- () => this.elements && Object.entries(this.elements).filter(([_, v]) => v._isMandatory)
50
- )
51
- }
52
-
53
31
  get _foreignKey4() {
54
32
  return this.own('__foreignKey4', () => foreignKey4(this))
55
33
  }
@@ -78,9 +78,7 @@ module.exports = cds.service.impl(function () {
78
78
  if (await _targetEntityDoesNotExist(req)) req.reject(404) // REVISIT: add a reasonable error message
79
79
  }
80
80
 
81
- // flag to trigger read after write in legacy odata adapter
82
- if (req.constructor.name in { ODataRequest: 1 }) req._.readAfterWrite = true
83
- if (req.protocol?.match(/odata/)) req._.readAfterWrite = true //> REVISIT for noah
81
+ if (req.protocol?.match(/odata/)) req._.readAfterWrite = true
84
82
 
85
83
  return req.data
86
84
  })
@@ -13,11 +13,11 @@ const LOG = cds.log('app')
13
13
  const { Readable } = require('node:stream')
14
14
 
15
15
  const { enrichDataWithKeysFromWhere } = require('../utils/keys')
16
- const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
16
+ const { DRAFT_COLUMNS_MAP } = require('../constants/draft')
17
17
  const propagateForeignKeys = require('../utils/propagateForeignKeys')
18
- const { checkInputConstraints, assertTargets } = require('../../cds-services/util/assert')
19
18
  const getTemplate = require('../utils/template')
20
19
  const getRowUUIDGeneratorFn = require('../utils/rowUUIDGenerator')
20
+ const templatePathSerializer = require('../utils/templateProcessorPathSerializer')
21
21
 
22
22
  const _shouldSuppressErrorPropagation = (event, value) => {
23
23
  return (
@@ -96,6 +96,113 @@ const _preProcessAssertTarget = (assocInfo, assertMap) => {
96
96
  })
97
97
  }
98
98
 
99
+ const _enumValues = element => {
100
+ return Object.keys(element).map(enumKey => {
101
+ const enum_ = element[enumKey]
102
+ const enumValue = enum_ && enum_.val
103
+
104
+ if (enumValue !== undefined) {
105
+ if (enumValue['=']) return enumValue['=']
106
+ if (enum_ && enum_.literal && enum_.literal === 'number') return Number(enumValue)
107
+ return enumValue
108
+ }
109
+
110
+ return enumKey
111
+ })
112
+ }
113
+
114
+ // REVISIT: this needs a cleanup!
115
+ const _assertError = (code, element, value, key, path) => {
116
+ let args
117
+
118
+ if (typeof code === 'object') {
119
+ args = code.args
120
+ code = code.code
121
+ }
122
+
123
+ const { name, type, precision, scale } = element
124
+ const error = new Error()
125
+ const errorEntry = {
126
+ code,
127
+ message: code,
128
+ target: path ?? element.name ?? key,
129
+ args: args ?? [name ?? key]
130
+ }
131
+
132
+ const assertError = Object.assign(error, errorEntry)
133
+ Object.assign(assertError, {
134
+ entity: element.parent && element.parent.name,
135
+ element: name, // > REVISIT: when is error.element needed?
136
+ type: element.items ? element.items._type : type,
137
+ status: 400,
138
+ value
139
+ })
140
+
141
+ if (element.enum) assertError.enum = _enumValues(element)
142
+ if (precision) assertError.precision = precision
143
+ if (scale) assertError.scale = scale
144
+
145
+ if (element.target) {
146
+ // REVISIT: when does this case apply?
147
+ assertError.target = element.target
148
+ }
149
+
150
+ return assertError
151
+ }
152
+
153
+ /**
154
+ * Check whether the target entity referenced by the association (the reference's target) exists and assert an error if
155
+ * the the reference's target doesn't exist.
156
+ *
157
+ * In other words, use this annotation to check whether a non-null foreign key input in a table has a corresponding
158
+ * primary key (also known as a parent key) in the associated/referenced target table (also known as a parent table).
159
+ *
160
+ * @param {object} assertMap - Map containing the targets to assert.
161
+ * @param {array} errors - Array to collect errors.
162
+ * @see {@link https://cap.cloud.sap/docs/guides/providing-services#assert-target @assert.target} for further information.
163
+ */
164
+ const _assertTargets = async (assertMap, errors) => {
165
+ const { targets: targetsMap, allTargets } = assertMap
166
+ if (targetsMap.size === 0) return
167
+
168
+ const targets = Array.from(targetsMap.values())
169
+ const transactions = targets.map(({ keys, entity }) => {
170
+ const where = Object.assign({}, ...keys)
171
+ return cds.db.exists(entity, where).forShareLock()
172
+ })
173
+ const targetsExistsResults = await Promise.allSettled(transactions)
174
+
175
+ targetsExistsResults.forEach((txPromise, index) => {
176
+ const isPromiseRejected = txPromise.status === 'rejected'
177
+ const shouldAssertError = (txPromise.status === 'fulfilled' && txPromise.value == null) || isPromiseRejected
178
+ if (!shouldAssertError) return
179
+
180
+ const target = targets[index]
181
+ const { element } = target.assocInfo
182
+
183
+ if (isPromiseRejected) {
184
+ LOG._debug &&
185
+ LOG.debug(
186
+ `The transaction to check the @assert.target constraint for foreign key "${element.name}" failed`,
187
+ txPromise.reason
188
+ )
189
+
190
+ throw new Error(txPromise.reason.message)
191
+ }
192
+
193
+ allTargets
194
+ .filter(t => t.key === target.key)
195
+ .forEach(target => {
196
+ const { row, pathSegmentsInfo } = target.assocInfo
197
+ const key = target.foreignKey.name
198
+ let path
199
+ if (pathSegmentsInfo?.length) path = templatePathSerializer(key, pathSegmentsInfo)
200
+ const error = _assertError('ASSERT_TARGET', target.foreignKey, row[key], key, path)
201
+ errors.push(error)
202
+ })
203
+ })
204
+ }
205
+
99
206
  const _processCategory = (req, category, value, elementInfo, assertMap) => {
100
207
  const { row, key, element, isRoot } = elementInfo
101
208
  category = _getSimpleCategory(category)
@@ -166,7 +273,7 @@ const _getProcessorFn = (req, errors, assertMap) => {
166
273
  const event = req.event
167
274
 
168
275
  return elementInfo => {
169
- const { row, key, element, plain, pathSegmentsInfo } = elementInfo
276
+ const { row, key, plain } = elementInfo
170
277
  // ugly pointer passing for sonar
171
278
  const value = { mandatory: false, val: row && row[key] }
172
279
 
@@ -175,9 +282,6 @@ const _getProcessorFn = (req, errors, assertMap) => {
175
282
  }
176
283
 
177
284
  if (_shouldSuppressErrorPropagation(event, value)) return
178
-
179
- // REVISIT: Convert checkInputConstraints to template mechanism
180
- checkInputConstraints({ element, value: value.val, errors, pathSegmentsInfo, event })
181
285
  }
182
286
  }
183
287
 
@@ -251,7 +355,7 @@ async function validate_input(req) {
251
355
  }
252
356
 
253
357
  const errs = cds.validate(req.data, req.target, assertOptions)
254
- if (errs) return req._errors.push(...errs)
358
+ if (errs) return errs.forEach(err => req.error(err))
255
359
 
256
360
  // -------------------------------------------------
257
361
  // REVISIT: is the below still needed?
@@ -276,49 +380,12 @@ async function validate_input(req) {
276
380
  pathSegmentsInfo: []
277
381
  })
278
382
  if (assertMap.targets.size > 0) {
279
- await assertTargets(assertMap, errors)
383
+ await _assertTargets(assertMap, errors)
280
384
  }
281
385
 
282
386
  if (errors.length) for (const error of errors) req.error(error)
283
387
  }
284
388
 
285
- const _getProcessorFnForActionsFunctions =
286
- (errors, opName) =>
287
- ({ row, key, element }) => {
288
- const value = row && row[key]
289
-
290
- // REVISIT: Convert checkInputConstraints to template mechanism
291
- checkInputConstraints({ element, value, errors, key: opName })
292
- }
293
-
294
- const _processActionFunctionRow = (row, param, key, errors, event, service) => {
295
- const values = Array.isArray(row[key]) ? row[key] : [row[key]]
296
-
297
- // unstructured
298
- for (const value of values) {
299
- checkInputConstraints({ element: param, value, errors, key })
300
- }
301
-
302
- // structured
303
- const template = getTemplate('app-input-operation', service, param, {
304
- pick: _pick,
305
- ignore: element => element._isAssociationStrict
306
- })
307
-
308
- template.process(values, _getProcessorFnForActionsFunctions(errors, key))
309
- }
310
-
311
- const _processActionFunction = (row, eventParams, errors, event, service) => {
312
- for (const key in eventParams) {
313
- let param = eventParams[key]
314
-
315
- // .type of action/function behaves different to .type of other csn elements
316
- const _type = param.type
317
- if (!_type && param.items) param = param.items
318
- _processActionFunctionRow(row, param, key, errors, event, service)
319
- }
320
- }
321
-
322
389
  function validate_action(req) {
323
390
  const operation = this.actions?.[req.event] || req.target?.actions?.[req.event]
324
391
  if (!operation) return
@@ -332,13 +399,7 @@ function validate_action(req) {
332
399
  protocol: req.protocol
333
400
  }
334
401
  let errs = cds.validate(data, operation, assertOptions)
335
- if (errs) return req._errors.push(...errs)
336
-
337
- // REVISIT: we still need the following because cds.validate doesn't check for @mandatory params (both flat and nested)
338
- const errors = []
339
- const arrayData = Array.isArray(data) ? data : [data]
340
- for (const row of arrayData) _processActionFunction(row, operation.params, errors, req.event, this)
341
- if (errors.length) for (const error of errors) req.error(error)
402
+ if (errs) return errs.forEach(err => req.error(err))
342
403
 
343
404
  // convert binaries
344
405
  operation.params &&
@@ -1,5 +1,5 @@
1
1
  const cds = require('../../cds')
2
- const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
2
+ const { DRAFT_COLUMNS_MAP } = require('../constants/draft')
3
3
 
4
4
  const _getStaticOrders = req => {
5
5
  const { target: entity, query } = req
@@ -76,12 +76,6 @@ function handle_temporal_data(req) {
76
76
  _getDateFromQueryOptions(_queryOptions['sap-valid-to'] ?? normalizeTimestamp('9999-12-31T23:59:59.9999999Z'))
77
77
  )
78
78
  }
79
-
80
- // REVISIT: needed without okra
81
- if (req.constructor.name !== 'ODataRequest') {
82
- req._['VALID-FROM'] = _['VALID-FROM']
83
- req._['VALID-TO'] = _['VALID-TO']
84
- }
85
79
  }
86
80
  handle_temporal_data._initial = true
87
81
 
@@ -1,5 +1,5 @@
1
1
  const cds = require('../../../../lib')
2
- const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
2
+ const { DRAFT_COLUMNS_MAP } = require('../constants/draft')
3
3
 
4
4
  const _4sqlite = cds.env.i18n && Array.isArray(cds.env.i18n.for_sqlite) ? cds.env.i18n.for_sqlite : []
5
5
  // compiler reserves 'localized' and raises a corresponding exception if used in models
@@ -1,4 +1,4 @@
1
- const { ensureNoDraftsSuffix } = require('../../common/utils/draft')
1
+ const { ensureNoDraftsSuffix } = require('./draft')
2
2
 
3
3
  const traverseFroms = (cqn, cb, aliasForSet) => {
4
4
  while (cqn.SELECT) cqn = cqn.SELECT.from
@@ -1,6 +1,6 @@
1
1
  const cds = require('../../cds')
2
2
 
3
- const { prefixForStruct } = require('../../common/utils/csn')
3
+ const { prefixForStruct } = require('./csn')
4
4
 
5
5
  const _autoGenerate = e => e && e.isUUID && e.key
6
6
 
@@ -1,7 +1,7 @@
1
1
  const cds = require('../../../../lib')
2
2
  let LOG = cds.log('app')
3
3
 
4
- const { rewriteAsterisks } = require('../../common/utils/rewriteAsterisks')
4
+ const { rewriteAsterisks } = require('./rewriteAsterisks')
5
5
 
6
6
  const _setInverseTransition = (mapping, ref, mapped) => {
7
7
  const existing = mapping.get(ref)
@@ -531,7 +531,7 @@ const _mappedValue = (col, alias) => {
531
531
  const getDBTable = target => cds.ql.resolve.table(target)
532
532
 
533
533
  const _appendForeignKeys = (newColumns, target, columns, { as, ref = [] }) => {
534
- const el = target.elements[as] || target.query._target.elements[ref.at(-1)]
534
+ const el = target.elements[as] || target.query._target?.elements[ref.at(-1)]
535
535
 
536
536
  if (el && el.isAssociation && el.keys) {
537
537
  for (const key of el.keys) {
@@ -1,6 +1,6 @@
1
1
  const resolveStructured = require('./resolveStructured')
2
- const { ensureNoDraftsSuffix } = require('../../common/utils/draft')
3
- const { traverseFroms } = require('../../common/utils/entityFromCqn')
2
+ const { ensureNoDraftsSuffix } = require('./draft')
3
+ const { traverseFroms } = require('./entityFromCqn')
4
4
 
5
5
  const OPERATIONS_MAP = ['=', '>', '<', '!=', '<>', '>=', '<=', 'like', 'between', 'in', 'not in'].reduce((acc, cur) => {
6
6
  acc[cur] = 1
@@ -6,7 +6,6 @@ const _processElement = (processFn, row, key, target, picked = {}, isRoot, pathS
6
6
 
7
7
  if (!plain) return
8
8
 
9
- /** @type import('../../types/api').templateElementInfo */
10
9
  const elementInfo = { row, key, element, target, plain, isRoot, pathSegmentsInfo }
11
10
 
12
11
  if (!element && target._flat2struct?.[key] && elementInfo.pathSegmentsInfo) {
@@ -53,7 +52,6 @@ const _processComplex = (processFn, row, template, key, pathOptions) => {
53
52
  let pathSegmentInfo
54
53
  if (pathOptions.includeKeyValues) {
55
54
  pathOptions.rowUUIDGenerator?.(keyNames, row, template)
56
- /** @type import('../../types/api').pathSegmentInfo */
57
55
  pathSegmentInfo = { key, keyNames, row, elements: template.target.elements, draftKeys: pathOptions.draftKeys }
58
56
  }
59
57
 
@@ -63,9 +61,6 @@ const _processComplex = (processFn, row, template, key, pathOptions) => {
63
61
  }
64
62
  }
65
63
 
66
- /**
67
- * @param {import("../../types/api").TemplateProcessor} args
68
- */
69
64
  const templateProcessor = ({ processFn, data, template, isRoot = true, pathOptions = {} }) => {
70
65
  if (!template || !template.elements.size || !data || typeof data !== 'object') return
71
66
  const dataArr = Array.isArray(data) ? data : [data]
@@ -1,4 +1,4 @@
1
- const cds = require('../../../../libx/_runtime/cds')
1
+ const cds = require('../../cds')
2
2
 
3
3
  const getAppMetadata = () => {
4
4
  const appMetadata = cds.env.app