@sap/cds 7.2.1 → 7.3.1

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 (59) hide show
  1. package/CHANGELOG.md +168 -126
  2. package/README.md +1 -1
  3. package/apis/core.d.ts +6 -4
  4. package/apis/services.d.ts +24 -4
  5. package/apis/test.d.ts +24 -10
  6. package/bin/serve.js +4 -3
  7. package/lib/auth/ias-auth.js +7 -8
  8. package/lib/compile/cdsc.js +5 -7
  9. package/lib/compile/etc/csv.js +22 -11
  10. package/lib/compile/for/lean_drafts.js +1 -1
  11. package/lib/dbs/cds-deploy.js +1 -2
  12. package/lib/env/cds-env.js +26 -20
  13. package/lib/env/defaults.js +4 -3
  14. package/lib/env/schema.js +9 -0
  15. package/lib/i18n/localize.js +83 -77
  16. package/lib/index.js +6 -2
  17. package/lib/linked/classes.js +13 -13
  18. package/lib/plugins.js +41 -45
  19. package/lib/req/user.js +2 -2
  20. package/lib/srv/protocols/_legacy.js +0 -1
  21. package/lib/srv/protocols/odata-v4.js +4 -0
  22. package/lib/utils/axios.js +7 -1
  23. package/lib/utils/cds-test.js +140 -133
  24. package/lib/utils/cds-utils.js +10 -3
  25. package/lib/utils/check-version.js +6 -0
  26. package/lib/utils/data.js +19 -6
  27. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +20 -19
  28. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +10 -1
  29. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +1 -1
  30. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +2 -3
  31. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +0 -14
  32. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/OdataRequest.js +1 -0
  33. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/BatchRequestListBuilder.js +5 -2
  34. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/handler/MetadataHandler.js +1 -1
  35. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/handler/ServiceHandler.js +1 -1
  36. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DispatcherCommand.js +2 -2
  37. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/BufferedWriter.js +1 -3
  38. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +1 -1
  39. package/libx/_runtime/common/composition/update.js +18 -2
  40. package/libx/_runtime/common/error/frontend.js +46 -34
  41. package/libx/_runtime/common/generic/auth/capabilities.js +33 -14
  42. package/libx/_runtime/common/generic/input.js +1 -1
  43. package/libx/_runtime/common/utils/cqn2cqn4sql.js +3 -3
  44. package/libx/_runtime/db/query/update.js +48 -30
  45. package/libx/_runtime/fiori/lean-draft.js +2 -3
  46. package/libx/_runtime/hana/conversion.js +3 -2
  47. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +1 -1
  48. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  49. package/libx/_runtime/remote/Service.js +1 -17
  50. package/libx/_runtime/remote/utils/client.js +3 -3
  51. package/libx/_runtime/remote/utils/data.js +5 -7
  52. package/libx/odata/{grammar.pegjs → grammar.peggy} +1 -1
  53. package/libx/odata/metadata.js +121 -0
  54. package/libx/odata/parser.js +1 -1
  55. package/libx/odata/service-document.js +61 -0
  56. package/libx/odata/utils.js +102 -48
  57. package/libx/rest/RestAdapter.js +2 -2
  58. package/libx/rest/middleware/error.js +1 -1
  59. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- const cds = require ('..')
1
+ const cds = require('..')
2
2
  const {existsSync, readdirSync} = require ('fs')
3
3
  const {join,dirname,resolve,parse,sep} = require ('path')
4
4
 
@@ -6,68 +6,75 @@ const DEBUG = cds.debug('i18n')
6
6
  const _node_modules = cds.env.cdsc.moduleLookupDirectories.map(d => sep+d.slice(0, -1))
7
7
 
8
8
  module.exports = Object.assign (localize, {
9
- bundles4, folders4, folder4, bundle4
9
+ localize, lookup, bundles4, folders4, folder4, bundle4
10
10
  })
11
11
 
12
+ /**
13
+ * Can be used like that:
14
+ * @example cds.i18n.lookup('CreatedAt','de')
15
+ */
16
+ function lookup (key, locale, model = cds.context?.model || cds.model) {
17
+ let bundle = bundle4 (model, locale)
18
+ return bundle?.[key]
19
+ }
12
20
 
