@sap/cds 8.7.1 → 8.7.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.
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
- The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
5
5
|
- This project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## Version 8.7.2 - 2025-02-14
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Strip `Z` suffix of values of `cds.Timestamp` with OData type `Edm.DateTime`
|
|
12
|
+
- Skip validation for mandatory fields in update scenarios for entities in draft activation
|
|
13
|
+
- `cds.compile.to.yaml` escapes strings including colons if necessary
|
|
14
|
+
|
|
7
15
|
## Version 8.7.1 - 2025-02-04
|
|
8
16
|
|
|
9
17
|
### Fixed
|
package/lib/compile/to/yaml.js
CHANGED
|
@@ -29,7 +29,7 @@ module.exports = function _2yaml (object, {limit=111}={}) {
|
|
|
29
29
|
if (typeof o === 'string') {
|
|
30
30
|
if (o.indexOf('\n')>=0) return '|'+'\n'+indent+ o.replace(/\n/g,'\n'+indent)
|
|
31
31
|
let s = o.trim()
|
|
32
|
-
return !s || /^[\^@#:,=!<>*|]/.test(s)
|
|
32
|
+
return !s || /^[\^@#:,=!<>*|]/.test(s) || /:\s/.test(o) ? '"'+ o.replace(/\\/g,'\\\\') +'"' : s
|
|
33
33
|
}
|
|
34
34
|
if (typeof o === 'function') return
|
|
35
35
|
else return o
|
package/lib/req/validate.js
CHANGED
|
@@ -171,7 +171,8 @@ const $any = class any {
|
|
|
171
171
|
// different keys and thus different insert checks.
|
|
172
172
|
const _is_insert = this.own('__is_insert', () => {
|
|
173
173
|
const entity = this._target || this
|
|
174
|
-
|
|
174
|
+
let keys = Object.keys (entity.keys||{})
|
|
175
|
+
keys = keys.filter(k => !entity.elements[k].virtual)
|
|
175
176
|
if (!keys.length) return ()=> true
|
|
176
177
|
else return data => typeof data === 'object' && !keys.every(k => k in data)
|
|
177
178
|
})
|
|
@@ -560,8 +560,7 @@ const read = service => {
|
|
|
560
560
|
odataReq.getBatchApplicationData().results[changeset].push({ result, req })
|
|
561
561
|
} else if (result.value && isStreaming(odataReq.getUriInfo().getPathSegments())) {
|
|
562
562
|
if (odataRes._response.destroyed) {
|
|
563
|
-
err = new
|
|
564
|
-
err.code = 'ERR_STREAM_PREMATURE_CLOSE'
|
|
563
|
+
err = new cds.error({ code: 'ERR_STREAM_PREMATURE_CLOSE', message: 'Response was closed while streaming' })
|
|
565
564
|
tx.rollback(err).catch(() => {})
|
|
566
565
|
} else {
|
|
567
566
|
// REVISIT: temp workaround for url streaming
|
|
@@ -574,7 +573,10 @@ const read = service => {
|
|
|
574
573
|
})
|
|
575
574
|
odataRes._response.on('close', () => {
|
|
576
575
|
if (!finished) {
|
|
577
|
-
err = new
|
|
576
|
+
err = new cds.error({
|
|
577
|
+
code: 'ERR_STREAM_PREMATURE_CLOSE',
|
|
578
|
+
message: 'Response was closed while streaming'
|
|
579
|
+
})
|
|
578
580
|
tx.rollback(err).catch(() => {})
|
|
579
581
|
}
|
|
580
582
|
})
|
|
@@ -232,13 +232,23 @@ module.exports = adapter => {
|
|
|
232
232
|
_setStreamingHeaders(result, res)
|
|
233
233
|
|
|
234
234
|
return new Promise((resolve, reject) => {
|
|
235
|
-
if (res.destroyed)
|
|
235
|
+
if (res.destroyed)
|
|
236
|
+
return reject(
|
|
237
|
+
new cds.error({ code: 'ERR_STREAM_PREMATURE_CLOSE', message: 'Response was closed while streaming' })
|
|
238
|
+
)
|
|
236
239
|
stream.pipe(res)
|
|
237
240
|
stream.on('end', () => resolve(result))
|
|
238
241
|
stream.once('error', reject)
|
|
239
242
|
let finished = false
|
|
240
243
|
res.on('finish', () => (finished = true))
|
|
241
|
-
res.on(
|
|
244
|
+
res.on(
|
|
245
|
+
'close',
|
|
246
|
+
() =>
|
|
247
|
+
!finished &&
|
|
248
|
+
reject(
|
|
249
|
+
new cds.error({ code: 'ERR_STREAM_PREMATURE_CLOSE', message: 'Response was closed while streaming' })
|
|
250
|
+
)
|
|
251
|
+
)
|
|
242
252
|
})
|
|
243
253
|
})
|
|
244
254
|
})
|
|
@@ -145,7 +145,11 @@ const _v2 = (val, element) => {
|
|
|
145
145
|
case 'cds.Time':
|
|
146
146
|
return `time'${_PT(val.split(':'))}'`
|
|
147
147
|
case 'cds.Timestamp':
|
|
148
|
-
return element['@odata.Type'] === 'Edm.DateTime'
|
|
148
|
+
return element['@odata.Type'] === 'Edm.DateTime'
|
|
149
|
+
? val.endsWith('Z')
|
|
150
|
+
? `datetime'${val.slice(0, -1)}'`
|
|
151
|
+
: `datetime'${val}'`
|
|
152
|
+
: `datetimeoffset'${val}'`
|
|
149
153
|
// bool
|
|
150
154
|
case 'cds.Boolean':
|
|
151
155
|
return val
|