@sap/cds 8.5.0 → 8.6.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.
- package/CHANGELOG.md +54 -3
- package/_i18n/i18n.properties +4 -7
- package/eslint.config.mjs +1 -1
- package/lib/compile/etc/properties.js +2 -2
- package/lib/compile/for/java.js +15 -3
- package/lib/compile/for/lean_drafts.js +44 -34
- package/lib/compile/for/nodejs.js +19 -10
- package/lib/compile/minify.js +2 -4
- package/lib/compile/parse.js +106 -72
- package/lib/compile/to/edm.js +19 -9
- package/lib/compile/to/hana.js +25 -21
- package/lib/compile/to/sql.js +15 -8
- package/lib/core/linked-csn.js +10 -4
- package/lib/dbs/cds-deploy.js +2 -2
- package/lib/env/cds-env.js +76 -66
- package/lib/env/defaults.js +1 -0
- package/lib/i18n/bundles.js +2 -1
- package/lib/i18n/localize.js +2 -2
- package/lib/index.js +24 -18
- package/lib/ql/CREATE.js +11 -6
- package/lib/ql/DELETE.js +12 -9
- package/lib/ql/DROP.js +15 -8
- package/lib/ql/INSERT.js +19 -14
- package/lib/ql/SELECT.js +95 -168
- package/lib/ql/UPDATE.js +23 -14
- package/lib/ql/UPSERT.js +15 -2
- package/lib/ql/Whereable.js +44 -118
- package/lib/ql/cds-ql.js +222 -28
- package/lib/ql/{Query.js → cds.ql-Query.js} +52 -41
- package/lib/ql/cds.ql-predicates.js +133 -0
- package/lib/ql/cds.ql-projections.js +111 -0
- package/lib/ql/cqn.d.ts +146 -0
- package/lib/srv/cds-connect.js +3 -3
- package/lib/srv/cds-serve.js +2 -2
- package/lib/srv/cds.Service.js +132 -0
- package/lib/srv/{srv-api.js → cds.ServiceClient.js} +16 -71
- package/lib/srv/cds.ServiceProvider.js +20 -0
- package/lib/srv/factory.js +20 -8
- package/lib/srv/protocols/hcql.js +2 -3
- package/lib/srv/protocols/index.js +3 -3
- package/lib/srv/srv-dispatch.js +7 -6
- package/lib/srv/srv-handlers.js +103 -113
- package/lib/srv/srv-methods.js +14 -14
- package/lib/srv/srv-tx.js +5 -3
- package/lib/utils/cds-utils.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +3 -3
- package/libx/_runtime/cds.js +2 -1
- package/libx/_runtime/common/aspects/service.js +25 -0
- package/libx/_runtime/common/generic/auth/index.js +5 -0
- package/libx/_runtime/common/generic/auth/restrict.js +36 -14
- package/libx/_runtime/common/generic/auth/service.js +24 -0
- package/libx/_runtime/common/generic/auth/utils.js +14 -6
- package/libx/_runtime/common/generic/etag.js +1 -1
- package/libx/_runtime/common/utils/cqn.js +1 -2
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +1 -1
- package/libx/_runtime/common/utils/generateOnCond.js +7 -3
- package/libx/_runtime/common/utils/postProcess.js +4 -1
- package/libx/_runtime/common/utils/restrictions.js +1 -0
- package/libx/_runtime/fiori/lean-draft.js +53 -42
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -1
- package/libx/_runtime/remote/Service.js +2 -0
- package/libx/_runtime/remote/utils/client.js +12 -0
- package/libx/odata/ODataAdapter.js +2 -1
- package/libx/odata/index.js +5 -3
- package/libx/odata/middleware/batch.js +4 -0
- package/libx/odata/middleware/create.js +2 -2
- package/libx/odata/middleware/delete.js +2 -2
- package/libx/odata/middleware/operation.js +2 -2
- package/libx/odata/middleware/read.js +14 -12
- package/libx/odata/middleware/service-document.js +16 -8
- package/libx/odata/middleware/update.js +2 -2
- package/libx/odata/parse/afterburner.js +64 -30
- package/libx/odata/parse/grammar.peggy +95 -0
- package/libx/odata/parse/parser.js +1 -1
- package/libx/odata/utils/index.js +6 -1
- package/libx/odata/utils/metadata.js +69 -75
- package/libx/odata/utils/postProcess.js +24 -3
- package/package.json +1 -1
- package/server.js +1 -1
- package/lib/ql/parse.js +0 -36
- /package/lib/ql/{infer.js → cds.ql-infer.js} +0 -0
package/lib/compile/to/sql.js
CHANGED
|
@@ -7,13 +7,20 @@ const TRACE = cds.debug('trace')
|
|
|
7
7
|
|
|
8
8
|
function cds_compile_to_sql (csn,_o) {
|
|
9
9
|
TRACE?.time('cdsc.compile 2sql'.padEnd(22))
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
try {
|
|
11
|
+
let result, next = ()=> result ??= function (){
|
|
12
|
+
csn = cds.minify(csn)
|
|
13
|
+
const o = cdsc._options.for.sql(_o) //> used twice below...
|
|
14
|
+
const all = cdsc.to.sql(csn,o) .map (each => each.replace(/^-- .+\n/,'')) //> strip comments
|
|
15
|
+
const sql = unfold_ddl(all, csn, o)
|
|
16
|
+
TRACE?.timeEnd('cdsc.compile 2sql'.padEnd(22))
|
|
17
|
+
if (o.as === 'str') return `\n${sql.join('\n\n')}\n`
|
|
18
|
+
return sql
|
|
19
|
+
}()
|
|
20
|
+
cds.emit ('compile.to.dbx', csn, _o, next)
|
|
21
|
+
return result ??= next() //> in case no handler called next
|
|
22
|
+
}
|
|
23
|
+
finally { TRACE?.timeEnd('cds.compile 2sql'.padEnd(22)) }
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
function cds_compile_to_hdbtable (csn,o) {
|
|
@@ -23,7 +30,7 @@ function cds_compile_to_hdbtable (csn,o) {
|
|
|
23
30
|
|
|
24
31
|
function cds_compile_to_hana(csn, o, beforeCsn) {
|
|
25
32
|
return require('./hana')(cds.minify(csn), o, beforeCsn)
|
|
26
|
-
}
|
|
33
|
+
}
|
|
27
34
|
|
|
28
35
|
function cds_compile_to_deltaSql (csn, o, beforeCsn) {
|
|
29
36
|
const options = cdsc._options.for.sql(o)
|
package/lib/core/linked-csn.js
CHANGED
|
@@ -13,9 +13,10 @@ const _kinds = {
|
|
|
13
13
|
|
|
14
14
|
class LinkedCSN {
|
|
15
15
|
|
|
16
|
-
constructor(x) {
|
|
16
|
+
constructor (x,...etc) {
|
|
17
17
|
|
|
18
|
-
if (
|
|
18
|
+
if (x.raw) x = require('../index').compile(String.raw(x,...etc)) //> for convenience in repl
|
|
19
|
+
else if (typeof x === 'string') x = require('../index').compile(x) //> for convenience in repl
|
|
19
20
|
const defs = x.definitions = _iterable (x.definitions||{})
|
|
20
21
|
for (let d in defs) _link (defs[d],d)
|
|
21
22
|
return Object.setPrototypeOf (x, new.target.prototype)
|
|
@@ -124,7 +125,7 @@ class LinkedCSN {
|
|
|
124
125
|
const _iterable = defs => defs && Object.setPrototypeOf (defs, LinkedDefinitions.prototype)
|
|
125
126
|
const _unresolved = (x, unknown = types.any) => ({ name:x, __proto__:unknown, _unresolved:true })
|
|
126
127
|
const _builtin = x => types[x] || x.startsWith?.('cds.hana.') && types.any
|
|
127
|
-
const _infer = require('../ql/infer')
|
|
128
|
+
const _infer = require('../ql/cds.ql-infer')
|
|
128
129
|
const _set = (o,p,v,e=false) => Object.defineProperty (o,p,{ value:v, enumerable:e, configurable:1, writable:1 })
|
|
129
130
|
const _own = (o,p) => { const pd = Reflect.getOwnPropertyDescriptor(o,p); return pd && pd.value }
|
|
130
131
|
const _is = x => {
|
|
@@ -140,4 +141,9 @@ any.prototype.set('is_linked', true)
|
|
|
140
141
|
|
|
141
142
|
|
|
142
143
|
/** @returns {LinkedCSN} */
|
|
143
|
-
|
|
144
|
+
const cds_linked = x => !x || x.is_linked ? x : new LinkedCSN (x)
|
|
145
|
+
|
|
146
|
+
module.exports = Object.assign (cds_linked, {
|
|
147
|
+
LinkedCSN, LinkedDefinitions,
|
|
148
|
+
types, classes
|
|
149
|
+
})
|
package/lib/dbs/cds-deploy.js
CHANGED
|
@@ -7,7 +7,7 @@ const TRACE = cds.debug('trace')
|
|
|
7
7
|
/** Fluent API: cds.deploy(model).to(db) */
|
|
8
8
|
const deploy = module.exports = function cds_deploy (model, options, csvs) {
|
|
9
9
|
|
|
10
|
-
return { async to (/** @type {import('
|
|
10
|
+
return { async to (/** @type {import('../srv/cds.ServiceClient')} */ db, o = options||{}) {
|
|
11
11
|
/* eslint-disable no-console */
|
|
12
12
|
|
|
13
13
|
// prepare logging
|
|
@@ -37,7 +37,7 @@ const deploy = module.exports = function cds_deploy (model, options, csvs) {
|
|
|
37
37
|
const _run = fn => o.dry ? fn(db) : db.run(fn)
|
|
38
38
|
await _run (async tx => {
|
|
39
39
|
let any = await deploy.schema (tx, model, o)
|
|
40
|
-
if (any || csvs) await deploy.data (tx, model, o, csvs, file => LOG?.(GREY, ' > init from', local(file), RESET))
|
|
40
|
+
if ((any || csvs) && !o.dry) await deploy.data (tx, model, o, csvs, file => LOG?.(GREY, ' > init from', local(file), RESET))
|
|
41
41
|
})
|
|
42
42
|
LOG?.('/> successfully deployed to', descr, '\n')
|
|
43
43
|
} catch (e) {
|
package/lib/env/cds-env.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { isdir, isfile, fs, path } = require('../utils/cds-utils')
|
|
2
2
|
const DEFAULTS = require('./defaults'), defaults = require.resolve ('./defaults')
|
|
3
3
|
const compat = require('./compat')
|
|
4
|
-
const
|
|
4
|
+
const DEBUG = /\b(y|all|env)\b/.test(process.env.DEBUG) ? console.debug : undefined
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -48,20 +48,25 @@ class Config {
|
|
|
48
48
|
if (_context === 'cds' && _defaults) compat (this)
|
|
49
49
|
if (!_home) return
|
|
50
50
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
console.error('@sap/cds-mtx is not supported by @sap/cds >= 7. Please upgrade to @sap/cds-mtxs following the migration guide on https://cap.cloud.sap/docs/guides/multitenancy/old-mtx-migration.')
|
|
62
|
-
process.exit(1)
|
|
51
|
+
// Read config sources in reverse order of precedence -> last one wins
|
|
52
|
+
if (_context !== 'cds') {
|
|
53
|
+
this.#import (_home,'package.json', { get: p => p[_context] })
|
|
54
|
+
} else {
|
|
55
|
+
for (let {impl} of Object.values(this.plugins)) {
|
|
56
|
+
const _plugin = path.dirname(impl)
|
|
57
|
+
this.#import (_plugin,'.cdsrc.yaml', { load: _readYaml })
|
|
58
|
+
this.#import (_plugin,'.cdsrc.json')
|
|
59
|
+
this.#import (_plugin,'.cdsrc.js')
|
|
60
|
+
this.#import (_plugin,'package.json', { get: p => p.cds })
|
|
63
61
|
}
|
|
64
|
-
|
|
62
|
+
const user_ = process.env.CDS_USER_HOME || require('os').homedir()
|
|
63
|
+
this.#import (user_,'.cdsrc.json')
|
|
64
|
+
this.#import (user_,'.cdsrc.js')
|
|
65
|
+
this.#import (_home,'.cdsrc.yaml', { load: _readYaml })
|
|
66
|
+
this.#import (_home,'.cdsrc.json')
|
|
67
|
+
this.#import (_home,'.cdsrc.js')
|
|
68
|
+
this.#import (_home,'package.json', { get: _ext_package_json })
|
|
69
|
+
this.#import (_home,'.cdsrc-private.json')
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
// Apply important (!) profiles from config sources
|
|
@@ -69,7 +74,7 @@ class Config {
|
|
|
69
74
|
delete this._profiles._important
|
|
70
75
|
|
|
71
76
|
// Add process env before linking to allow things like CDS_requires_db=sql
|
|
72
|
-
this._add_process_env(
|
|
77
|
+
this._add_process_env()
|
|
73
78
|
|
|
74
79
|
// Link cds.requires services to cds.requires.kinds
|
|
75
80
|
this._link_required_services()
|
|
@@ -93,31 +98,21 @@ class Config {
|
|
|
93
98
|
}
|
|
94
99
|
}
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
return
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
{ path: user_home, file: '.cdsrc.json', mapper: x => x.cds||x },
|
|
112
|
-
{ path: home, file: '.cdsrc.json', mapper: x => x.cds||x },
|
|
113
|
-
{ path: home, file: 'package.json', mapper: _package_json },
|
|
114
|
-
{ path: home, file: '.cdsrc-private.json', mapper: x => x.cds||x },
|
|
115
|
-
]
|
|
116
|
-
function _package_json (pkg) { // fill cds.extends from .extends
|
|
117
|
-
let cds = pkg.cds
|
|
118
|
-
if (pkg.extends) (cds??={}).extends = pkg.extends
|
|
119
|
-
return cds
|
|
120
|
-
}
|
|
101
|
+
|
|
102
|
+
#import (dir, file, etc) {
|
|
103
|
+
let conf = this.load (dir, file, etc)
|
|
104
|
+
if (conf) this.add (conf)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
load (dir, file, { load=_readJson, get = x => x.cds||x } = {}) {
|
|
109
|
+
file = path.join (dir, file)
|
|
110
|
+
DEBUG?.('[cds.env] - checking', {file})
|
|
111
|
+
let cont = load(file); if (!cont) return
|
|
112
|
+
let conf = get(cont); if (!conf) return
|
|
113
|
+
DEBUG?.('[cds.env] - importing', file)
|
|
114
|
+
this._sources.push (file)
|
|
115
|
+
return conf
|
|
121
116
|
}
|
|
122
117
|
|
|
123
118
|
|
|
@@ -194,25 +189,25 @@ class Config {
|
|
|
194
189
|
// The following are internal APIs which can always change!
|
|
195
190
|
//
|
|
196
191
|
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const val = all[key]
|
|
204
|
-
process.env[key] = typeof val === 'string' ? val : JSON.stringify(val)
|
|
205
|
-
}
|
|
206
|
-
this._sources.push (file)
|
|
207
|
-
} catch (e) {
|
|
208
|
-
if (e instanceof SyntaxError) console.error(`Error parsing '${file}': ${e.message}`)
|
|
209
|
-
else if (e.code !== 'MODULE_NOT_FOUND') console.error(e.message)
|
|
192
|
+
_add_to_env (filename, env = process.env) {
|
|
193
|
+
const _env = this.load (this._home, filename, { load: _readEnv })
|
|
194
|
+
for (const key in _env) {
|
|
195
|
+
if (key in env) continue // do not change existing env vars
|
|
196
|
+
const val = _env[key]
|
|
197
|
+
env[key] = typeof val === 'string' ? val : JSON.stringify(val)
|
|
210
198
|
}
|
|
211
199
|
}
|
|
212
200
|
|
|
213
|
-
|
|
214
|
-
|
|
201
|
+
_add_process_env() {
|
|
202
|
+
const prefix = this._context, cwd = this._home
|
|
215
203
|
const {env} = process
|
|
204
|
+
if (this._profiles.has('development')) {
|
|
205
|
+
this._add_to_env ('default-env.json', env)
|
|
206
|
+
for (let each of this._profiles)
|
|
207
|
+
each === 'development' || this._add_to_env (`.${each}.env`, env)
|
|
208
|
+
this._add_to_env ('.env', env)
|
|
209
|
+
}
|
|
210
|
+
|
|
216
211
|
const PREF = prefix.toUpperCase(), my = { CONFIG: PREF+'_CONFIG', ENV: PREF+'_ENV' }
|
|
217
212
|
let config
|
|
218
213
|
|
|
@@ -224,7 +219,7 @@ class Config {
|
|
|
224
219
|
// CDS_CONFIG=/path/to/config.json *OR* CDS_CONFIG=/path/to/config/dir
|
|
225
220
|
if (typeof val === "string") {
|
|
226
221
|
// Load from JSON file or directory; No profile support!
|
|
227
|
-
if (
|
|
222
|
+
if (cwd && !path.isAbsolute(val)) val = path.join(cwd, val)
|
|
228
223
|
const json = _readJson(val) || _readFromDir(val)
|
|
229
224
|
if (json) this.add (json, val, false)
|
|
230
225
|
}
|
|
@@ -246,7 +241,7 @@ class Config {
|
|
|
246
241
|
o[next] = _value4(env[p])
|
|
247
242
|
}
|
|
248
243
|
|
|
249
|
-
this.add(config, 'process.env')
|
|
244
|
+
if (Object.keys(config).length) this.add (config, 'process.env')
|
|
250
245
|
}
|
|
251
246
|
|
|
252
247
|
_link_required_services () {
|
|
@@ -312,7 +307,7 @@ class Config {
|
|
|
312
307
|
}
|
|
313
308
|
|
|
314
309
|
if (!bindings && SERVICE_BINDING_ROOT) {
|
|
315
|
-
bindings = serviceBindings(SERVICE_BINDING_ROOT)
|
|
310
|
+
bindings = require('./serviceBindings')(SERVICE_BINDING_ROOT)
|
|
316
311
|
bindingsSource = SERVICE_BINDING_ROOT
|
|
317
312
|
}
|
|
318
313
|
|
|
@@ -435,7 +430,7 @@ class Config {
|
|
|
435
430
|
*/
|
|
436
431
|
function _add_static_profiles (_home, profiles) {
|
|
437
432
|
for (let src of ['package.json', '.cdsrc.json']) try {
|
|
438
|
-
|
|
433
|
+
const conf = require(path.join(_home,src))
|
|
439
434
|
const cds = src === 'package.json' ? conf.cds : conf.cds||conf
|
|
440
435
|
if (cds?.profiles) return profiles.push(...cds.profiles)
|
|
441
436
|
if (cds?.profile) return profiles.push(cds.profile)
|
|
@@ -495,17 +490,26 @@ function _value4 (val) {
|
|
|
495
490
|
return val
|
|
496
491
|
}
|
|
497
492
|
|
|
498
|
-
function _readJson (file
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
return JSON.parse (
|
|
502
|
-
} catch (e) {
|
|
503
|
-
if (e instanceof SyntaxError) console.error(`Error parsing '${file}': ${e.message}`)
|
|
504
|
-
else if (e.code !== 'MODULE_NOT_FOUND') console.error(e.message)
|
|
493
|
+
function _readJson (file) {
|
|
494
|
+
if (isfile(file)) {
|
|
495
|
+
if (file.endsWith('.js')) return require (file)
|
|
496
|
+
try { return JSON.parse (fs.readFileSync(file,'utf-8')) } catch (e) { console.error(e) }
|
|
505
497
|
}
|
|
506
498
|
}
|
|
507
499
|
|
|
500
|
+
function _readYaml (file) {
|
|
501
|
+
if (isfile(file)) {
|
|
502
|
+
const YAML = _readYaml.parser ??= require('../compile/etc/yaml')
|
|
503
|
+
return YAML.parse (fs.readFileSync(file,'utf-8'))
|
|
504
|
+
}
|
|
505
|
+
}
|
|
508
506
|
|
|
507
|
+
function _readEnv (file) {
|
|
508
|
+
if (isfile(file)) {
|
|
509
|
+
const ENV = _readEnv.parser = require('../compile/etc/properties')
|
|
510
|
+
return ENV.parse (fs.readFileSync(file,'utf-8'))
|
|
511
|
+
}
|
|
512
|
+
}
|
|
509
513
|
|
|
510
514
|
function _readFromDir (p) {
|
|
511
515
|
if (isdir(p)) {
|
|
@@ -516,6 +520,12 @@ function _readFromDir (p) {
|
|
|
516
520
|
return _value4(fs.readFileSync(p, "utf-8"))
|
|
517
521
|
}
|
|
518
522
|
|
|
523
|
+
// REVISIT: We need to get rid of such hard-coded stuff
|
|
524
|
+
function _ext_package_json (pkg) { // fill cds.extends from .extends
|
|
525
|
+
let cds = pkg.cds
|
|
526
|
+
if (pkg.extends) (cds??={}).extends = pkg.extends
|
|
527
|
+
return cds
|
|
528
|
+
}
|
|
519
529
|
|
|
520
530
|
|
|
521
531
|
/** @type Config & typeof DEFAULTS */
|
package/lib/env/defaults.js
CHANGED
|
@@ -152,6 +152,7 @@ const defaults = module.exports = {
|
|
|
152
152
|
/** @deprecated */ for_sqlite: ['de', 'fr'],
|
|
153
153
|
/** @deprecated */ for_sql: ['de', 'fr'],
|
|
154
154
|
/** @deprecated */ fallback_bundle: '',
|
|
155
|
+
/** @deprecated */ fatjson: true, // REVISIT: remove in cds9
|
|
155
156
|
},
|
|
156
157
|
|
|
157
158
|
odata: {
|
package/lib/i18n/bundles.js
CHANGED
|
@@ -73,7 +73,8 @@ class I18nBundle {
|
|
|
73
73
|
if (lang in $) return $[locale] = $[lang] // already cached -> leave method
|
|
74
74
|
else all = this.files.content4 (lang, lang) // load content for language only
|
|
75
75
|
}
|
|
76
|
-
const
|
|
76
|
+
const defaults = (_defaults ?? this.defaults) || Object.prototype
|
|
77
|
+
const texts = i18n.fatjson ? Object.assign ({},defaults) : Object.create (defaults)
|
|
77
78
|
return $[locale] = $[suffix] = Object.assign (texts, ...all)
|
|
78
79
|
}
|
|
79
80
|
|
package/lib/i18n/localize.js
CHANGED
|
@@ -56,8 +56,8 @@ class Localize {
|
|
|
56
56
|
|
|
57
57
|
module.exports = exports = localize
|
|
58
58
|
|
|
59
|
-
function localize (input) {
|
|
60
|
-
if (
|
|
59
|
+
function localize (input,...etc) {
|
|
60
|
+
if (etc.length) return exports.legacy (input,...etc)
|
|
61
61
|
return new Localize (input)
|
|
62
62
|
}
|
|
63
63
|
|
package/lib/index.js
CHANGED
|
@@ -4,15 +4,18 @@ if (process.env.CDS_STRICT_NODE_VERSION !== 'false') require ('./utils/check-ver
|
|
|
4
4
|
const { EventEmitter } = require('node:events')
|
|
5
5
|
const cds = module.exports = global.cds = new class cds extends EventEmitter {
|
|
6
6
|
|
|
7
|
-
/** @typedef {import('./srv/
|
|
8
|
-
/** @type {import('./core/linked-csn
|
|
7
|
+
/** @typedef {import('./srv/cds.ServiceProvider')} Service */
|
|
8
|
+
/** @type {import('./core/linked-csn')} */ model = undefined
|
|
9
9
|
/** @type Service */ db = undefined
|
|
10
10
|
/** CLI args */ cli = { command:'', options:{}, argv:[] }
|
|
11
11
|
/** Working dir */ root = process.cwd()
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
if (eve === 'served')
|
|
15
|
-
|
|
13
|
+
emit (eve, ...args) {
|
|
14
|
+
if (eve === 'served') return this.listeners(eve) .reduce (
|
|
15
|
+
(p,each) => p.then(()=> each.call(this,...args)),
|
|
16
|
+
Promise.resolve()
|
|
17
|
+
)
|
|
18
|
+
else return super.emit (eve, ...args)
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
// Configuration & Information
|
|
@@ -69,7 +72,7 @@ const cds = module.exports = global.cds = new class cds extends EventEmitter {
|
|
|
69
72
|
shutdown() { this.app?.server && process.exit() } // is overridden in bin/serve.js
|
|
70
73
|
|
|
71
74
|
// Core Services API
|
|
72
|
-
get Service() { return super.Service = require('./srv/
|
|
75
|
+
get Service() { return super.Service = require('./srv/cds.ServiceProvider') }
|
|
73
76
|
get EventContext() { return super.EventContext = require('./req/context') }
|
|
74
77
|
get Request() { return super.Request = require('./req/request') }
|
|
75
78
|
get Event() { return super.Event = require('./req/event') }
|
|
@@ -82,7 +85,7 @@ const cds = module.exports = global.cds = new class cds extends EventEmitter {
|
|
|
82
85
|
get DatabaseService() { return super.DatabaseService = require('../libx/_runtime/db/Service.js') }
|
|
83
86
|
get RemoteService() { return super.RemoteService = require('../libx/_runtime/remote/Service.js') }
|
|
84
87
|
|
|
85
|
-
/** Contexts and Transactions @type {import('./req/context
|
|
88
|
+
/** Contexts and Transactions @type {import('./req/context')} */
|
|
86
89
|
get context() { return this._context.getStore() }
|
|
87
90
|
set context(x) { this._context.enterWith(x) }
|
|
88
91
|
get spawn() { return super.spawn = this._context.spawn }
|
|
@@ -98,7 +101,7 @@ const cds = module.exports = global.cds = new class cds extends EventEmitter {
|
|
|
98
101
|
clone(x) { return structuredClone(x) }
|
|
99
102
|
|
|
100
103
|
// Querying and Databases
|
|
101
|
-
get infer(){ return super.infer = require('./ql/infer') }
|
|
104
|
+
get infer(){ return super.infer = require('./ql/cds.ql-infer.js') }
|
|
102
105
|
get txs() { return super.txs = new this.Service('cds.tx') }
|
|
103
106
|
get ql() { return super.ql = require('./ql/cds-ql') }
|
|
104
107
|
tx (..._) { return (this.db || this.txs).tx(..._) }
|
|
@@ -122,17 +125,20 @@ const cds = module.exports = global.cds = new class cds extends EventEmitter {
|
|
|
122
125
|
|
|
123
126
|
// Add global convenience shortcuts for cds.ql and cds.parse commands
|
|
124
127
|
cds.extend (global) .with ( class globals {
|
|
125
|
-
get SELECT() { return
|
|
126
|
-
get INSERT() { return
|
|
127
|
-
get UPSERT() { return
|
|
128
|
-
get UPDATE() { return
|
|
129
|
-
get DELETE() { return
|
|
130
|
-
get CREATE() { return cds.ql.CREATE }
|
|
131
|
-
get DROP() { return cds.ql.DROP }
|
|
132
|
-
get CDL() { return cds.parse.
|
|
133
|
-
get CQL() { return cds.parse.
|
|
134
|
-
get CXL() { return cds.parse.
|
|
128
|
+
get SELECT() { return Q('SELECT') }
|
|
129
|
+
get INSERT() { return Q('INSERT') }
|
|
130
|
+
get UPSERT() { return Q('UPSERT') }
|
|
131
|
+
get UPDATE() { return Q('UPDATE') }
|
|
132
|
+
get DELETE() { return Q('DELETE') }
|
|
133
|
+
/** @deprecated */ get CREATE() { return D('CREATE', '{CREATE} = cds.ql', cds.ql.CREATE) }
|
|
134
|
+
/** @deprecated */ get DROP() { return D('DROP', '{DROP} = cds.ql', cds.ql.DROP) }
|
|
135
|
+
/** @deprecated */ get CDL() { return D('CDL', 'cds.parse.cdl', cds.parse.cdl) }
|
|
136
|
+
/** @deprecated */ get CQL() { return D('CQL', 'cds.parse.cql', cds.parse.cql) }
|
|
137
|
+
/** @deprecated */ get CXL() { return D('CXL', 'cds.parse.expr', cds.parse.expr) }
|
|
135
138
|
} .prototype )
|
|
139
|
+
function Q (p) { return G (p, cds.ql[p]) }
|
|
140
|
+
function D (old,use,fn) { return G (old, cds.utils.deprecated (fn,{kind:'Global constant',old,use})) }
|
|
141
|
+
function G (p,v) { Object.defineProperty (global, p, { value:v, enumerable:1,configurable:1}); return v }
|
|
136
142
|
|
|
137
143
|
// Allow for `import cds from '@sap/cds'` without `esModuleInterop` in tsconfig.json
|
|
138
144
|
Object.defineProperties (module.exports, { default: {value:cds}, __esModule: {value:true} })
|
package/lib/ql/CREATE.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
const Query = require('./cds.ql-Query')
|
|
2
|
+
class CREATE extends Query {
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** @type import('./cqn').CREATE['CREATE'] */
|
|
5
|
+
CREATE = {}
|
|
6
|
+
|
|
7
|
+
static call = (..._) => (new this).entity(..._)
|
|
8
|
+
static API = { class:this,
|
|
9
|
+
entity: (..._) => (new this).entity(..._)
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
entity (e, elements) {
|
|
@@ -23,3 +25,6 @@ module.exports = class Query extends require('./Query') {
|
|
|
23
25
|
|
|
24
26
|
get _target_ref(){ return this.CREATE.entity }
|
|
25
27
|
}
|
|
28
|
+
|
|
29
|
+
/** @type CREATE.API & (...entries:[]) => CREATE */
|
|
30
|
+
module.exports = CREATE.init()
|
package/lib/ql/DELETE.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
const Whereable = require('./Whereable')
|
|
2
|
+
class DELETE extends Whereable {
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/** @type import('./cqn').DELETE['DELETE'] */
|
|
5
|
+
DELETE = {}
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
static
|
|
7
|
-
|
|
8
|
-
from: (..._) => (new this).from(..._),
|
|
9
|
-
})
|
|
7
|
+
static call = (..._) => (new this).from(..._)
|
|
8
|
+
static API = { class:this,
|
|
9
|
+
from: (..._) => (new this).from(..._)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
from(entity,
|
|
13
|
-
this.DELETE.from = this._target4 (...
|
|
14
|
-
if (
|
|
12
|
+
from (entity, ...etc) {
|
|
13
|
+
this.DELETE.from = this._target4 (entity, ...etc) // supporting tts
|
|
14
|
+
if (!entity.raw && etc.length) this.byKey(etc[0])
|
|
15
15
|
return this
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -21,3 +21,6 @@ module.exports = class Query extends Whereable {
|
|
|
21
21
|
|
|
22
22
|
get _target_ref(){ return this.DELETE.from }
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
/** @type DELETE.API & (...entries:[]) => DELETE */
|
|
26
|
+
module.exports = DELETE.init()
|
package/lib/ql/DROP.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
const Query = require('./cds.ql-Query')
|
|
2
|
+
class DROP extends Query {
|
|
3
|
+
|
|
4
|
+
/** @type import('./cqn').DROP['DROP'] */
|
|
5
|
+
DROP = {}
|
|
6
|
+
|
|
7
|
+
static call = (..._) => (new this).entity(..._)
|
|
8
|
+
static API = { class:this,
|
|
9
|
+
entity: (..._) => (new this).entity(..._),
|
|
10
|
+
table: (..._) => (new this).table(..._),
|
|
11
|
+
view: (..._) => (new this).view(..._),
|
|
9
12
|
}
|
|
13
|
+
|
|
10
14
|
entity(e) {
|
|
11
15
|
this.DROP.entity = this._target4 (e)
|
|
12
16
|
return this
|
|
@@ -24,3 +28,6 @@ module.exports = class Query extends require('./Query') {
|
|
|
24
28
|
|
|
25
29
|
get _target_ref(){ return this.DROP.entity }
|
|
26
30
|
}
|
|
31
|
+
|
|
32
|
+
/** @type DROP.API & (...entries:[]) => DROP */
|
|
33
|
+
module.exports = DROP.init()
|
package/lib/ql/INSERT.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
const Query = require('./cds.ql-Query')
|
|
2
|
+
class INSERT extends Query {
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** @type import('./cqn').INSERT['INSERT'] */
|
|
5
|
+
INSERT = {}
|
|
6
|
+
|
|
7
|
+
static call = (..._) => (new this).entries(..._)
|
|
8
|
+
static API = { class:this,
|
|
9
|
+
into: (..._) => (new this).into(..._)
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
into (entity, ...data) {
|
|
11
|
-
this._.into = this._target4 (...
|
|
13
|
+
this._.into = this._target4 (entity, ...data) // supporting tts
|
|
12
14
|
if (data.length) this.entries(...data)
|
|
13
15
|
return this
|
|
14
16
|
}
|
|
@@ -44,18 +46,21 @@ module.exports = class Query extends require('./Query') {
|
|
|
44
46
|
return this
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
/** @deprecated */ as (
|
|
48
|
-
INSERT_as_SELECT ??= require('../utils').deprecated(()=>{},{old:'INSERT.as(SELECT)', use:'INSERT.entries(SELECT)'})
|
|
49
|
-
INSERT_as_SELECT()
|
|
50
|
-
return this.from(query)
|
|
51
|
-
}
|
|
49
|
+
/** @deprecated */ as(q) { return this.from(q) }
|
|
52
50
|
|
|
53
51
|
valueOf() {
|
|
54
52
|
return super.valueOf('INSERT INTO')
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
get _target_ref(){ return this.
|
|
55
|
+
get _target_ref(){ return ( this.INSERT || this.UPSERT ).into }
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
const is_array = Array.isArray
|
|
61
|
-
|
|
59
|
+
|
|
60
|
+
INSERT.prototype.as = require('../utils').deprecated (INSERT.prototype.as, {
|
|
61
|
+
old:'INSERT.as(SELECT)',
|
|
62
|
+
use:'INSERT.entries(SELECT)'
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
/** @type INSERT.API & (...entries:[]) => INSERT */
|
|
66
|
+
module.exports = INSERT.init()
|