13
- function localize (model, /*with:*/ locale, aString, extBundle) {
14
- const _localize = bundle => localizeString (aString, bundle, extBundle)
21
+ /**
22
+ * Can be used like that:
23
+ * @example cds.localize(edmx,'de')
24
+ */
25
+ function localize (aString, locale, model = cds.context?.model || cds.model, ext={}) {
15
26
 
16
- const bundle = bundles4 (model, locale)
17
- if (Array.isArray(locale)) { // array of multiple locales
18
- return (function*(){
19
- let any;
20
- if(bundle && bundle[Symbol.iterator]) { // try iteration only if bundle is set
21
- for (let [lang,each] of bundle) yield any = [ _localize(each), {lang} ]
22
- }
23
- if (!any) yield [ _localize(), {lang:''} ]
24
- })()
25
- } else { // a single locale string
26
- return _localize(bundle)
27
+ // support for legacy signature
28
+ if (typeof aString === 'object') [ aString, model ] = [ model, aString ]
29
+
30
+ // in case of multiple locales, return a generator
31
+ if (Array.isArray(locale)) return (function*(){
32
+ let localized, bundles = bundles4 (model, locale)
33
+ if (bundles?.[Symbol.iterator]) for (let [lang,each] of bundles) {
34
+ localized = _localize_with (each)
35
+ yield [ localized, {lang} ]
36
+ }
37
+ if (!localized) yield [ aString, {lang:''} ]
38
+ })()
39
+
40
+ // otherwise return a single localized string
41
+ let bundle = bundle4 (model, locale)
42
+ return _localize_with (bundle)
43
+
44
+ function _localize_with (bundle) {
45
+ if (!bundle || !aString) return aString
46
+ if (typeof aString === 'object') aString = JSON.stringify(aString)
47
+ const escape = aString.startsWith('<?xml') ? escapeXmlAttr : /^[{[]/.test(aString) ? escapeJson : v=>v
48
+ return aString.replace (/{i18n>([^}]+)}/g, (_, key) => {
49
+ const val = ext[key] || bundle[key]
50
+ return !val ? key : escape(val)
51
+ })
27
52
  }
28
53
  }
29
54
 
30
- const TEXT_KEY_MARKER = 'i18n>'
31
- const TEXT_KEYS = /{b?i18n>([^"}]+)}/g
32
- function localizeString (aString, bundle, extBundle) {
33
- if (!bundle || !aString) return aString
34
- if (typeof aString === 'object') aString = JSON.stringify(aString, null, 2)
35
- // quick check for presence of any text key, to avoid expensive operation below
36
- if (!aString.includes(TEXT_KEY_MARKER)) return aString
37
- const escape = aString.startsWith('<?xml') ? escapeXmlAttr : /^[{[]/.test(aString) ? escapeJson : v=>v
38
- return aString.replace (TEXT_KEYS, (_, key) => {
39
- const val = (extBundle && extBundle[key]) || bundle[key]
40
- return val ? escape(val) : key
41
- })
42
- }
43
55
 
44
56
 
45
57
  /**
46
58
  * Returns all property bundles, i.e. one for each available translation language,
47
59
  * for the given model.
48
60
  */
49
- function bundles4 (model, locales) { // NOSONAR
50
-
51
- const folders = folders4 (model)
52
- if (folders.length === 0) return //> no folders, hence no bundles found at all
53
- if (typeof locales === 'string') return bundle4 (model, locales) // single locale string --> single bundle
54
- if (!locales) locales = cds.env.i18n.languages // default
55
- if (locales.split) locales = locales.split(',')
56
- // if no languages are specified, use all available
57
- if (locales.length === 1 && (locales[0] === '*' || locales[0] === 'all')) {
58
- locales = allLocales4 (folders)
59
- if (!locales) return {}
61
+ function bundles4 (model, locales = cds.env.i18n.languages) {
62
+
63
+ const folders = folders4 (model); if (folders.length === 0) return
64
+
65
+ if (locales.split) locales = locales.split(',')
66
+ if (locales[0] === '*' || locales[0] === 'all') {
67
+ locales = allLocales4 (folders); if (!locales) return {}
60
68
  if (!locales.includes(cds.env.i18n.fallback_bundle)) locales.push (cds.env.i18n.fallback_bundle)
61
69
  }
62
- DEBUG && DEBUG ('Languages:', locales)
70
+
71
+ DEBUG?.('Languages:', locales)
63
72
 
64
73
  return (function*(){
65
74
  for (let each of locales) {
66
- let bundle = bundle4 (model, each)
67
- if (bundle) {
68
- DEBUG && DEBUG (bundle)
69
- yield [ each, bundle ]
70
- }
75
+ let bundle = bundle4 (model, each); if(!bundle) continue
76
+ DEBUG?.(bundle)
77
+ yield [ each, bundle ]
71
78
  }
72
79
  })()
73
80
  }
@@ -79,13 +86,13 @@ function bundles4 (model, locales) { // NOSONAR
79
86
  */
80
87
  function allLocales4 (folders) {
81
88
  // find all languages in all folders
82
- const files = folders
83
- .map (folder => readdirSync(folder)
84
- .filter (e => e.startsWith(cds.env.i18n.file))
85
- .map(i18nFile => join (folder, i18nFile))
86
- ).reduce ((files, file) => files.concat(file)) // flatten
89
+ const files = folders.map (folder => readdirSync(folder)
90
+ .filter (e => e.startsWith(cds.env.i18n.file))
91
+ .map(i18nFile => join (folder, i18nFile))
92
+ ).reduce ((files, file) => files.concat(file)) // flatten
93
+
87
94
  if (files.length === 0) {
88
- DEBUG && DEBUG ('No languages for folders:', folders)
95
+ DEBUG?.('No languages for folders:', folders)
89
96
  return null
90
97
  }
91
98
 
@@ -117,17 +124,26 @@ function allLocales4 (folders) {
117
124
  */
118
125
  function bundle4 (model, locale) {
119
126
 
120
- const folders = folders4 (model); if (!folders.length) return //> no folders, hence no bundles found at all
127
+ if (typeof model === 'string') [ model, locale ] = [ cds.context?.model || cds.model, model ]
128
+
129
+ const bundles = model.texts || Object.defineProperty (model,'texts',{value:{}}).texts
130
+ if (locale in bundles) return bundles[locale]
131
+
121
132
  const bundle = {}
133
+ const folders = folders4(model)
134
+ try {
135
+ if (!folders.length) return bundle
136
+
137
+ add (cds.env.i18n.fallback_bundle) // e.g. i18n.properties
138
+ if (locale === cds.env.i18n.fallback_bundle) return bundle
122
139
 
123
- add (cds.env.i18n.fallback_bundle) // e.g. i18n.properties
124
- if (locale === cds.env.i18n.fallback_bundle) return bundle
140
+ add (cds.env.i18n.default_language) // e.g. i18n_en.properties
141
+ if (locale === cds.env.i18n.default_language) return bundle
125
142
 
126
- add (cds.env.i18n.default_language) // e.g. i18n_en.properties
127
- if (locale === cds.env.i18n.default_language) return bundle
143
+ add (locale) // e.g. i18n_de.properties
144
+ return bundle
128
145
 
129
- add (locale) // e.g. i18n_de.properties
130
- return bundle
146
+ } finally { bundles[locale] = bundle }
131
147
 
132
148
  function add (lang) {
133
149
  for (let each of folders) {
@@ -154,18 +170,16 @@ function folders4 (model) {
154
170
  // foo/bar.cds
155
171
  // foo/node_modules/reuse-level-1/model.cds
156
172
  // foo/node_modules/reuse-level-2/model.cds
157
- if (!model.$sources) return []
158
- const srcFolders = new Set (model.$sources.map (dirname))
159
- const folders = []
173
+ const folders = [] // using an array here to not screw up the folder order
174
+ const srcFolders = new Set ((model.$sources||[]).map(dirname))
160
175
  srcFolders.forEach(src => {
161
- let folder = folder4 (src)
176
+ const folder = folder4 (src)
162
177
  if (folder && !folders.includes(folder)) {
163
- folders.push(folder) // use an array here to not screw up the folder order
178
+ folders.push(folder)
164
179
  }
165
180
  })
166
-
167
- Object.defineProperty (model, '_i18nfolders', {value:folders})
168
- return folders.reverse()
181
+ Object.defineProperty (model, '_i18nfolders', {value:folders.reverse()})
182
+ return folders
169
183
  }
170
184
 
171
185
  /**
@@ -202,7 +216,7 @@ function loadFromJSON (res, lang=cds.env.i18n.default_language) {
202
216
  const bundles = require (resolve (cds.root,res+'.json'))
203
217
  return bundles[lang] || bundles [(lang.match(/\w+/)||[])[0]]
204
218
  } catch(e) {
205
- if (e.code !== 'MODULE_NOT_FOUND') throw e
219
+ if (e.code !== 'MODULE_NOT_FOUND') throw e
206
220
  }
207
221
  }
208
222
 
@@ -231,17 +245,9 @@ function escapeXmlAttr (str) {
231
245
  .replace(/</g, '&lt;')
232
246
  .replace(/"/g, '&quot;')
233
247
  .replace(/\r\n|\n/g, '&#xa;');
234
- if (!result.startsWith('{i18n>') && !result.startsWith('{bi18n'))
235
- result = result.replace(/>/g, '&gt;')
248
+ if (!result.startsWith('{i18n>')) result = result.replace(/>/g, '&gt;')
236
249
  }
237
250
  return result;
238
251
  }
239
252
 
240
- function escapeJson (str) { return str
241
- .replace(/"/g, '\\"')
242
- .replace(/\\t/g, '\\t')
243
- .replace(/\\n/g, '\\n')
244
- }
245
-
246
-
247
- /* eslint no-console:off */
253
+ const escapeJson = str => str.replace(/"/g, '\\"')
package/lib/index.js CHANGED
@@ -7,9 +7,10 @@ const cds = module.exports = new class cds extends EventEmitter {
7
7
 
8
8
  // Configuration & Information
9
9
  get requires() { return super.requires = this.env.requires._resolved() }
10
- get plugins() { return super.plugins = require('./plugins') }
10
+ get plugins() { return super.plugins = require('./plugins').activate() }
11
11
  get version() { return super.version = require('../package.json').version }
12
12
  get env() { return super.env = require('./env/cds-env').for('cds',this.root) }
13
+ get schema() { return super.schema = require('./env/schema') } // dynamic schema loading
13
14
  get home() { return super.home = __dirname.slice(0,-4) }
14
15
  cli = { command:'', options:{}, argv:[] }
15
16
  root = process.cwd()
@@ -25,7 +26,6 @@ const cds = module.exports = new class cds extends EventEmitter {
25
26
  get extend() { return super.extend = require('./compile/extend') }
26
27
  get deploy() { return super.deploy = require('./dbs/cds-deploy') }
27
28
  get localize() { return super.localize = require('./i18n/localize') }
28
- get build() { return () => { throw new Error('This application uses @sap/cds version >= 7, which is not compatible with the installed @sap/cds-dk version 6. Either update @sap/cds-dk to version 7 or downgrade @sap/cds to version 6 instead.') } }
29
29
  /** @type {{definitions:{},extensions:[]}} */ model = undefined
30
30
  /** @type Service */ db = undefined
31
31
 
@@ -116,6 +116,10 @@ const cds = module.exports = new class cds extends EventEmitter {
116
116
 
117
117
  // legacy and to be moved stuff -> hidden for tools in cds.__proto__
118
118
  /** @deprecated */ in (cwd) { return !cwd ? this : {__proto__:this, cwd, env: this.env.for('cds',cwd) } }
119
+ get build() { return () => cds.error('\
120
+ This application uses @sap/cds version >= 7, which is not compatible with the installed @sap/cds-dk version 6. \
121
+ Either update @sap/cds-dk to version 7 or downgrade @sap/cds to version 6 instead.\
122
+ ')}
119
123
  }
120
124
 
121
125
  // add global cds.ql commands
@@ -1,6 +1,3 @@
1
- const { serve_on_root } = global.cds?.env.features || {}
2
- const { middlewares } = global.cds?.env.requires || {}
3
- const { protocols: envProtocols } = global.cds?.env || {}
4
1
  const { extend } = require('../lazy')
5
2
 
6
3
  class any {
@@ -79,7 +76,7 @@ class service extends context {
79
76
 
80
77
  // Return a sluggified variant of the service's name
81
78
  const pathFromServiceName4 = (srv) => {
82
- return (
79
+ return (
83
80
  /[^.]+$/.exec(srv.name)[0] //> my.very.CatalogService --> CatalogService
84
81
  .replace(/Service$/,'') //> CatalogService --> Catalog
85
82
  .replace(/_/g,'-') //> foo_bar_baz --> foo-bar-baz
@@ -87,7 +84,7 @@ class service extends context {
87
84
  .toLowerCase() //> FOO --> foo
88
85
  )
89
86
  }
90
-
87
+
91
88
  // Return an array of service paths for a given service and protocol.
92
89
  // The results are not prefixed with the protocol's path.
93
90
  // Can return multiple results to support serving the same protocol on multiple paths:
@@ -108,10 +105,10 @@ class service extends context {
108
105
  else paths.push(def['@path'] || pathFromServiceName4(srv))
109
106
  }
110
107
  }
111
-
108
+
112
109
  // in case protocol is set via options.at but not contained in @protocol
113
110
  if (paths.length === 0) paths.push(def['@path'] || pathFromServiceName4(srv))
114
-
111
+
115
112
  return paths
116
113
  }
117
114
 
@@ -125,15 +122,18 @@ class service extends context {
125
122
  throw new Error(`Absolute @path (starting with '/') cannot be set for more than one protocol`)
126
123
  }
127
124
 
128
- const endpoints = []
129
- for (let pName of protocols) {
130
- let p = this._protocols[pName] || envProtocols[pName]
131
- if (!p) throw new Error(`Protocol "${pName}" is unknown`)
125
+ const endpoints = [], env_protocols = global.cds?.env.protocols
126
+ const serve_on_root = global.cds?.env.features.serve_on_root
127
+
128
+ for (let each of protocols) {
129
+ let p = this._protocols[each] || env_protocols[each]
130
+ if (!p) throw new Error(`Protocol "${each}" is unknown`)
132
131
 
133
- const kind = pName
132
+ const middlewares = global.cds?.requires.middlewares
133
+ const kind = each
134
134
  let prefix = middlewares ? p.path || '/' : '/' // > no middlewares, no prefix
135
135
  if (!prefix.endsWith('/')) prefix += '/'
136
- const unprefixedPaths = unprefixedPaths4(pName, srv, options)
136
+ const unprefixedPaths = unprefixedPaths4(each, srv, options)
137
137
  for (let path of unprefixedPaths) {
138
138
  if (path.startsWith('/')) endpoints.push({ kind, path})
139
139
  else {
package/lib/plugins.js CHANGED
@@ -1,49 +1,45 @@
1
- // IMPORTANT We must not use cds.debug/log/env here to allow plugins to change env.defaults
2
- const DEBUG = /\by|all|plugins\b/.test(process.env.DEBUG)
3
- const cds = require('.'), { local } = cds.utils
1
+ const cds = require('.')
4
2
 
5
- module.exports = (async function load_plugins (log = console.log) {
6
-
7
- if (DEBUG) console.time('[cds] - loaded plugins in')
3
+ /**
4
+ * Fetch cds-plugins from project's package dependencies.
5
+ * Used in and made available through cds.env.plugins.
6
+ */
7
+ exports.fetch = function (DEV = process.env.NODE_ENV !== 'production') {
8
8
  const plugins = {}
9
-
10
- load_from(cds.home) // load well-known plugins from our dependencies
11
- load_from(cds.root)
12
-
13
- global._plugins = Object.keys(plugins) // used in cds.env
14
- await Promise.all(Object.values(plugins).map(load => load()))
15
- if (DEBUG) console.timeEnd('[cds] - loaded plugins in')
16
-
9
+ fetch_plugins_in (cds.home, false)
10
+ fetch_plugins_in (cds.root, DEV)
11
+ function fetch_plugins_in (root, dev) {
12
+ let pkg; try { pkg = require(root + '/package.json') } catch { return }
13
+ let deps = { ...pkg.dependencies, ...dev && pkg.devDependencies }
14
+ for (let each in deps) try {
15
+ let impl = require.resolve(each + '/cds-plugin', { paths: [root] })
16
+ plugins[each] = { impl }
17
+ } catch { /* no cds-plugin.js */ }
18
+ }
17
19
  return plugins
18
-
19
- function load_from(pkg_path) {
20
- let pkg; try { pkg = require(pkg_path + '/package.json') } catch { return }
21
-
22
- if (pkg.cds?.plugins) {
23
- for (let each of pkg.cds.plugins) {
24
- let plugin = typeof each === 'string' ? each : each.impl
25
- if (plugin.startsWith('.'))
26
- plugin = require.resolve(pkg_path + '/' + plugin)
27
- _load_plugin(plugin, plugin, each)
28
- }
29
- } else {
30
- const deps = { ...pkg.dependencies, ...(process.env.NODE_ENV !== 'production' && pkg.devDependencies) }
31
- const plugins = []
32
- for (let each in deps) try {
33
- let plugin = require.resolve(each + '/cds-plugin', {paths:[pkg_path]})
34
- plugins.push (()=>_load_plugin(each, plugin))
35
- } catch { /* no plugin */ }
36
- for (let each of plugins) each()
37
- }
38
-
39
- function _load_plugin (name, impl, conf) {
40
- plugins[name] = async() => {
41
- // TODO support ESM plugins. But see cap/cds/pull/1838#issuecomment-1177200 !
42
- const plugin = plugins[name] = require(impl)
43
- if (DEBUG) log('[cds] - loaded plugin:', { impl: local(impl) })
44
- if (plugin.activate) await plugin.activate(conf)
45
- }
20
+ }
21
+
22
+ /**
23
+ * Load and activate cds-plugins from project's package dependencies.
24
+ * Used in and made available through cds.plugins.
25
+ */
26
+ exports.activate = async function () {
27
+ const DEBUG = cds.debug ('plugins', {label:'cds'})
28
+ DEBUG && console.time ('[cds] - loaded plugins in')
29
+ const { plugins } = cds.env, { local } = cds.utils
30
+ await Promise.all (Object.entries(plugins) .map (async ([ plugin, conf ]) => {
31
+ DEBUG?.(`loading plugin ${plugin}:`, { impl: local(conf.impl) })
32
+ // TODO: support ESM plugins. But see cap/cds/pull/1838#issuecomment-1177200 !
33
+ const p = require (conf.impl)
34
+ if(p.activate) {
35
+ cds.log('plugins').warn(`WARNING: \n
36
+ Returning an 'activate' function is deprecated and won't be
37
+ supported in future releases. Please return a Promise with 'module.exports' instead.
38
+ `)
39
+ await p.activate(conf)
46
40
  }
47
- }
48
-
49
- })()
41
+ return p
42
+ }))
43
+ DEBUG && console.timeEnd ('[cds] - loaded plugins in')
44
+ return plugins
45
+ }
package/lib/req/user.js CHANGED
@@ -13,9 +13,9 @@ class User {
13
13
  get attr() { return super.attr = {} }
14
14
  set attr(a) { super.attr = a }
15
15
 
16
- get roles(){ return super.roles = {} }
16
+ get roles() { return super.roles = {} }
17
17
  set roles(r) {
18
- super.roles = !Array.isArray(r) ? r : r.reduce((p,n)=>{ p[n]=1; return p },{})
18
+ super.roles = Array.isArray(r) ? r.reduce((p, n) => { p[n]=1; return p }, {}) : r
19
19
  }
20
20
 
21
21
  is (role) {
@@ -17,7 +17,6 @@ class LegacyProtocolAdapter extends ProtocolAdapter {
17
17
 
18
18
  static serve (srv, /* in: */ app) {
19
19
  return super.serve (srv, app, { before: [
20
- // async (req, res, next) => { await 1; next() }, // REVISIT: AsyncResource.bind() -> enable to break cds/tests/_runtime/odata/__tests__/integration/crud-with-mtx.test.js with existing, non-middleware mode, *w/o* fix to BufferedWriter
21
20
  cds_context,
22
21
  libx.perf,
23
22
  libx.auth(srv),
@@ -17,5 +17,9 @@ module.exports = function ODataAdapter (srv) { return [
17
17
 
18
18
  next()
19
19
  },
20
+ ...cds.env.features.odata_new_adapter ? [
21
+ require('../../../libx/odata/service-document')(srv),
22
+ require('../../../libx/odata/metadata')(srv),
23
+ ] : [],
20
24
  libx.to.odata_v4 (srv)
21
25
  ]}
@@ -2,10 +2,16 @@ class Axios {
2
2
 
3
3
  get axios() {
4
4
  // eslint-disable-next-line cds/no-missing-dependencies
5
- return super.axios = require('axios').create ({
5
+ const axios = require('axios').create ({
6
6
  headers: { 'Content-Type': 'application/json' },
7
7
  baseURL: this.url,
8
8
  })
9
+ // fill in baseURL on subsequent this.url = url, after server has started
10
+ Reflect.defineProperty (this, 'url', { configurable: true, set: url => {
11
+ Reflect.defineProperty (this, 'url', { value: url })
12
+ axios.defaults.baseURL = url
13
+ }})
14
+ return super.axios = axios
9
15
  }
10
16
  get (..._) { return this.axios.get (..._args(_)) .catch(_error) }
11
17
  put (..._) { return this.axios.put (..._args(_)) .catch(_error) }