@sap/cds 6.1.3 → 6.2.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.
- package/CHANGELOG.md +77 -8
- package/apis/cds.d.ts +18 -6
- package/apis/connect.d.ts +1 -1
- package/apis/cqn.d.ts +1 -1
- package/apis/log.d.ts +23 -5
- package/apis/ql.d.ts +128 -61
- package/apis/services.d.ts +11 -0
- package/apis/test.d.ts +61 -0
- package/apis/utils.d.ts +15 -0
- package/app/fiori/preview.js +1 -0
- package/bin/build/buildTaskEngine.js +70 -22
- package/bin/build/buildTaskFactory.js +18 -11
- package/bin/build/buildTaskHandler.js +1 -1
- package/bin/build/buildTaskProviderFactory.js +3 -13
- package/bin/build/constants.js +0 -1
- package/bin/build/index.js +14 -6
- package/bin/build/provider/buildTaskHandlerEdmx.js +2 -3
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +2 -2
- package/bin/build/provider/buildTaskHandlerInternal.js +3 -6
- package/bin/build/provider/buildTaskProviderInternal.js +51 -39
- package/bin/build/provider/fiori/index.js +3 -3
- package/bin/build/provider/hana/2migration.js +1 -1
- package/bin/build/provider/hana/index.js +34 -27
- package/bin/build/provider/java/index.js +6 -7
- package/bin/build/provider/mtx/index.js +20 -18
- package/bin/build/provider/mtx/resourcesTarBuilder.js +8 -11
- package/bin/build/provider/mtx-sidecar/index.js +13 -17
- package/bin/build/provider/nodejs/index.js +8 -7
- package/bin/build/util.js +22 -4
- package/bin/cds.js +8 -4
- package/bin/deploy/to-hana/cfUtil.js +53 -18
- package/bin/mtx/in-cds.js +1 -0
- package/bin/serve.js +37 -30
- package/lib/auth/basic-auth.js +33 -0
- package/lib/auth/dummy-auth.js +7 -0
- package/lib/auth/ias-auth.js +2 -0
- package/lib/auth/index.js +31 -0
- package/lib/auth/jwt-auth.js +3 -0
- package/lib/auth/mocked-users.js +72 -0
- package/lib/auth/passport-basic.js +12 -0
- package/lib/auth/passport-digest.js +14 -0
- package/lib/auth/xsuaa-auth.js +3 -0
- package/lib/compile/cds-compile.js +3 -3
- package/lib/compile/to/cdl.js +5 -1
- package/lib/compile/to/edm.js +8 -0
- package/lib/compile/to/gql.js +1 -0
- package/lib/compile/to/json.js +30 -5
- package/lib/compile/to/sql.js +3 -1
- package/lib/core/index.js +5 -1
- package/lib/dbs/cds-deploy.js +36 -6
- package/lib/env/cds-env.js +15 -5
- package/lib/env/cds-requires.js +51 -58
- package/lib/env/defaults.js +1 -0
- package/lib/env/schemas/cds-package.json +4 -0
- package/lib/env/schemas/cds-rc.json +63 -77
- package/lib/i18n/localize.js +16 -5
- package/lib/index.js +9 -4
- package/lib/log/cds-error.js +4 -6
- package/lib/log/cds-log.js +89 -53
- package/lib/log/service/index.js +1 -0
- package/lib/ql/CREATE.js +2 -5
- package/lib/ql/DELETE.js +1 -1
- package/lib/ql/DROP.js +1 -3
- package/lib/ql/INSERT.js +3 -3
- package/lib/ql/Query.js +10 -23
- package/lib/ql/SELECT.js +1 -2
- package/lib/ql/UPDATE.js +2 -2
- package/lib/ql/Whereable.js +7 -15
- package/lib/ql/cds-ql.js +9 -3
- package/lib/req/cds-context.js +11 -3
- package/lib/req/context.js +29 -23
- package/lib/req/locale.js +9 -5
- package/lib/req/request.js +1 -0
- package/lib/req/user.js +2 -1
- package/lib/srv/cds-connect.js +1 -1
- package/lib/srv/cds-serve.js +21 -14
- package/lib/srv/middlewares/cds-context.js +29 -0
- package/lib/srv/middlewares/ctx-model.js +24 -0
- package/lib/srv/middlewares/errors.js +9 -0
- package/lib/srv/middlewares/index.js +22 -0
- package/lib/srv/middlewares/sap-statistics.js +13 -0
- package/lib/srv/middlewares/trace.js +102 -0
- package/lib/srv/protocols/_legacy.js +42 -0
- package/lib/srv/protocols/graphql.js +39 -0
- package/lib/srv/protocols/hcql.js +37 -0
- package/lib/srv/protocols/index.js +86 -0
- package/lib/srv/protocols/odata-v2-proxy.js +3767 -0
- package/lib/srv/protocols/odata-v2.js +26 -0
- package/lib/srv/protocols/odata-v4.js +16 -0
- package/lib/srv/protocols/rest.js +13 -0
- package/lib/srv/srv-api.js +5 -0
- package/lib/srv/srv-models.js +4 -6
- package/lib/utils/axios.js +3 -2
- package/lib/utils/cds-test.js +27 -21
- package/lib/utils/cds-utils.js +19 -20
- package/lib/utils/tar.js +175 -0
- package/libx/_runtime/audit/generic/personal/utils.js +18 -7
- package/libx/_runtime/audit/utils/v2.js +1 -0
- package/libx/_runtime/auth/index.js +4 -0
- package/libx/_runtime/auth/strategies/ias-auth.js +76 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +8 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +15 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/orderByToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ResourcePathParser.js +9 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriInfo.js +5 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +12 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/BufferedWriter.js +6 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/RequestValidator.js +47 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/util/assert.js +4 -0
- package/libx/_runtime/common/aspects/relation.js +1 -1
- package/libx/_runtime/common/composition/data.js +61 -15
- package/libx/_runtime/common/composition/delete.js +0 -1
- package/libx/_runtime/common/composition/insert.js +0 -1
- package/libx/_runtime/common/composition/tree.js +4 -10
- package/libx/_runtime/common/composition/update.js +44 -21
- package/libx/_runtime/common/generic/auth/capabilities.js +8 -10
- package/libx/_runtime/common/generic/crud.js +1 -2
- package/libx/_runtime/common/generic/etag.js +4 -4
- package/libx/_runtime/common/generic/input.js +4 -4
- package/libx/_runtime/common/generic/paging.js +3 -3
- package/libx/_runtime/common/generic/put.js +3 -3
- package/libx/_runtime/common/generic/sorting.js +4 -4
- package/libx/_runtime/common/generic/temporal.js +3 -3
- package/libx/_runtime/common/i18n/messages.properties +0 -7
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +11 -6
- package/libx/_runtime/common/utils/csn.js +0 -28
- package/libx/_runtime/common/utils/draft.js +8 -1
- package/libx/_runtime/common/utils/path.js +7 -1
- package/libx/_runtime/common/utils/resolveView.js +2 -3
- package/libx/_runtime/db/data-conversion/post-processing.js +3 -44
- package/libx/_runtime/db/generic/input.js +3 -3
- package/libx/_runtime/db/sql-builder/dataTypes.js +4 -0
- package/libx/_runtime/fiori/generic/activate.js +2 -2
- package/libx/_runtime/fiori/generic/before.js +40 -72
- package/libx/_runtime/fiori/generic/cancel.js +2 -2
- package/libx/_runtime/fiori/generic/delete.js +2 -2
- package/libx/_runtime/fiori/generic/edit.js +2 -2
- package/libx/_runtime/fiori/generic/new.js +2 -2
- package/libx/_runtime/fiori/generic/patch.js +49 -37
- package/libx/_runtime/fiori/generic/prepare.js +2 -2
- package/libx/_runtime/fiori/generic/read.js +27 -37
- package/libx/_runtime/fiori/utils/where.js +4 -2
- package/libx/_runtime/hana/Service.js +1 -3
- package/libx/_runtime/hana/conversion.js +3 -0
- package/libx/_runtime/hana/driver.js +33 -3
- package/libx/_runtime/hana/dynatrace.js +1 -0
- package/libx/_runtime/hana/search2Contains.js +12 -1
- package/libx/_runtime/hana/search2cqn4sql.js +10 -27
- package/libx/_runtime/hana/streaming.js +1 -0
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +4 -2
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +1 -0
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +5 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -0
- package/libx/_runtime/messaging/enterprise-messaging.js +62 -3
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/messaging/redis-messaging.js +1 -0
- package/libx/_runtime/remote/Service.js +2 -2
- package/libx/_runtime/remote/utils/client.js +8 -3
- package/libx/_runtime/remote/utils/data.js +7 -2
- package/libx/_runtime/sqlite/Service.js +18 -7
- package/libx/_runtime/sqlite/conversion.js +3 -0
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +3 -3
- package/libx/_runtime/sqlite/localized.js +8 -8
- package/libx/odata/afterburner.js +39 -7
- package/libx/odata/cqn2odata.js +6 -3
- package/libx/odata/grammar.pegjs +66 -18
- package/libx/odata/index.js +3 -2
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +2 -0
- package/libx/rest/RestAdapter.js +62 -43
- package/libx/rest/middleware/parse.js +2 -1
- package/libx/rest/middleware/update.js +1 -1
- package/package.json +2 -2
- package/server.js +5 -4
- package/srv/mtx.cds +1 -1
- package/srv/mtx.js +4 -33
- package/lib/srv/adapters.js +0 -85
- package/lib/utils/resources/index.js +0 -48
- package/lib/utils/resources/tar.js +0 -49
- package/lib/utils/resources/utils.js +0 -11
- package/libx/_runtime/extensibility/activate.js +0 -69
- package/libx/_runtime/extensibility/add.js +0 -50
- package/libx/_runtime/extensibility/addExtension.js +0 -72
- package/libx/_runtime/extensibility/defaults.js +0 -34
- package/libx/_runtime/extensibility/handler/transformREAD.js +0 -121
- package/libx/_runtime/extensibility/handler/transformRESULT.js +0 -51
- package/libx/_runtime/extensibility/handler/transformWRITE.js +0 -64
- package/libx/_runtime/extensibility/linter/allowlist_checker.js +0 -373
- package/libx/_runtime/extensibility/linter/annotations_checker.js +0 -113
- package/libx/_runtime/extensibility/linter/checker_base.js +0 -20
- package/libx/_runtime/extensibility/linter/namespace_checker.js +0 -180
- package/libx/_runtime/extensibility/linter.js +0 -32
- package/libx/_runtime/extensibility/push.js +0 -118
- package/libx/_runtime/extensibility/service.js +0 -38
- package/libx/_runtime/extensibility/token.js +0 -57
- package/libx/_runtime/extensibility/utils.js +0 -131
- package/libx/_runtime/extensibility/validation.js +0 -50
- package/libx/_runtime/extensibility/views.js +0 -12
- package/srv/extensibility-service.cds +0 -60
- package/srv/extensibility-service.js +0 -1
- package/srv/extensions.cds +0 -8
- package/srv/model-provider.cds +0 -61
- package/srv/model-provider.js +0 -143
package/lib/index.js
CHANGED
|
@@ -23,10 +23,9 @@ const _class = lazy => cds.builtin.classes [lazy]
|
|
|
23
23
|
const _require = require; require = lazified (module) // eslint-disable-line
|
|
24
24
|
const _service = lazified ({ // nested facade for service-related modules
|
|
25
25
|
/** @param x {(this:Service, srv:Service, ...etc) => any} */ impl: x=>x,
|
|
26
|
-
/** @type {{ [path:string] : Service }} */ paths: {},
|
|
27
26
|
/** @type Service[] */ providers: [],
|
|
28
27
|
factory: require ('./srv/factory'),
|
|
29
|
-
|
|
28
|
+
protocols: require ('./srv/protocols'),
|
|
30
29
|
bindings: require ('./srv/bindings'),
|
|
31
30
|
})
|
|
32
31
|
|
|
@@ -66,6 +65,8 @@ const cds = module.exports = extend (new facade) .with ({
|
|
|
66
65
|
*[Symbol.iterator]() {for (let e in this) yield this[e]}
|
|
67
66
|
get _pending(){ let p={}; Object.defineProperty(this,'_pending',{value:p}); return p }
|
|
68
67
|
},
|
|
68
|
+
middlewares: require('./srv/middlewares'),
|
|
69
|
+
auth: require ('./auth'),
|
|
69
70
|
|
|
70
71
|
// Core Services API
|
|
71
72
|
Service: require ('./srv/srv-api'),
|
|
@@ -73,7 +74,7 @@ const cds = module.exports = extend (new facade) .with ({
|
|
|
73
74
|
Request: require ('./req/request'),
|
|
74
75
|
Event: require ('./req/event'),
|
|
75
76
|
User: require ('./req/user'),
|
|
76
|
-
ql: require ('./ql/cds-ql'),
|
|
77
|
+
ql: lazy => require ('./ql/cds-ql'),
|
|
77
78
|
tx: (..._) => (cds.db || cds.Service.prototype) .tx (..._),
|
|
78
79
|
/** @type Service */ db: undefined,
|
|
79
80
|
|
|
@@ -124,7 +125,7 @@ extend (cds.__proto__) .with ({
|
|
|
124
125
|
extend (cds.__proto__) .with (lazified ({
|
|
125
126
|
/** @deprecated */ in: (cwd) => !cwd ? cds : {__proto__:cds, cwd, env: cds.env.for('cds',cwd) },
|
|
126
127
|
mtx: lazy => require('../bin/mtx/in-cds'),
|
|
127
|
-
build: lazy => require('../bin/build')
|
|
128
|
+
build: lazy => require('../bin/build')
|
|
128
129
|
}))
|
|
129
130
|
|
|
130
131
|
// Add global forwards to cds.ql and cds.parse
|
|
@@ -147,6 +148,10 @@ if (process.env.CDS_STRICT_NODE_VERSION !== 'false') {
|
|
|
147
148
|
// restore require for subsequent uses in lazy getters
|
|
148
149
|
require = _require // eslint-disable-line
|
|
149
150
|
|
|
151
|
+
// can be used to later check that one has only one cds object
|
|
152
|
+
if (!global.__cds_loaded_from) global.__cds_loaded_from = new Set
|
|
153
|
+
global.__cds_loaded_from.add(__filename)
|
|
154
|
+
|
|
150
155
|
if (process.env.CDS_GLOBAL) // TODO for stakeholder-tests only. Remove after cds 6.
|
|
151
156
|
Object.assign(module,{ exports: global.cds || (global.cds = cds)})
|
|
152
157
|
else
|
package/lib/log/cds-error.js
CHANGED
|
@@ -17,12 +17,10 @@ const { format } = require('util'), _formatted = v => format(v)
|
|
|
17
17
|
* let x = y || cds.error `Argument 'y' must not be null`
|
|
18
18
|
*/
|
|
19
19
|
const error = exports = module.exports = function cds_error (msg, _details, _base) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (_details) Object.assign (e,_details)
|
|
25
|
-
}
|
|
20
|
+
if (msg.raw) [ msg, _details, _base ] = [ error.message(...arguments) ]
|
|
21
|
+
const e = msg.stack ? msg : typeof msg === 'string' ? new Error(msg) : Object.assign(new Error,msg)
|
|
22
|
+
Error.captureStackTrace (e,_base||error)
|
|
23
|
+
if (_details) Object.assign (e,_details)
|
|
26
24
|
if (new.target) return e; else throw e
|
|
27
25
|
}
|
|
28
26
|
|
package/lib/log/cds-log.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
const cds = require ('../index'),
|
|
2
|
-
|
|
3
|
-
// Use configured logger in case of cds serve
|
|
4
|
-
if (log.Logger || log.service) {
|
|
5
|
-
if (log.Logger) exports.Logger = require (log.Logger)
|
|
6
|
-
if (log.service) {
|
|
7
|
-
const {app} = cds, serveIn = app => require('./service').serveIn(app)
|
|
8
|
-
app ? setImmediate(() => serveIn(app)) : cds.on('bootstrap', app => serveIn(app))
|
|
9
|
-
}
|
|
10
|
-
}
|
|
1
|
+
const cds = require ('../index'), conf = cds.env.log
|
|
2
|
+
const log = module.exports = exports = cds_log
|
|
11
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Cache used for all constructed loggers.
|
|
6
|
+
*/
|
|
7
|
+
exports.loggers = {}
|
|
12
8
|
|
|
13
9
|
/**
|
|
14
10
|
* Returns a trace logger for the given module if trace is switched on for it,
|
|
@@ -42,27 +38,26 @@ if (log.Logger || log.service) {
|
|
|
42
38
|
* @param {string} [module] the module for which a logger is requested
|
|
43
39
|
* @param {string|number|{ level, prefix }} [options] the log level to enable -> 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace
|
|
44
40
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
function cds_log (module, options) { // NOSONAR
|
|
42
|
+
const id = module?.match(/^[^|]+/)[0] || 'cds', cache = log.loggers
|
|
43
|
+
const cached = cache[id]
|
|
44
|
+
if (cached && !options) return cached
|
|
48
45
|
|
|
49
|
-
let
|
|
50
|
-
|
|
51
|
-
if (!level) level = (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
if (typeof level === 'string') {
|
|
56
|
-
level = exports.levels [level.toUpperCase()]
|
|
57
|
-
}
|
|
46
|
+
let label = options?.label || options?.prefix || cached?.label || id
|
|
47
|
+
let level = typeof options === 'object' ? options.level : options
|
|
48
|
+
if (!level) level = DEBUG_matches(module) ? DEBUG : conf.levels[id] || INFO
|
|
49
|
+
if (typeof level === 'string') level = log.levels [level.toUpperCase()]
|
|
50
|
+
if (cached && cached.level === level) return cached
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
const logger = new Logger (label, level)
|
|
53
|
+
return cache[id] = Object.assign (cached || logger.log, {
|
|
54
|
+
id, label, level, setFormat(fn){ logger.format = fn; return this },
|
|
55
|
+
_trace: level >= TRACE,
|
|
56
|
+
_debug: level >= DEBUG,
|
|
57
|
+
_info: level >= INFO,
|
|
58
|
+
_warn: level >= WARN,
|
|
59
|
+
_error: level >= ERROR,
|
|
60
|
+
}, logger)
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
|
|
@@ -72,7 +67,7 @@ module.exports = exports = function cds_log (module, options) { // NOSONAR
|
|
|
72
67
|
*/
|
|
73
68
|
exports.debug = function cds_debug (module) {
|
|
74
69
|
const L = this.log (module)
|
|
75
|
-
|
|
70
|
+
if (L._debug) return L.debug
|
|
76
71
|
}
|
|
77
72
|
|
|
78
73
|
|
|
@@ -84,53 +79,94 @@ exports.debug = function cds_debug (module) {
|
|
|
84
79
|
*
|
|
85
80
|
* cds.log.Logger = () => winston.createLogger (...)
|
|
86
81
|
*
|
|
87
|
-
* @param {string} [
|
|
82
|
+
* @param {string} [label] the module for which a logger is requested
|
|
88
83
|
* @param {number} [level] the log level to enable -> 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace
|
|
89
84
|
*/
|
|
90
85
|
/* eslint-disable no-console */
|
|
91
|
-
exports.Logger = (
|
|
92
|
-
const fmt = (level,args) => logger.format (
|
|
93
|
-
const logger =
|
|
94
|
-
format: exports.format,
|
|
86
|
+
exports.Logger = (label, level) => {
|
|
87
|
+
const fmt = (level,args) => logger.format (label,level,...args)
|
|
88
|
+
const logger = {
|
|
89
|
+
format: exports.format, // use logger.format as this could be changed dynamically
|
|
95
90
|
trace: level < TRACE ? ()=>{} : (...args) => console.trace (...fmt(TRACE,args)),
|
|
96
91
|
debug: level < DEBUG ? ()=>{} : (...args) => console.debug (...fmt(DEBUG,args)),
|
|
97
92
|
log: level < INFO ? ()=>{} : (...args) => console.log (...fmt(INFO,args)),
|
|
98
93
|
info: level < INFO ? ()=>{} : (...args) => console.info (...fmt(INFO,args)),
|
|
99
94
|
warn: level < WARN ? ()=>{} : (...args) => console.warn (...fmt(WARN,args)),
|
|
100
95
|
error: level < ERROR ? ()=>{} : (...args) => console.error (...fmt(ERROR,args)),
|
|
101
|
-
|
|
102
|
-
_debug: level >= DEBUG,
|
|
103
|
-
_info: level >= INFO,
|
|
104
|
-
_warn: level >= WARN,
|
|
105
|
-
_error: level >= ERROR,
|
|
106
|
-
})
|
|
107
|
-
// deleted stdout -> stderr redirection for cds compile as bin/utils/log.js is used
|
|
96
|
+
}
|
|
108
97
|
return logger
|
|
109
98
|
}
|
|
99
|
+
function Logger (label, level) { return exports.Logger (label, level) }
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Convenience method to construct winston loggers, very similar to `winston.createLogger()`.
|
|
104
|
+
* @param {object} options - as in `winston.createLogger()`
|
|
105
|
+
* @returns The winston logger, decorated with the standard cds.log methods
|
|
106
|
+
* .debug(), .info(), .warn(), .error(), etc.
|
|
107
|
+
*/
|
|
108
|
+
exports.winstonLogger = (options) => (label, level) => {
|
|
109
|
+
const winston = require("winston") // eslint-disable-line cds/no-missing-dependencies
|
|
110
|
+
const logger = winston.createLogger({
|
|
111
|
+
levels: log.levels, level: Object.keys(log.levels)[level],
|
|
112
|
+
transports: [new winston.transports.Console()],
|
|
113
|
+
...options
|
|
114
|
+
})
|
|
115
|
+
const { formatWithOptions } = require('util')
|
|
116
|
+
const _fmt = ([...args]) => formatWithOptions(
|
|
117
|
+
{ colors: false }, `[${label}] -`, ...args
|
|
118
|
+
)
|
|
119
|
+
return Object.assign (logger, {
|
|
120
|
+
trace: (...args) => logger.TRACE (_fmt(args)),
|
|
121
|
+
debug: (...args) => logger.DEBUG (_fmt(args)),
|
|
122
|
+
log: (...args) => logger.INFO (_fmt(args)),
|
|
123
|
+
info: (...args) => logger.INFO (_fmt(args)),
|
|
124
|
+
warn: (...args) => logger.WARN (_fmt(args)),
|
|
125
|
+
error: (...args) => logger.ERROR (_fmt(args)),
|
|
126
|
+
})
|
|
127
|
+
}
|
|
110
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Built-in formatters
|
|
131
|
+
*/
|
|
132
|
+
const { simple } = exports.formatters = {
|
|
133
|
+
simple: (label, level, ...args) => [ `[${label}] -`, ...args ],
|
|
134
|
+
mt: (label, level, ...args) => {
|
|
135
|
+
const t = cds.context?.tenant; if (t) label += '|'+t
|
|
136
|
+
return simple (label, level, ...args)
|
|
137
|
+
},
|
|
138
|
+
get json() {
|
|
139
|
+
return this._json || (this._json = require('./format/kibana'))
|
|
140
|
+
}
|
|
141
|
+
}
|
|
111
142
|
|
|
112
143
|
/**
|
|
113
|
-
* Formats
|
|
144
|
+
* Formats log outputs by returning an array of arguments which are passed to
|
|
114
145
|
* console.log() et al.
|
|
115
146
|
* You can assign custom formatters like that:
|
|
116
147
|
*
|
|
117
|
-
* cds.log.format = (
|
|
148
|
+
* cds.log.format = (label, level, ...args) => [ '[', label, ']', ...args ]
|
|
118
149
|
*
|
|
119
|
-
* @param {string}
|
|
120
|
-
* @param {number} level
|
|
150
|
+
* @param {string} label the label to prefix to log output
|
|
151
|
+
* @param {number} level the log level to enable -> 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace
|
|
121
152
|
* @param {any[]} args the arguments passed to Logger.debug|log|info|wanr|error()
|
|
122
153
|
*/
|
|
123
154
|
exports.format = (
|
|
124
|
-
process.env.NODE_ENV === 'production' && cds.env.features.kibana_formatter ?
|
|
125
|
-
|
|
126
|
-
const t = cds.context?.tenant
|
|
127
|
-
return [ t ? `[${module}|${t}]` : `[${module}]`, '-', ...args ]
|
|
128
|
-
}
|
|
129
|
-
: (module, level, ...args) => [ `[${module}] -`, ...args ]
|
|
155
|
+
process.env.NODE_ENV === 'production' && cds.env.features.kibana_formatter ? log.formatters.json :
|
|
156
|
+
cds.requires.multitenancy ? log.formatters.mt : simple
|
|
130
157
|
)
|
|
131
158
|
|
|
132
159
|
|
|
160
|
+
const DEBUG_matches = (m) => process.env.DEBUG?.match(RegExp(`\\b(y|all|${m||'any'})\\b`))
|
|
133
161
|
const { ERROR, WARN, INFO, DEBUG, TRACE } = exports.levels = {
|
|
134
162
|
SILENT:0, ERROR:1, WARN:2, INFO:3, DEBUG:4, TRACE:5, SILLY:5, VERBOSE:5
|
|
135
163
|
}
|
|
136
|
-
|
|
164
|
+
|
|
165
|
+
;(function _init() {
|
|
166
|
+
const conf = cds.env.log
|
|
167
|
+
if (conf.Logger) exports.Logger = require (conf.Logger) // Use configured logger in case of cds serve
|
|
168
|
+
if (conf.service) {
|
|
169
|
+
const {app} = cds, serveIn = app => require('./service').serveIn(app)
|
|
170
|
+
app ? setImmediate(() => serveIn(app)) : cds.on('bootstrap', app => serveIn(app))
|
|
171
|
+
}
|
|
172
|
+
})()
|
package/lib/log/service/index.js
CHANGED
package/lib/ql/CREATE.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
const $ = Object.assign
|
|
3
|
-
|
|
4
|
-
module.exports = class CREATE extends Query {
|
|
1
|
+
module.exports = class Query extends require('./Query') {
|
|
5
2
|
|
|
6
3
|
static _api() {
|
|
7
|
-
return
|
|
4
|
+
return Object.assign((..._) => (new this).entity(..._), {
|
|
8
5
|
entity: (..._) => (new this).entity(..._),
|
|
9
6
|
})
|
|
10
7
|
}
|
package/lib/ql/DELETE.js
CHANGED
package/lib/ql/DROP.js
CHANGED
package/lib/ql/INSERT.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
const is_array = Array.isArray
|
|
1
|
+
module.exports = class Query extends require('./Query') {
|
|
3
2
|
|
|
4
|
-
module.exports = class INSERT extends Query {
|
|
5
3
|
static _api() {
|
|
6
4
|
return Object.assign ((..._) => (new this).entries(..._), {
|
|
7
5
|
into: (..._) => (new this).into(..._),
|
|
@@ -63,3 +61,5 @@ module.exports = class INSERT extends Query {
|
|
|
63
61
|
return super.valueOf('INSERT INTO')
|
|
64
62
|
}
|
|
65
63
|
}
|
|
64
|
+
|
|
65
|
+
const is_array = Array.isArray
|
package/lib/ql/Query.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { AsyncResource } = require('async_hooks')
|
|
2
|
-
const { inspect } = require('util')
|
|
3
2
|
const cds = require('../index')
|
|
4
3
|
|
|
5
4
|
class Query {
|
|
@@ -8,7 +7,14 @@ class Query {
|
|
|
8
7
|
|
|
9
8
|
/** Creates a derived instance that initially inherits all properties. */
|
|
10
9
|
clone(){
|
|
11
|
-
|
|
10
|
+
const inherited = Object.create (this[this.cmd])
|
|
11
|
+
return {__proto__:this, [this.cmd]: inherited }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
flat(){
|
|
15
|
+
const flat = this[this.cmd]
|
|
16
|
+
for (let x=flat; x.__proto__;) Object.assign(flat, x = x.__proto__)
|
|
17
|
+
return new this.constructor (flat)
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
/** Binds this query to be executed with the given service */
|
|
@@ -23,20 +29,6 @@ class Query {
|
|
|
23
29
|
return (r,e) => q.runInAsyncScope (srv.run, srv, this) .then (r,e)
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
/** Beautifies output in REPL */
|
|
27
|
-
[inspect.custom]() {
|
|
28
|
-
const {cmd} = this, colors = process.env.CDS_TERM_COLORS !== false
|
|
29
|
-
return `{ ${cmd}: `+ inspect(this[cmd], { colors, depth: 22 })
|
|
30
|
-
.replace(/^\w*\s/, '')
|
|
31
|
-
.replace(
|
|
32
|
-
/{ ref: \[([^\]]*)\] }/g,
|
|
33
|
-
(_,ref) => '{ref:[' + ref.slice(1, -1) + ']}'
|
|
34
|
-
)
|
|
35
|
-
.replace(/{ val: ([^ ]*) }/g, '{val:$1}')
|
|
36
|
-
.replace(/{ (xpr|ref|val): /g, '{$1:') +
|
|
37
|
-
'}'
|
|
38
|
-
}
|
|
39
|
-
|
|
40
32
|
_target_ref4 (target, arg2) {
|
|
41
33
|
|
|
42
34
|
// Resolving this._target --> REVISIT: this is not reliable !!!
|
|
@@ -55,19 +47,14 @@ class Query {
|
|
|
55
47
|
|
|
56
48
|
//> REVISIT: should we rather have consistent .from/.entity/.into in CQN?
|
|
57
49
|
_target_name4 (...args) {
|
|
58
|
-
const {ref} = this._target_ref4 (...args)
|
|
59
|
-
return ref.length === 1 && typeof ref[0] === 'string' ? ref[0] : {ref}
|
|
50
|
+
const {ref, as} = this._target_ref4 (...args)
|
|
51
|
+
return ref.length === 1 && typeof ref[0] === 'string' && !as ? ref[0] : as ? {ref, as} : {ref}
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
_expected (...args) {
|
|
63
55
|
return cds.error.expected (...args)
|
|
64
56
|
}
|
|
65
57
|
|
|
66
|
-
_own (property, _ = this[this.cmd]) {
|
|
67
|
-
const pd = Reflect.getOwnPropertyDescriptor (_, property)
|
|
68
|
-
return pd && pd.value
|
|
69
|
-
}
|
|
70
|
-
|
|
71
58
|
_add (property, values) {
|
|
72
59
|
const _ = this[this.cmd], pd = Reflect.getOwnPropertyDescriptor (_,property)
|
|
73
60
|
_[property] = !pd || !pd.value ? values : [ ...pd.value, ...values ]
|
package/lib/ql/SELECT.js
CHANGED
package/lib/ql/UPDATE.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const Whereable = require('./Whereable')
|
|
2
2
|
const { parse } = require('../index')
|
|
3
3
|
|
|
4
|
-
module.exports = class
|
|
4
|
+
module.exports = class Query extends Whereable {
|
|
5
5
|
|
|
6
6
|
static _api() {
|
|
7
7
|
return Object.assign ((..._) => (new this).entity(..._), {
|
|
@@ -94,4 +94,4 @@ const _comma_separated_exprs = (s) => {
|
|
|
94
94
|
return all
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
const operators = { '=':1, '-=':2, '+=':2, '*=':2, '/=':2, '%=':2 }
|
|
97
|
+
const operators = { '=':1, '-=':2, '+=':2, '*=':2, '/=':2, '%=':2 }
|
package/lib/ql/Whereable.js
CHANGED
|
@@ -2,12 +2,7 @@ const { error } = require ('../index')
|
|
|
2
2
|
const cds = require('../index')
|
|
3
3
|
const parse = require('./parse')
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
if (where.includes('or')) Object.defineProperty(where,'_includes_or__',{value:1})
|
|
7
|
-
else Object.defineProperty(where,'_includes_or__',{value:0})
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
class Whereable extends require('./Query') {
|
|
5
|
+
class Query extends require('./Query') {
|
|
11
6
|
|
|
12
7
|
where(...x) { return this._where (x,'and','where') }
|
|
13
8
|
and(...x) { return this._where (x,'and') }
|
|
@@ -19,20 +14,17 @@ class Whereable extends require('./Query') {
|
|
|
19
14
|
if (!_clause) _clause = (
|
|
20
15
|
_.having ? 'having' :
|
|
21
16
|
_.where ? 'where' :
|
|
22
|
-
_.from
|
|
17
|
+
_.from?.on ? 'on' :
|
|
23
18
|
error (`Invalid attempt to call '${this.cmd}.${and_or}()' before a prior call to '${this.cmd}.where()'`)
|
|
24
19
|
)
|
|
25
20
|
if (_clause === 'on') _ = _.from
|
|
26
|
-
let left =
|
|
21
|
+
let left = Reflect.getOwnPropertyDescriptor(_,_clause)?.value
|
|
27
22
|
if (!left) {
|
|
28
|
-
|
|
23
|
+
if (pred.includes('or')) this._left_has_or = true
|
|
29
24
|
_[_clause] = pred
|
|
30
25
|
} else {
|
|
31
|
-
if (and_or === 'and') {
|
|
32
|
-
|
|
33
|
-
if (left._includes_or__ === 1) left = [{xpr:left}]
|
|
34
|
-
if (pred.includes('or')) pred = [{xpr:pred}]
|
|
35
|
-
}
|
|
26
|
+
if (this._left_has_or && and_or === 'and') { left = [{xpr:left}]; delete this._left_has_or }
|
|
27
|
+
if (pred.includes('or')) pred = [{xpr:pred}]
|
|
36
28
|
_[_clause] = [ ...left, and_or, ...pred ]
|
|
37
29
|
}
|
|
38
30
|
}
|
|
@@ -111,4 +103,4 @@ const is_cqn = x => x.val !== undefined || x.xpr || x.ref || x.list || x.func ||
|
|
|
111
103
|
const is_array = Array.isArray
|
|
112
104
|
const operators = { '=':1, '<':2, '<=':2, '>':2, '>=':2, '!=':3, '<>':3, in:4, like:4, IN:4, LIKE:4 }
|
|
113
105
|
|
|
114
|
-
module.exports = Object.assign (
|
|
106
|
+
module.exports = Object.assign (Query, { predicate4, parse })
|
package/lib/ql/cds-ql.js
CHANGED
|
@@ -2,19 +2,25 @@ const cds = require('../index')
|
|
|
2
2
|
const Query = require('./Query')
|
|
3
3
|
require = path => { // eslint-disable-line no-global-assign
|
|
4
4
|
const clazz = module.require (path); if (!clazz._api) return clazz
|
|
5
|
+
const api = clazz._api()
|
|
5
6
|
Object.defineProperty (clazz.prototype, 'cmd', { value: path.match(/\w+$/)[0] })
|
|
6
|
-
return
|
|
7
|
+
return Object.assign (function (...args) {
|
|
8
|
+
if (new.target) return new clazz (...args) // allows: new SELECT
|
|
9
|
+
return api (...args) // allows: SELECT(...).from()
|
|
10
|
+
}, api)
|
|
7
11
|
}
|
|
8
12
|
|
|
9
13
|
module.exports = Object.assign (_deprecated_srv_ql, { cdr: true,
|
|
10
|
-
Query,
|
|
14
|
+
Query, clone(q) {
|
|
15
|
+
const cmd = q.cmd || Object.keys(q)[0]
|
|
16
|
+
return {__proto__:q, [cmd]: {__proto__:q[cmd] }}
|
|
17
|
+
},
|
|
11
18
|
SELECT: require('./SELECT'),
|
|
12
19
|
INSERT: require('./INSERT'),
|
|
13
20
|
UPDATE: require('./UPDATE'),
|
|
14
21
|
DELETE: require('./DELETE'),
|
|
15
22
|
CREATE: require('./CREATE'),
|
|
16
23
|
DROP: require('./DROP'),
|
|
17
|
-
clone(q) { return Query.prototype.clone.call(q) }
|
|
18
24
|
})
|
|
19
25
|
|
|
20
26
|
function _deprecated_srv_ql() { // eslint-disable-next-line no-console
|
package/lib/req/cds-context.js
CHANGED
|
@@ -10,7 +10,6 @@ module.exports = new class extends AsyncLocalStorage {
|
|
|
10
10
|
_context4(v) {
|
|
11
11
|
if (v instanceof EventContext || typeof v !== 'object') return v
|
|
12
12
|
if (v.context) return v.context
|
|
13
|
-
if (v.req) v = v.res ? {http:v} : {http:{ ...v, res: v.req.res }}
|
|
14
13
|
return EventContext.for(v)
|
|
15
14
|
}
|
|
16
15
|
|
|
@@ -31,12 +30,21 @@ module.exports = new class extends AsyncLocalStorage {
|
|
|
31
30
|
if (o instanceof EventContext) throw cds.error `The passed options must not be an instance of cds.EventContext.`
|
|
32
31
|
const fx = ()=>{
|
|
33
32
|
const tx = cds.tx({...o}) // create a new detached transaction for each run of the background job
|
|
34
|
-
return cds._context.run (tx, ()=>
|
|
33
|
+
return cds._context.run (tx, async ()=> {
|
|
34
|
+
// REVISIT: The model must be set _after_ run to make sure that cds.context.tenant is correctly set.
|
|
35
|
+
// Otherwise, `model4` could query the wrong database to check for extensions.
|
|
36
|
+
if (cds.model && (cds.env.requires.extensibility || cds.env.requires.toggles)) {
|
|
37
|
+
const ctx = cds.context
|
|
38
|
+
const ExtendedModels = require('../srv/srv-models') // the sentinel is automatically started when required
|
|
39
|
+
cds.context.model = await ExtendedModels.model4(ctx.tenant, ctx.features)
|
|
40
|
+
tx.model = cds.context.model
|
|
41
|
+
}
|
|
42
|
+
return Promise.resolve(fn(tx))
|
|
35
43
|
.then (tx.commit, e => tx.rollback(_error(e, cds)))
|
|
36
44
|
.then (res => Promise.all(em.listeners('succeeded').map(each => each(res))))
|
|
37
45
|
.catch (err => Promise.all(em.listeners('failed').map(each => each(err))))
|
|
38
46
|
.finally (() => Promise.all(em.listeners('done').map(each => each())))
|
|
39
|
-
)
|
|
47
|
+
})
|
|
40
48
|
}
|
|
41
49
|
const em = new EventEmitter; em.timer = (
|
|
42
50
|
(o && o.after) ? setTimeout(fx, o.after) :
|
package/lib/req/context.js
CHANGED
|
@@ -88,9 +88,18 @@ class EventContext {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
set user(u) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
if (u && typeof u === 'object') for (let p of ['tenant','locale']) {
|
|
92
|
+
let pd = Reflect.getOwnPropertyDescriptor(u,p)
|
|
93
|
+
if (pd?.value) this[p] = pd.value
|
|
94
|
+
}
|
|
95
|
+
let user = u instanceof cds.User ? Object.create(u,{
|
|
96
|
+
tenant: {get:()=> this.tenant},
|
|
97
|
+
locale: {get:()=> this.locale},
|
|
98
|
+
}) : Object.defineProperties (new cds.User(u), {
|
|
99
|
+
tenant: {get:()=> this.tenant},
|
|
100
|
+
locale: {get:()=> this.locale},
|
|
101
|
+
})
|
|
102
|
+
super.user = user
|
|
94
103
|
}
|
|
95
104
|
get user() {
|
|
96
105
|
this.user = this._propagated.user || _anonymous
|
|
@@ -109,13 +118,13 @@ class EventContext {
|
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
get _features() {
|
|
112
|
-
return super._features = this._propagated._features ||
|
|
121
|
+
return super._features = this._propagated._features || Features.for (this.http?.req?.features || this.user?.features || this.http?.req?.user?.features)
|
|
113
122
|
}
|
|
114
123
|
get features() {
|
|
115
|
-
return super.features = this._features ||
|
|
124
|
+
return super.features = this._features || Features.none
|
|
116
125
|
}
|
|
117
126
|
set features(v) {
|
|
118
|
-
super.features =
|
|
127
|
+
super.features = Features.for(v)
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
get model() {
|
|
@@ -174,26 +183,23 @@ class EventContext {
|
|
|
174
183
|
get _tx() { return this.tx } // REVISIT: for compatibility to bade usages of req._tx
|
|
175
184
|
}
|
|
176
185
|
|
|
177
|
-
const _TENANT_LOCALE = { tenant:1, locale:2 }
|
|
178
186
|
const _anonymous = new cds.User.default
|
|
179
187
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
get() { return
|
|
192
|
-
|
|
193
|
-
|
|
188
|
+
|
|
189
|
+
class Features {
|
|
190
|
+
static for (x) { // normalizes features to an object
|
|
191
|
+
if (!x) return
|
|
192
|
+
if (x === '*') return this.all
|
|
193
|
+
const fts = new this
|
|
194
|
+
if (Array.isArray(x)) { for (let f of x) fts[f] = true }
|
|
195
|
+
else if (typeof x === 'object') { for (let f in x) if (x[f]) fts[f] = true }
|
|
196
|
+
else if (typeof x === 'string') { for (let f of x.split(',')) fts[f] = true }
|
|
197
|
+
return fts
|
|
198
|
+
}
|
|
199
|
+
get $hash() { return super.$hash = Object.keys(this).join(',') }
|
|
200
|
+
static all = new Proxy ({'*':true},{ has:() => true, get:(_,p) => p === '$hash' ? '*' : true })
|
|
201
|
+
static none = new class none extends Features {}
|
|
194
202
|
}
|
|
195
|
-
const allFeatures = new Proxy ({'*':true},{ has:() => true, get:(_,p) => p === '$hash' ? '*' : true })
|
|
196
|
-
const noFeatures = {__proto__:{ $hash:'' }}
|
|
197
203
|
|
|
198
204
|
EventContext.prototype._set('_propagated', Object.seal({}))
|
|
199
205
|
EventContext.propagateHeaders = [ 'x-correlation-id' ]
|
package/lib/req/locale.js
CHANGED
|
@@ -5,14 +5,18 @@ const INCLUDE_LIST = i18n.preserved_locales.reduce((p,n)=>{
|
|
|
5
5
|
},{
|
|
6
6
|
en_US_x_saptrc: 'en_US_saptrc',
|
|
7
7
|
en_US_x_sappsd: 'en_US_sappsd',
|
|
8
|
-
en_US_x_saprigi: 'en_US_saprigi'
|
|
9
|
-
'1Q': 'en_US_saptrc',
|
|
10
|
-
'2Q': 'en_US_sappsd',
|
|
11
|
-
'3Q': 'en_US_saprigi'
|
|
8
|
+
en_US_x_saprigi: 'en_US_saprigi'
|
|
12
9
|
})
|
|
13
10
|
|
|
11
|
+
const SAP_LANGUAGES = {
|
|
12
|
+
'1Q': 'en_US_x_saptrc',
|
|
13
|
+
'2Q': 'en_US_x_sappsd',
|
|
14
|
+
'3Q': 'en_US_x_saprigi'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// normalizes to BCP47
|
|
14
18
|
const from_req = req => req && (
|
|
15
|
-
req.query && req.query['sap-language'] ||
|
|
19
|
+
req.query && (req.query['sap-locale'] || SAP_LANGUAGES[req.query['sap-language']]) ||
|
|
16
20
|
req.headers && (req.headers['x-sap-request-language'] || req.headers['accept-language'])
|
|
17
21
|
)
|
|
18
22
|
|
package/lib/req/request.js
CHANGED
|
@@ -61,6 +61,7 @@ class Request extends require('./event') {
|
|
|
61
61
|
warn (...args) { return this._messages.add (3, ...args) }
|
|
62
62
|
error (...args) { return this._errors.add (4, ...args) }
|
|
63
63
|
reject (...args) {
|
|
64
|
+
if (args[0] === 401 && this._.req?.login) return this._.req.login()
|
|
64
65
|
let e = this.error(...args)
|
|
65
66
|
if (!e.stack) Error.captureStackTrace (e = Object.assign(new Error,e), this.reject)
|
|
66
67
|
throw e
|
package/lib/req/user.js
CHANGED
|
@@ -8,7 +8,8 @@ class User {
|
|
|
8
8
|
}
|
|
9
9
|
if (typeof _ === 'string') { this.id = _; return }
|
|
10
10
|
for (let each in _) super[each === '_roles' ? 'roles' : each] = _[each] // overrides getters
|
|
11
|
-
|
|
11
|
+
const roles = this.hasOwnProperty('roles') && this.roles // eslint-disable-line no-prototype-builtins
|
|
12
|
+
if (Array.isArray(roles)) this.roles = roles.reduce ((p,n)=>{p[n]=1; return p},{})
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
get attr() { return super.attr = {} }
|
package/lib/srv/cds-connect.js
CHANGED
|
@@ -6,7 +6,7 @@ const _pending = cds.services._pending || {} // used below to chain parallel con
|
|
|
6
6
|
*/
|
|
7
7
|
const connect = module.exports = async function cds_connect (options) {
|
|
8
8
|
if (typeof options === 'object' && cds.db) throw cds.error (
|
|
9
|
-
`
|
|
9
|
+
`Re-connect to primary db with potentially different options is not allowed!`
|
|
10
10
|
)
|
|
11
11
|
if (typeof options === 'string') cds.db = await connect.to (options)
|
|
12
12
|
else await connect.to ('db',options)
|