@sap/cds 6.0.2 → 6.1.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 +153 -19
- package/apis/cds.d.ts +11 -7
- package/apis/log.d.ts +48 -0
- package/apis/ql.d.ts +72 -15
- package/bin/build/buildTaskHandler.js +5 -2
- package/bin/build/constants.js +4 -1
- package/bin/build/provider/buildTaskHandlerEdmx.js +11 -39
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +13 -32
- package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
- package/bin/build/provider/buildTaskProviderInternal.js +22 -14
- package/bin/build/provider/hana/index.js +8 -7
- package/bin/build/provider/java/index.js +18 -8
- package/bin/build/provider/mtx/index.js +7 -4
- package/bin/build/provider/mtx/resourcesTarBuilder.js +64 -35
- package/bin/build/provider/mtx-extension/index.js +57 -0
- package/bin/build/provider/mtx-sidecar/index.js +46 -18
- package/bin/build/provider/nodejs/index.js +34 -13
- package/bin/build/util.js +6 -4
- package/bin/deploy/to-hana/cfUtil.js +7 -2
- package/bin/deploy/to-hana/hana.js +6 -3
- package/bin/serve.js +8 -13
- package/lib/compile/{index.js → cds-compile.js} +0 -0
- package/lib/compile/extend.js +15 -5
- package/lib/compile/minify.js +1 -15
- package/lib/compile/parse.js +1 -1
- package/lib/compile/resolve.js +2 -2
- package/lib/compile/to/srvinfo.js +6 -4
- package/lib/{deploy.js → dbs/cds-deploy.js} +8 -8
- package/lib/env/{index.js → cds-env.js} +1 -17
- package/lib/env/{requires.js → cds-requires.js} +24 -3
- package/lib/env/defaults.js +7 -1
- package/lib/env/schemas/cds-package.json +11 -0
- package/lib/env/schemas/cds-rc.json +605 -0
- package/lib/index.js +20 -17
- package/lib/log/{errors.js → cds-error.js} +1 -1
- package/lib/log/{index.js → cds-log.js} +0 -0
- package/lib/ql/SELECT.js +1 -1
- package/lib/ql/{index.js → cds-ql.js} +0 -0
- package/lib/req/cds-context.js +1 -1
- package/lib/req/context.js +35 -7
- package/lib/req/locale.js +5 -1
- package/lib/{serve → srv}/adapters.js +23 -19
- package/lib/{connect → srv}/bindings.js +0 -0
- package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
- package/lib/{serve/index.js → srv/cds-serve.js} +1 -1
- package/lib/{serve → srv}/factory.js +2 -3
- package/lib/{serve/Service-api.js → srv/srv-api.js} +14 -6
- package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +3 -2
- package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
- package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
- package/lib/srv/srv-models.js +206 -0
- package/lib/{serve/Transaction.js → srv/srv-tx.js} +6 -1
- package/lib/utils/{tests.js → cds-test.js} +2 -2
- package/lib/utils/cds-utils.js +146 -0
- package/lib/utils/index.js +2 -136
- package/lib/utils/jest.js +43 -0
- package/lib/utils/resources/index.js +14 -24
- package/lib/utils/resources/tar.js +18 -41
- package/libx/_runtime/auth/index.js +13 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +9 -20
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +19 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +8 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +8 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +2 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +8 -5
- package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
- package/libx/_runtime/cds-services/util/errors.js +1 -29
- package/libx/_runtime/common/constants/events.js +1 -3
- package/libx/_runtime/common/i18n/messages.properties +2 -1
- package/libx/_runtime/common/perf/index.js +10 -15
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
- package/libx/_runtime/common/utils/template.js +1 -1
- package/libx/_runtime/db/Service.js +2 -14
- package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
- package/libx/_runtime/db/generic/input.js +4 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
- package/libx/_runtime/extensibility/activate.js +47 -47
- package/libx/_runtime/extensibility/add.js +19 -13
- package/libx/_runtime/extensibility/addExtension.js +17 -13
- package/libx/_runtime/extensibility/defaults.js +25 -30
- package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
- package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
- package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
- package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
- package/libx/_runtime/extensibility/linter.js +32 -0
- package/libx/_runtime/extensibility/push.js +78 -21
- package/libx/_runtime/extensibility/service.js +29 -12
- package/libx/_runtime/extensibility/token.js +56 -0
- package/libx/_runtime/extensibility/validation.js +6 -9
- package/libx/_runtime/fiori/generic/activate.js +0 -4
- package/libx/_runtime/fiori/generic/edit.js +1 -9
- package/libx/_runtime/fiori/generic/new.js +3 -28
- package/libx/_runtime/fiori/generic/patch.js +6 -7
- package/libx/_runtime/fiori/generic/prepare.js +11 -18
- package/libx/_runtime/fiori/generic/read.js +11 -1
- package/libx/_runtime/fiori/utils/handler.js +0 -17
- package/libx/_runtime/hana/Service.js +0 -1
- package/libx/_runtime/hana/conversion.js +12 -1
- package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
- package/libx/_runtime/hana/pool.js +6 -10
- package/libx/_runtime/hana/search2Contains.js +0 -5
- package/libx/_runtime/hana/search2cqn4sql.js +1 -0
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +18 -19
- package/libx/_runtime/messaging/file-based.js +1 -0
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/messaging/service.js +11 -6
- package/libx/_runtime/remote/utils/client.js +6 -2
- package/libx/_runtime/remote/utils/data.js +5 -0
- package/libx/_runtime/sqlite/Service.js +0 -1
- package/libx/odata/afterburner.js +79 -2
- package/libx/odata/cqn2odata.js +9 -7
- package/libx/odata/grammar.pegjs +161 -77
- package/libx/odata/index.js +9 -3
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +39 -5
- package/libx/rest/RestAdapter.js +1 -2
- package/libx/rest/middleware/delete.js +4 -5
- package/libx/rest/middleware/parse.js +3 -2
- package/package.json +3 -3
- package/server.js +1 -1
- package/srv/extensibility-service.cds +6 -3
- package/srv/model-provider.cds +3 -1
- package/srv/model-provider.js +84 -104
- package/srv/mtx.js +7 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +0 -240
|
@@ -3,10 +3,10 @@ const path = require('path')
|
|
|
3
3
|
const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
4
4
|
const { BuildError } = require('../../util')
|
|
5
5
|
const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY, ODATA_VERSION, ODATA_VERSION_V2, FOLDER_GEN, BUILD_NODEJS_EDMX_GENERAION, EDMX_GENERATION,
|
|
6
|
-
SKIP_PACKAGE_JSON_GENERATION, CONTENT_EDMX, CONTENT_PACKAGE_JSON, CONTENT_PACKAGELOCK_JSON, CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON } = require('../../constants')
|
|
7
|
-
const { WARNING } =
|
|
6
|
+
SKIP_PACKAGE_JSON_GENERATION, CONTENT_EDMX, CONTENT_PACKAGE_JSON, CONTENT_PACKAGELOCK_JSON, CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, SEMVER_REGEX } = require('../../constants')
|
|
7
|
+
const { WARNING, ERROR } = BuildTaskHandlerEdmx
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class NodejsModuleBuilder extends BuildTaskHandlerEdmx {
|
|
10
10
|
init() {
|
|
11
11
|
super.init()
|
|
12
12
|
// set unified option values in order to ease access later on
|
|
@@ -28,6 +28,12 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
28
28
|
this.destSrv = this.isStagingBuild() ? path.resolve(this.task.dest, this.env.folders.srv) : path.join(this.task.dest, FOLDER_GEN)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
options() {
|
|
32
|
+
const options = super.options(), {cds} = this
|
|
33
|
+
if (cds.requires.extensibility || cds.requires.toggles) options.flavor = 'xtended'
|
|
34
|
+
return options
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
async build() {
|
|
32
38
|
const destSrv = this.isStagingBuild() ? this.destSrv : path.resolve(this.destSrv, this.env.folders.srv)
|
|
33
39
|
const destRoot = this.isStagingBuild() ? this.task.dest : this.destSrv
|
|
@@ -48,7 +54,8 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
48
54
|
await this.collectAllLanguageBundles(dictionary, sources, destSrv, destRoot)
|
|
49
55
|
|
|
50
56
|
if (this.hasBuildOption(CONTENT_EDMX, true)) {
|
|
51
|
-
await this.
|
|
57
|
+
const m = await this.cds.load(sources.base, super.options()) // REVISIT: Quick hack to get inferred model as expected by cds.compile.to.edmx()
|
|
58
|
+
await this.compileToEdmx(m, this.destSrv)
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
if (!this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
|
|
@@ -77,11 +84,11 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/**
|
|
80
|
-
* Copy files from the given <em>src</em>' folder (e.g. 'project/srv') to either <em>destRoot</em> (e.g. 'project/gen/srv')
|
|
87
|
+
* Copy files from the given <em>src</em>' folder (e.g. 'project/srv') to either <em>destRoot</em> (e.g. 'project/gen/srv')
|
|
81
88
|
* or <em>destSrv</em> (e.g. 'project/gen/srv/srv') folders according to the file semantics.
|
|
82
|
-
* Files with project semantics like 'package.json' or '.npmrc' file are copied to <em>destRoot</em> while others like '.js' service handlers
|
|
89
|
+
* Files with project semantics like 'package.json' or '.npmrc' file are copied to <em>destRoot</em> while others like '.js' service handlers
|
|
83
90
|
* are copied to <em>destSrv</em>.
|
|
84
|
-
* @param {*} src
|
|
91
|
+
* @param {*} src
|
|
85
92
|
* @param {*} destRoot - folder name representing the app root folder (e.g. gen/srv)
|
|
86
93
|
* @param {*} destSrv - folder name representing the app sub-folder (e.g. gen/srv/srv)
|
|
87
94
|
* @returns the list of files that have been copied
|
|
@@ -98,7 +105,8 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
98
105
|
// TODO shall not copy language bundles - return !/(\/|\\)(node_modules|_i18n)(\/|\\)?$/.test(entry)
|
|
99
106
|
return !/(\/|\\)node_modules(\/|\\)?$/.test(entry)
|
|
100
107
|
}
|
|
101
|
-
|
|
108
|
+
// make sure the file exists on srv root level - see https://github.tools.sap/cap/issues/issues/12077
|
|
109
|
+
if (srvRootBlockList.test(entry) && path.dirname(entry) === src) {
|
|
102
110
|
srvRootFileNames.push(path.basename(entry))
|
|
103
111
|
return false
|
|
104
112
|
}
|
|
@@ -125,8 +133,8 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
125
133
|
/**
|
|
126
134
|
* Copy dedicated files (files with project semantics like package.json, .npmrc, .cdsrc, etc.)
|
|
127
135
|
* from the given <em>src</em> folder (e.g. 'project') into the given <em>dest</em> folder (e.g. 'project/gen/srv')
|
|
128
|
-
* @param {*} src
|
|
129
|
-
* @param {*} dest
|
|
136
|
+
* @param {*} src
|
|
137
|
+
* @param {*} dest
|
|
130
138
|
* @param {*} filter - copy file if filter function returns true
|
|
131
139
|
*/
|
|
132
140
|
async _copyProjectRootContent(src, dest, filter) {
|
|
@@ -163,12 +171,18 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
163
171
|
async _modifyPackageJson(file) {
|
|
164
172
|
function _addEnginesField(content) {
|
|
165
173
|
if (!content.engines || !content.engines.node) {
|
|
174
|
+
// use minimum node version of @sap/cds
|
|
166
175
|
const { engines } = require('../../../../package.json')
|
|
167
176
|
if (engines && engines.node) {
|
|
168
177
|
this.logger.log(`${this.task.for}: adding node engines version to package.json ${engines.node}`)
|
|
169
178
|
content.engines = content.engines || {}
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
const nodeVersion = NodejsModuleBuilder._convertToClosedVersionRange(engines.node)
|
|
180
|
+
if (nodeVersion) {
|
|
181
|
+
content.engines.node = nodeVersion
|
|
182
|
+
return true
|
|
183
|
+
} else {
|
|
184
|
+
this.pushMessage(`Invalid node version defined in engines definition for @sap/cds ${engines.node} - skip node engines definition`, ERROR)
|
|
185
|
+
}
|
|
172
186
|
}
|
|
173
187
|
}
|
|
174
188
|
return false
|
|
@@ -184,6 +198,13 @@ class NodeCfModuleBuilder extends BuildTaskHandlerEdmx {
|
|
|
184
198
|
await this.write(content).to(file)
|
|
185
199
|
}
|
|
186
200
|
}
|
|
201
|
+
|
|
202
|
+
static _convertToClosedVersionRange(rtVersion) {
|
|
203
|
+
rtVersion = rtVersion.trim()
|
|
204
|
+
if (rtVersion.match(SEMVER_REGEX)) {
|
|
205
|
+
return rtVersion.replace(SEMVER_REGEX, '^$2$3$4')
|
|
206
|
+
}
|
|
207
|
+
}
|
|
187
208
|
}
|
|
188
209
|
|
|
189
|
-
module.exports =
|
|
210
|
+
module.exports = NodejsModuleBuilder
|
package/bin/build/util.js
CHANGED
|
@@ -124,11 +124,13 @@ function _redacted(cred) {
|
|
|
124
124
|
* @returns
|
|
125
125
|
*/
|
|
126
126
|
function isStreamlinedMtx(cds) {
|
|
127
|
-
if (process.env.OLD_MTX)
|
|
128
|
-
|
|
127
|
+
if (hasOptionValue(process.env.OLD_MTX, true)) {
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
return (cds.env.get("requires.toggles")
|
|
129
131
|
|| cds.env.requires['cds.xt.ModelProviderService']
|
|
130
|
-
|| cds.env.get("requires.multitenancy
|
|
131
|
-
|
|
132
|
+
|| (typeof cds.env.get("requires.multitenancy") === "object")
|
|
133
|
+
) && !(() => { try { return cds.mtx } catch (e) { /**/ } })()
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
class BuildMessage extends Error {
|
|
@@ -77,7 +77,12 @@ class CfUtil {
|
|
|
77
77
|
async _cfRequest(urlPath, queryObj, bodyObj) {
|
|
78
78
|
if (queryObj) {
|
|
79
79
|
const entries = Object.entries(queryObj);
|
|
80
|
-
const queryStr = entries.map((
|
|
80
|
+
const queryStr = entries.map(([key, value]) => {
|
|
81
|
+
// commas cause problems in cf curl when not double encoded
|
|
82
|
+
value = value.replace(/,/g, encodeURIComponent(','));
|
|
83
|
+
return `${key}=${encodeURIComponent(value)}`;
|
|
84
|
+
}).join('&');
|
|
85
|
+
|
|
81
86
|
urlPath = urlPath + `?${queryStr}`;
|
|
82
87
|
}
|
|
83
88
|
|
|
@@ -125,7 +130,7 @@ class CfUtil {
|
|
|
125
130
|
async getCfTargetFromCli() {
|
|
126
131
|
const result = await this._cfRun('target');
|
|
127
132
|
return {
|
|
128
|
-
apiEndpoint: this._extract(result, /api endpoint\s*:\s*(
|
|
133
|
+
apiEndpoint: this._extract(result, /api endpoint\s*:\s*([^\s]+)/i, `CF API endpoint is missing. Use 'cf login' to login.`),
|
|
129
134
|
user: this._extract(result, /user\s*:\s*(.+)/i, `CF user is missing. Use 'cf login' to login.`),
|
|
130
135
|
org: this._extract(result, /org\s*:\s*(.+)/i, `CF org is missing. Use 'cf target -o <ORG> to specify.`),
|
|
131
136
|
space: this._extract(result, /space\s*:\s*(.+)/i, `CF space is missing. Use 'cf target -s <SPACE>' to specify.`),
|
|
@@ -35,7 +35,12 @@ class HanaDeployer {
|
|
|
35
35
|
this.logger = logger;
|
|
36
36
|
|
|
37
37
|
this.logger.log(`${bold('Starting deploy to SAP HANA ...')}`);
|
|
38
|
-
if (
|
|
38
|
+
if (vcapFile) {
|
|
39
|
+
this.logger.log();
|
|
40
|
+
this.logger.log(`Using VCAP_SERVICES from file ${vcapFile} (beta feature).`);
|
|
41
|
+
bindCallback = null // credentials are given - no cds bind then
|
|
42
|
+
}
|
|
43
|
+
else if (bindCallback) {
|
|
39
44
|
this.logger.log('Using cds bind');
|
|
40
45
|
}
|
|
41
46
|
this.logger.log();
|
|
@@ -46,8 +51,6 @@ class HanaDeployer {
|
|
|
46
51
|
|
|
47
52
|
let vcapServices;
|
|
48
53
|
if (vcapFile) {
|
|
49
|
-
this.logger.log();
|
|
50
|
-
this.logger.log(`Using vcap file ${vcapFile} (beta feature).`);
|
|
51
54
|
vcapServices = await this._loadVCAPServices(vcapFile);
|
|
52
55
|
}
|
|
53
56
|
|
package/bin/serve.js
CHANGED
|
@@ -181,7 +181,7 @@ async function serve (all=[], o={}) { // NOSONAR
|
|
|
181
181
|
log ('loading plugin:', {impl})
|
|
182
182
|
// TODO support ESM plugins. But see cap/cds/pull/1838#issuecomment-1177200 !
|
|
183
183
|
const plugin = require(impl)
|
|
184
|
-
if (plugin.activate) plugin.activate(each)
|
|
184
|
+
if (plugin.activate) await plugin.activate(each)
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
// bootstrap server from project-local server.js or from @sap/cds/server.js
|
|
@@ -225,7 +225,7 @@ async function _local_server_js() {
|
|
|
225
225
|
let server_js = process.env.CDS_TYPESCRIPT && _local('server.ts') || _local('server.js')
|
|
226
226
|
if (server_js) {
|
|
227
227
|
log ('Loading server from', { file: local(server_js) })
|
|
228
|
-
let fn = await _import(server_js)
|
|
228
|
+
let fn = await cds.utils._import(server_js)
|
|
229
229
|
if (fn && fn.default) fn = fn.default // default ESM export
|
|
230
230
|
return typeof fn === 'function' ? fn : cds.server
|
|
231
231
|
}
|
|
@@ -258,16 +258,19 @@ function _prepare_logging () { // NOSONAR
|
|
|
258
258
|
cds.on ('serving', (srv) => {
|
|
259
259
|
const details = {}
|
|
260
260
|
if (srv.path) details.path = srv.path
|
|
261
|
-
if (srv._source
|
|
261
|
+
if (srv._source && !srv._source.startsWith('@sap'))
|
|
262
|
+
details.impl = local(srv._source)
|
|
262
263
|
log (`${srv.mocked ? 'mocking' : 'serving'} ${srv.name}`, details)
|
|
263
264
|
})
|
|
264
265
|
|
|
266
|
+
cds.on ('served', ()=> console.log())
|
|
267
|
+
|
|
265
268
|
// print info when we are finally on air
|
|
266
269
|
cds.once ('listening', ({url})=>{
|
|
267
|
-
console.log
|
|
270
|
+
console.log()
|
|
268
271
|
log ('server listening on',{url})
|
|
269
272
|
_timer && console.timeEnd (_timer)
|
|
270
|
-
if (process.stdin.isTTY) log (`[ terminate with ^C ]`)
|
|
273
|
+
if (process.stdin.isTTY) log (`[ terminate with ^C ]\n`)
|
|
271
274
|
})
|
|
272
275
|
}
|
|
273
276
|
|
|
@@ -320,14 +323,6 @@ function _with_mocks (o) {
|
|
|
320
323
|
}
|
|
321
324
|
}
|
|
322
325
|
|
|
323
|
-
const { pathToFileURL } = require('url') // on Windows, must use a file: URL for ESM import
|
|
324
|
-
function _import(filePath) {
|
|
325
|
-
return typeof jest !== 'undefined'
|
|
326
|
-
? require(filePath)
|
|
327
|
-
: import (pathToFileURL(filePath).href)
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
|
|
331
326
|
const SECRETS = /(password)|(certificate)|(ca)|(secret)|(key)/i // 'certificate' and 'ca' on HANA
|
|
332
327
|
/** mascades password-like strings, also reducing clutter in output */
|
|
333
328
|
function _redacted(cred) {
|
|
File without changes
|
package/lib/compile/extend.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
const compile = require ('./cds-compile')
|
|
1
2
|
const { extend } = require ('../lazy')
|
|
2
|
-
const compile = require ('./index')
|
|
3
3
|
|
|
4
|
-
module.exports = o => o.definitions ? { with(...
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
module.exports = o => o.definitions ? { with(...csns) {
|
|
5
|
+
|
|
6
|
+
const csn=o, merged = { definitions: {}, extensions: [] }
|
|
7
|
+
for (const { definitions, extensions } of csns) {
|
|
8
|
+
if (definitions) Object.assign(merged.definitions, definitions)
|
|
9
|
+
if (extensions) merged.extensions.push(...extensions)
|
|
10
|
+
}
|
|
11
|
+
const extended = compile({
|
|
12
|
+
'base.csn': compile.to.json(csn),
|
|
13
|
+
'ext.csn': compile.to.json(merged)
|
|
14
|
+
})
|
|
15
|
+
extended.$sources = csn.$sources // required to load resources like i18n later on
|
|
16
|
+
return extended
|
|
17
|
+
|
|
8
18
|
}} : extend(o)
|
package/lib/compile/minify.js
CHANGED
|
@@ -35,7 +35,7 @@ module.exports = function cds_minify (csn, _roots) { // IMPORTANT: don't add cds
|
|
|
35
35
|
}
|
|
36
36
|
function _visit (d) {
|
|
37
37
|
if (typeof d === 'string') {
|
|
38
|
-
if (isInReservedNamespace(d)) return
|
|
38
|
+
if (cds.compiler.model.isInReservedNamespace(d)) return
|
|
39
39
|
else d = all[d]
|
|
40
40
|
} else if (d.ref) return d.ref.reduce((p,n) => {
|
|
41
41
|
let d = (p.elements || csn.definitions[p.target].elements)[n.id || n] // > n.id -> view with parameters
|
|
@@ -61,18 +61,4 @@ module.exports = function cds_minify (csn, _roots) { // IMPORTANT: don't add cds
|
|
|
61
61
|
return minified
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/**
|
|
65
|
-
* TODO - keep in sync with @sap/cds-compiler. Use their public API once it is available!
|
|
66
|
-
* Checks whether the given absolute path is inside a reserved namespace.
|
|
67
|
-
*
|
|
68
|
-
* @param {string} absolute
|
|
69
|
-
* @returns {boolean}
|
|
70
|
-
*/
|
|
71
|
-
function isInReservedNamespace(absolute) {
|
|
72
|
-
return absolute.startsWith( 'cds.') &&
|
|
73
|
-
!absolute.match(/^cds\.foundation(\.|$)/) &&
|
|
74
|
-
!absolute.match(/^cds\.outbox(\.|$)/) && // Requested by Node runtime
|
|
75
|
-
!absolute.match(/^cds\.xt(\.|$)/); // Requested by Mtx
|
|
76
|
-
}
|
|
77
|
-
|
|
78
64
|
const _minified = Symbol('minified')
|
package/lib/compile/parse.js
CHANGED
|
@@ -56,7 +56,7 @@ const tagged = (parse, strings, ...values) => {
|
|
|
56
56
|
all[2*i] = s
|
|
57
57
|
all[2*i+1] = v instanceof cds.entity ? v.name : ':'+i
|
|
58
58
|
if (typeof v === 'string' && s.endsWith(' like ') && !v.includes('%')) values[i] = `%${v}%`
|
|
59
|
-
if (Array.isArray(v) && s.endsWith(' in ')) values[i] = {list: v.map(cxn4)}
|
|
59
|
+
if (Array.isArray(v) && s.toLowerCase().endsWith(' in ')) values[i] = {list: v.map(cxn4)}
|
|
60
60
|
}
|
|
61
61
|
all[2*i] = strings[i]
|
|
62
62
|
return merge (parse(all.join('')), values)
|
package/lib/compile/resolve.js
CHANGED
|
@@ -20,7 +20,7 @@ module.exports = exports = function cds_resolve (model, o={}) { // NOSONAR
|
|
|
20
20
|
if (model === '*') return _resolve_all(o,this)
|
|
21
21
|
if (Array.isArray(model)) {
|
|
22
22
|
const resolved = [... new Set(model)] .reduce ((prev,next) => prev.concat (this.resolve(next,o)||[]), [])
|
|
23
|
-
return o.dry || o === false ? resolved : _resolved (resolved)
|
|
23
|
+
return o.dry || o === false ? [...new Set(resolved.flat())] : _resolved (resolved)
|
|
24
24
|
}
|
|
25
25
|
if (model.endsWith('/*')) return _resolve_subdirs_in(model,o,this)
|
|
26
26
|
|
|
@@ -69,7 +69,7 @@ const _required = (cds,env=cds.env) => Object.values(env.requires) .map (r => r.
|
|
|
69
69
|
const _resolve = require('module')._resolveFilename
|
|
70
70
|
|
|
71
71
|
function _resolve_all (o,cds) {
|
|
72
|
-
const {roots} = o.env || cds.env; if (o.dry || o === false) return [ ...roots, ..._required(cds) ]
|
|
72
|
+
const {roots} = o.env || cds.env; if (o.dry || o === false) return [ ...roots, ...new Set(_required(cds).flat()) ]
|
|
73
73
|
const cache = o.cache || exports.cache
|
|
74
74
|
const cached = cache['*']; if (cached) return cached
|
|
75
75
|
cache['*'] = [] // important to avoid endless recursion on '*'
|
|
@@ -69,21 +69,23 @@ module.exports = (model, options={}) => {
|
|
|
69
69
|
|
|
70
70
|
function _javaPrefix() {
|
|
71
71
|
let is_java
|
|
72
|
+
const javaPrefixDefault = 'odata/v4/'
|
|
72
73
|
for (let s of model.$sources) {
|
|
73
74
|
const file = isfile (join (s,'../src/main/resources/application.yaml'))
|
|
74
75
|
if (file) {
|
|
75
76
|
const yaml = cds.load.yaml(file)
|
|
76
|
-
for (let
|
|
77
|
+
for (let yamlDoc of Array.isArray(yaml) ? yaml : [yaml]) {
|
|
78
|
+
const cds = yamlDoc?.cds;
|
|
77
79
|
if (!cds) continue
|
|
78
80
|
return cds['odataV4.endpoint.path'] || cds['odataV2.endpoint.path'] // https://cap.cloud.sap/docs/java/application-services#configure-base-path
|
|
79
81
|
|| cds['odata-v4.endpoint.path'] || cds['odata-v2.endpoint.path'] // older/intermediate config, keep for backward compatibility
|
|
80
|
-
|
|
82
|
+
|| javaPrefixDefault
|
|
81
83
|
}
|
|
82
|
-
return
|
|
84
|
+
return javaPrefixDefault
|
|
83
85
|
}
|
|
84
86
|
else if (isfile (join(s,'../pom.xml'))) is_java = true
|
|
85
87
|
}
|
|
86
|
-
return is_java &&
|
|
88
|
+
return is_java && javaPrefixDefault
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const cds = require('
|
|
1
|
+
const cds = require('../index'), { local, inspect } = cds.utils
|
|
2
2
|
const DEBUG = cds.debug('deploy')
|
|
3
3
|
/* eslint-disable no-console */
|
|
4
4
|
|
|
@@ -121,11 +121,11 @@ exports.create = async function (db, csn=db.model, o) {
|
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
exports.init = (db, csn=db.model, log=()=>{}) => db.tx (async tx => {
|
|
124
|
-
const resources = await exports.resources(csn
|
|
124
|
+
const resources = await exports.resources(csn, {testdata: cds.env.features.test_data})
|
|
125
|
+
const inits=[]
|
|
125
126
|
for (let [file,e] of Object.entries(resources)) {
|
|
126
127
|
if (e === '*') { // init.js/ts
|
|
127
|
-
|
|
128
|
-
let x = typeof jest !== 'undefined' ? require(file) : await import(pathToFileURL(file).href); if (!x) continue
|
|
128
|
+
let x = await cds.utils._import(file); if (!x) continue
|
|
129
129
|
if (x.default) x = x.default // default ESM export
|
|
130
130
|
inits.push (!x.then && typeof x === 'function' ? x(db,csn) : x)
|
|
131
131
|
log (file)
|
|
@@ -144,9 +144,9 @@ exports.init = (db, csn=db.model, log=()=>{}) => db.tx (async tx => {
|
|
|
144
144
|
})
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
exports.resources = async function (csn) {
|
|
147
|
+
exports.resources = async function (csn, opts) {
|
|
148
148
|
if (!csn || !csn.definitions) csn = await cds.load (csn||'*') .then (cds.minify)
|
|
149
|
-
const folders = await exports.resources.folders(csn)
|
|
149
|
+
const folders = await exports.resources.folders(csn, opts)
|
|
150
150
|
const found={}, ts = process.env.CDS_TYPESCRIPT
|
|
151
151
|
for (let folder of folders) {
|
|
152
152
|
// fetching init.js files
|
|
@@ -174,11 +174,11 @@ exports.resources = async function (csn) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
|
|
177
|
-
exports.resources.folders = async function (csn) {
|
|
177
|
+
exports.resources.folders = async function (csn, o={}) {
|
|
178
178
|
if (!csn || !csn.definitions) csn = await cds.load (csn||'*') .then (cds.minify)
|
|
179
179
|
const folders = new Set (csn.$sources.map (path.dirname) .filter (f => f !== cds.home))
|
|
180
180
|
if (cds.env.folders.db) folders.add (path.resolve(cds.root, cds.env.folders.db))
|
|
181
|
-
if (
|
|
181
|
+
if (o.testdata) folders.add (path.resolve(cds.root,'test/'))
|
|
182
182
|
return folders
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { isfile, fs, path } = require('../utils')
|
|
1
|
+
const { isfile, fs, path } = require('../utils/cds-utils')
|
|
2
2
|
const DEFAULTS = require('./defaults'), defaults = require.resolve ('./defaults')
|
|
3
3
|
const compat = require('./compat')
|
|
4
4
|
const presets = require('./presets')
|
|
@@ -130,22 +130,6 @@ class Config {
|
|
|
130
130
|
return option.split('.').reduce ((p,n)=> p && p[n], this)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
/**
|
|
134
|
-
* This is `this.requires` plus additional entries for all cds.required.<name>.service
|
|
135
|
-
* @returns {import('./requires')}
|
|
136
|
-
*/
|
|
137
|
-
get required_services_or_defs() {
|
|
138
|
-
const dict = Object.create (this.requires)
|
|
139
|
-
for (let [name,e] of Object.entries (this.requires)) if (e.service) {
|
|
140
|
-
if (e.service in dict && !e.override && e.service !== name) {
|
|
141
|
-
console.error (`Datasource name '${e.service}' conflicts with 'service' definition referred to in 'cds.requires.${name}':`, e)
|
|
142
|
-
throw new Error (`Datasource name '${e.service}' conflicts with service definition`)
|
|
143
|
-
}
|
|
144
|
-
else dict[e.service] = { ...e, name }
|
|
145
|
-
}
|
|
146
|
-
return super.required_services_or_defs = dict
|
|
147
|
-
}
|
|
148
|
-
|
|
149
133
|
get profiles() {
|
|
150
134
|
return super.profiles = Array.from (this._profiles)
|
|
151
135
|
}
|
|
@@ -11,6 +11,23 @@ exports = module.exports = {
|
|
|
11
11
|
'[production]': { kind: 'jwt-auth' }
|
|
12
12
|
},
|
|
13
13
|
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This is the implementation for `cds.requires` which is `cds.env.requires`
|
|
17
|
+
* plus additional entries for all cds.required.<name>.service
|
|
18
|
+
* @returns {import('./cds-requires')}
|
|
19
|
+
*/
|
|
20
|
+
_resolved() {
|
|
21
|
+
const dict = Object.create (this)
|
|
22
|
+
for (let [name,e] of Object.entries (this)) if (e.service) {
|
|
23
|
+
if (e.service in dict && !e.override && e.service !== name) {
|
|
24
|
+
console.error (`Datasource name '${e.service}' conflicts with 'service' definition referred to in 'cds.requires.${name}':`, e) // eslint-disable-line no-console
|
|
25
|
+
throw new Error (`Datasource name '${e.service}' conflicts with service definition`)
|
|
26
|
+
}
|
|
27
|
+
else dict[e.service] = { ...e, name }
|
|
28
|
+
}
|
|
29
|
+
return dict
|
|
30
|
+
}
|
|
14
31
|
}
|
|
15
32
|
|
|
16
33
|
|
|
@@ -85,6 +102,10 @@ const _databases = {
|
|
|
85
102
|
'[development]': { kind: 'sqlite', credentials: { url: ':memory:' } },
|
|
86
103
|
'[production]': { kind: 'hana' },
|
|
87
104
|
},
|
|
105
|
+
"sql-mt": {
|
|
106
|
+
'[development]': { kind: 'sqlite' },
|
|
107
|
+
'[production]': { kind: 'hana-mt' },
|
|
108
|
+
},
|
|
88
109
|
"sqlite": _compat_to_use({
|
|
89
110
|
credentials: { url: 'sqlite.db' },
|
|
90
111
|
impl: `${_runtime}/sqlite/Service.js`,
|
|
@@ -208,11 +229,11 @@ const _mtx_services = {
|
|
|
208
229
|
model: "@sap/cds/srv/extensions",
|
|
209
230
|
},
|
|
210
231
|
"extensibility": {
|
|
211
|
-
model: [ "@sap/cds/srv/mtx", "@sap/cds/srv/extensions" ]
|
|
232
|
+
model: [ "@sap/cds/srv/mtx", "@sap/cds/srv/extensions" ],
|
|
233
|
+
tenantCheckInterval: 10000
|
|
212
234
|
},
|
|
213
235
|
"cds.xt.ExtensibilityService": {
|
|
214
|
-
model: "@sap/cds/srv/extensibility-service"
|
|
215
|
-
tenantCheckInterval: 10000
|
|
236
|
+
model: "@sap/cds/srv/extensibility-service"
|
|
216
237
|
},
|
|
217
238
|
"uiflex": "extensibility", // REVISIT: temporary for compatibility with cds-mtxs tests -> eliminate "uiflex" later
|
|
218
239
|
|
package/lib/env/defaults.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
const path = require('path')
|
|
1
2
|
const [,major,minor] = /v(\d+)\.(\d+)/.exec(process.version)
|
|
2
3
|
const production = process.env.NODE_ENV === 'production'
|
|
3
4
|
|
|
4
5
|
module.exports = {
|
|
5
6
|
|
|
6
|
-
requires: require('./requires'),
|
|
7
|
+
requires: require('./cds-requires'),
|
|
8
|
+
|
|
9
|
+
schemas: {
|
|
10
|
+
'cds-rc.json': path.join(__dirname, 'schemas/cds-rc.json'),
|
|
11
|
+
'cds-package.json': path.join(__dirname, 'schemas/cds-package.json'),
|
|
12
|
+
},
|
|
7
13
|
|
|
8
14
|
features: {
|
|
9
15
|
folders: 'fts/*', // where to find feature toggles -> switch on by default when released
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "JSON schema for CDS configuration in package.json",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"description": "This is a JSON schema representation of the CDS project configuration inside a project root level package.json",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"cds": {
|
|
8
|
+
"$ref": "cdsJsonSchema://schemas/cds-rc.json"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|