@sap/cds 5.8.4 → 5.9.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 +174 -77
- package/app/fiori/preview.js +16 -11
- package/app/index.js +1 -1
- package/bin/build/buildTaskFactory.js +3 -3
- package/bin/build/buildTaskProviderFactory.js +1 -1
- package/bin/build/constants.js +1 -1
- package/bin/build/provider/buildTaskHandlerEdmx.js +12 -7
- package/bin/build/provider/buildTaskHandlerInternal.js +1 -1
- package/bin/build/provider/buildTaskProviderInternal.js +8 -2
- package/bin/build/provider/hana/2migration.js +27 -24
- package/bin/build/provider/hana/index.js +17 -18
- package/bin/build/provider/hana/migrationtable.js +9 -10
- package/bin/build/provider/java-cf/index.js +4 -5
- package/bin/build/provider/node-cf/index.js +99 -6
- package/bin/cds.js +17 -18
- package/bin/deploy/to-hana/cfUtil.js +16 -19
- package/bin/deploy/to-hana/hana.js +7 -24
- package/bin/deploy/to-hana/hdiDeployUtil.js +8 -4
- package/bin/mtx/in-cds.js +2 -2
- package/bin/serve.js +10 -3
- package/bin/utils/modules.js +7 -0
- package/bin/version.js +56 -3
- package/lib/compile/cdsc.js +26 -3
- package/lib/compile/etc/_localized.js +36 -25
- package/lib/compile/etc/csv.js +8 -8
- package/lib/compile/for/drafts.js +9 -0
- package/lib/compile/for/java.js +16 -0
- package/lib/compile/for/nodejs.js +12 -0
- package/lib/compile/for/odata.js +1 -1
- package/lib/compile/index.js +3 -0
- package/lib/compile/minify.js +16 -2
- package/lib/compile/parse.js +2 -2
- package/lib/compile/resolve.js +35 -18
- package/lib/compile/to/json.js +3 -1
- package/lib/compile/to/sql.js +2 -2
- package/lib/compile/to/srvinfo.js +4 -2
- package/lib/connect/index.js +1 -1
- package/lib/core/entities.js +15 -14
- package/lib/core/index.js +39 -36
- package/lib/core/reflect.js +4 -2
- package/lib/deploy.js +114 -127
- package/lib/env/defaults.js +1 -0
- package/lib/env/index.js +165 -165
- package/lib/env/presets.js +1 -0
- package/lib/env/requires.js +120 -49
- package/lib/index.js +1 -0
- package/lib/log/format/kibana.js +2 -2
- package/lib/ql/SELECT.js +10 -0
- package/lib/ql/parse.js +1 -0
- package/lib/req/cds-context.js +4 -1
- package/lib/req/context.js +50 -56
- package/lib/req/event.js +1 -6
- package/lib/req/locale.js +6 -5
- package/lib/req/request.js +2 -0
- package/lib/req/user.js +7 -5
- package/lib/serve/Service-api.js +10 -7
- package/lib/serve/Service-dispatch.js +9 -11
- package/lib/serve/Service-methods.js +30 -41
- package/lib/serve/Transaction.js +10 -7
- package/lib/serve/adapters.js +7 -5
- package/lib/serve/index.js +24 -12
- package/lib/utils/data.js +1 -1
- package/lib/utils/index.js +27 -30
- package/lib/utils/resources/index.js +101 -0
- package/lib/utils/resources/tar.js +71 -0
- package/lib/utils/resources/utils.js +11 -0
- package/libx/_runtime/audit/Service.js +36 -39
- package/libx/_runtime/audit/generic/personal/access.js +3 -4
- package/libx/_runtime/audit/generic/personal/modification.js +3 -4
- package/libx/_runtime/audit/utils/v2.js +1 -2
- package/libx/_runtime/auth/index.js +126 -84
- package/libx/_runtime/auth/strategies/JWT.js +12 -19
- package/libx/_runtime/auth/strategies/dummy.js +1 -5
- package/libx/_runtime/auth/strategies/dwc.js +11 -9
- package/libx/_runtime/auth/strategies/mock.js +0 -4
- package/libx/_runtime/auth/strategies/{utils/xssec.js → xssecUtils.js} +7 -4
- package/libx/_runtime/auth/strategies/xsuaa.js +12 -19
- package/libx/_runtime/auth/utils.js +22 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +104 -98
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/language.js +2 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -29
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +2 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +3 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +4 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +24 -21
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +8 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +2 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DispatcherCommand.js +2 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -12
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +33 -9
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +50 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +10 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +9 -11
- package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +6 -3
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +4 -2
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +2 -3
- package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +6 -4
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +1 -0
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +8 -5
- package/libx/_runtime/cds-services/services/Service.js +40 -0
- package/libx/_runtime/cds-services/services/utils/columns.js +4 -3
- package/libx/_runtime/cds-services/services/utils/compareJson.js +4 -4
- package/libx/_runtime/cds-services/services/utils/differ.js +3 -3
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +4 -4
- package/libx/_runtime/cds-services/services/utils/restrictions.js +78 -0
- package/libx/_runtime/cds-services/util/assert.js +20 -14
- package/libx/_runtime/cds.js +9 -1
- package/libx/_runtime/common/aspects/any.js +5 -0
- package/libx/_runtime/common/aspects/entity.js +25 -7
- package/libx/_runtime/common/aspects/utils.js +2 -2
- package/libx/_runtime/common/composition/data.js +6 -0
- package/libx/_runtime/common/composition/insert.js +3 -2
- package/libx/_runtime/common/composition/tree.js +4 -10
- package/libx/_runtime/common/composition/update.js +4 -4
- package/libx/_runtime/common/constants/draft.js +29 -26
- package/libx/_runtime/common/error/constants.js +2 -2
- package/libx/_runtime/common/error/frontend.js +7 -15
- package/libx/_runtime/common/generic/auth/capabilities.js +59 -0
- package/libx/_runtime/common/generic/auth/constants.js +20 -0
- package/libx/_runtime/common/generic/auth/expand.js +54 -0
- package/libx/_runtime/common/generic/auth/index.js +32 -0
- package/libx/_runtime/common/generic/auth/insertOnly.js +15 -0
- package/libx/_runtime/common/generic/auth/readOnly.js +26 -0
- package/libx/_runtime/common/generic/auth/requires.js +34 -0
- package/libx/_runtime/common/generic/auth/restrict.js +296 -0
- package/libx/_runtime/common/generic/auth/utils.js +213 -0
- package/libx/_runtime/common/generic/crud.js +8 -6
- package/libx/_runtime/common/generic/etag.js +1 -1
- package/libx/_runtime/common/generic/input.js +35 -35
- package/libx/_runtime/common/generic/sorting.js +2 -3
- package/libx/_runtime/common/generic/temporal.js +2 -2
- package/libx/_runtime/common/i18n/messages.properties +1 -1
- package/libx/_runtime/common/toggles/handler.js +21 -0
- package/libx/_runtime/common/utils/copy.js +10 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +100 -29
- package/libx/_runtime/common/utils/csn.js +63 -1
- package/libx/_runtime/common/utils/dollar.js +10 -1
- package/libx/_runtime/common/utils/draft.js +46 -7
- package/libx/_runtime/common/utils/entityFromCqn.js +13 -9
- package/libx/_runtime/common/utils/extensibilityUtils.js +18 -0
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +88 -104
- package/libx/_runtime/common/utils/generateOnCond.js +4 -1
- package/libx/_runtime/common/utils/quotingStyles.js +2 -0
- package/libx/_runtime/common/utils/resolveStructured.js +25 -9
- package/libx/_runtime/common/utils/resolveView.js +4 -1
- package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -16
- package/libx/_runtime/common/utils/structured.js +33 -37
- package/libx/_runtime/common/utils/template.js +17 -8
- package/libx/_runtime/common/utils/templateProcessor.js +28 -28
- package/libx/_runtime/db/data-conversion/post-processing.js +118 -417
- package/libx/_runtime/db/expand/expandCQNToJoin.js +45 -41
- package/libx/_runtime/db/expand/rawToExpanded.js +29 -8
- package/libx/_runtime/db/generic/index.js +1 -3
- package/libx/_runtime/db/generic/input.js +5 -10
- package/libx/_runtime/db/generic/rewrite.js +5 -2
- package/libx/_runtime/db/generic/structured.js +2 -2
- package/libx/_runtime/db/query/delete.js +2 -2
- package/libx/_runtime/db/query/insert.js +1 -1
- package/libx/_runtime/db/query/update.js +9 -14
- package/libx/_runtime/db/sql-builder/CreateBuilder.js +4 -3
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +14 -1
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -2
- package/libx/_runtime/db/sql-builder/dataTypes.js +3 -3
- package/libx/_runtime/db/utils/columns.js +3 -3
- package/libx/_runtime/db/utils/normalizeTimeData.js +2 -2
- package/libx/_runtime/db/utils/propagateForeignKeys.js +6 -2
- package/libx/_runtime/extensibility/mps/index.js +5 -0
- package/libx/_runtime/extensibility/mps/service.js +111 -0
- package/libx/_runtime/extensibility/mps/tar.js +42 -0
- package/libx/_runtime/extensibility/mps/utils.js +11 -0
- package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformREAD.js +0 -0
- package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformRESULT.js +17 -5
- package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformWRITE.js +1 -0
- package/libx/_runtime/extensibility/uiflex/index.js +54 -0
- package/libx/_runtime/extensibility/uiflex/service.js +276 -0
- package/libx/_runtime/{fiori → extensibility}/uiflex/utils.js +22 -7
- package/libx/_runtime/fiori/generic/activate.js +2 -2
- package/libx/_runtime/fiori/generic/before.js +4 -4
- package/libx/_runtime/fiori/generic/new.js +3 -3
- package/libx/_runtime/fiori/generic/patch.js +1 -1
- package/libx/_runtime/fiori/generic/read.js +58 -66
- package/libx/_runtime/fiori/generic/readOverDraft.js +71 -16
- package/libx/_runtime/fiori/utils/handler.js +6 -13
- package/libx/_runtime/fiori/utils/where.js +6 -5
- package/libx/_runtime/hana/Service.js +4 -10
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +1 -1
- package/libx/_runtime/hana/driver.js +2 -2
- package/libx/_runtime/hana/execute.js +27 -74
- package/libx/_runtime/hana/pool.js +1 -1
- package/libx/_runtime/hana/streaming.js +2 -1
- package/libx/_runtime/index.js +6 -6
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +5 -21
- package/libx/_runtime/messaging/Outbox.js +2 -2
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -14
- package/libx/_runtime/messaging/common-utils/connections.js +5 -7
- package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +30 -0
- package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +36 -30
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -12
- package/libx/_runtime/messaging/enterprise-messaging.js +8 -8
- package/libx/_runtime/messaging/file-based.js +5 -5
- package/libx/_runtime/messaging/message-queuing.js +14 -12
- package/libx/_runtime/messaging/outbox/utils.js +18 -19
- package/libx/_runtime/messaging/redis-messaging.js +91 -0
- package/libx/_runtime/messaging/service.js +8 -6
- package/libx/_runtime/remote/Service.js +44 -8
- package/libx/_runtime/remote/utils/client.js +20 -13
- package/libx/_runtime/remote/utils/data.js +11 -11
- package/libx/_runtime/sqlite/Service.js +6 -9
- package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +5 -2
- package/libx/_runtime/types/api.js +10 -2
- package/libx/common/utils/ucsn.js +109 -0
- package/libx/gql/resolvers/crud/update.js +5 -0
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +3 -1
- package/libx/gql/schema/typeDefMap.js +2 -2
- package/libx/odata/afterburner.js +110 -16
- package/libx/odata/grammar.pegjs +9 -1
- package/libx/odata/parseToCqn.js +39 -0
- package/libx/odata/parser.js +1 -1
- package/libx/rest/RestAdapter.js +9 -1
- package/libx/rest/middleware/input.js +54 -0
- package/libx/rest/middleware/operation.js +14 -1
- package/libx/rest/middleware/parse.js +11 -7
- package/package.json +1 -1
- package/server.js +34 -19
- package/srv/audit-log.cds +2 -2
- package/srv/flex.cds +8 -2
- package/srv/flex.js +1 -1
- package/srv/mps.cds +23 -0
- package/srv/mps.js +1 -0
- package/libx/_runtime/auth/strategies/utils/uaa.js +0 -21
- package/libx/_runtime/common/generic/auth.js +0 -874
- package/libx/_runtime/common/toggles/alpha.js +0 -43
- package/libx/_runtime/db/generic/arrayed.js +0 -33
- package/libx/_runtime/fiori/uiflex/index.js +0 -35
- package/libx/_runtime/fiori/uiflex/service.js +0 -150
- package/libx/rest/utils/data.js +0 -60
package/bin/cds.js
CHANGED
|
@@ -13,19 +13,22 @@ const cli = { //NOSONAR
|
|
|
13
13
|
}
|
|
14
14
|
require('util').inspect.defaultOptions = { colors: !!process.stderr.isTTY, depth:11 }
|
|
15
15
|
if (!argv.length) argv = process.argv.slice(3)
|
|
16
|
-
if (cmd in this.Shortcuts) cmd = process.argv[2] = this.Shortcuts[cmd]
|
|
17
16
|
if (process.env.NODE_ENV !== 'test') this.errorHandlers()
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return task.apply (this, this.args(task,argv))
|
|
17
|
+
if (cmd in this.Shortcuts) cmd = process.argv[2] = this.Shortcuts[cmd]
|
|
18
|
+
let task = this.load ('./'+cmd)
|
|
19
|
+
if (task) return task.apply (this, this.args(task,argv))
|
|
20
|
+
|
|
21
|
+
// delegate to cds-dk for rest of commands (usually shortcuts like `cds c`)
|
|
22
|
+
const dk = _requireDk('cds')
|
|
23
|
+
return dk ? dk.exec(cmd, ...argv) : _die_needsDk (cmd)
|
|
21
24
|
},
|
|
22
25
|
|
|
23
26
|
load (cmd) {
|
|
24
|
-
return _require ('./'+cmd)
|
|
25
|
-
|| _require ('@sap/cds-dk/bin/'+cmd) // if dk is in installed modules
|
|
26
|
-
|| _require (_npmGlobalModules()+'/@sap/cds-dk/bin/'+cmd) // needed for running cds in npm scripts
|
|
27
|
+
return _require ('./'+cmd) || _requireDk (cmd)
|
|
27
28
|
},
|
|
28
29
|
|
|
30
|
+
help (cmd) { return this.exec ('help', cmd) },
|
|
31
|
+
|
|
29
32
|
args (task, argv) {
|
|
30
33
|
|
|
31
34
|
const { options:o=[], flags:f=[], shortcuts:s=[] } = task
|
|
@@ -62,10 +65,6 @@ const cli = { //NOSONAR
|
|
|
62
65
|
const _exit = (c) => { console.log(); process.exit(c) }
|
|
63
66
|
cds.repl || process.on ('unhandledRejection', _error)
|
|
64
67
|
cds.repl || process.on ('uncaughtException', _error)
|
|
65
|
-
process.on ('SIGTERM',_exit)
|
|
66
|
-
process.on ('SIGHUP',_exit)
|
|
67
|
-
process.on ('SIGINT',_exit)
|
|
68
|
-
process.on ('SIGUSR2',_exit) // by nodemon
|
|
69
68
|
},
|
|
70
69
|
|
|
71
70
|
get log() { return this.log = require('./utils/log') }
|
|
@@ -76,7 +75,13 @@ const _require = (id,o) => {
|
|
|
76
75
|
return require (resolved)
|
|
77
76
|
}
|
|
78
77
|
|
|
79
|
-
const
|
|
78
|
+
const _requireDk = (cmd) => {
|
|
79
|
+
const { npmGlobalModules } = require('./utils/modules')
|
|
80
|
+
return _require ('@sap/cds-dk/bin/'+cmd) // if dk is in installed modules
|
|
81
|
+
|| _require (npmGlobalModules()+'/@sap/cds-dk/bin/'+cmd) // needed for running cds in npm scripts
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const _die_needsDk = (cmd) => {
|
|
80
85
|
const dk = {add:1,build:1,compile:1,deploy:1,env:1,eval:1,help:1,import:1,init:1,repl:1,watch:1}
|
|
81
86
|
let message
|
|
82
87
|
if (!cmd) { message = `
|
|
@@ -95,12 +100,6 @@ const _requires_cdsdk = (cmd) => {
|
|
|
95
100
|
return console.error (message)
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
const _npmGlobalModules = () => {
|
|
99
|
-
try {
|
|
100
|
-
return require ('child_process').execSync('npm root -g').toString().trim()
|
|
101
|
-
} catch (err) { return }
|
|
102
|
-
}
|
|
103
|
-
|
|
104
103
|
module.exports = Object.assign ((..._) => cli.exec(..._), cli)
|
|
105
104
|
if (!module.parent) cli.exec()
|
|
106
105
|
/* eslint no-console:off */
|
|
@@ -26,7 +26,10 @@ class CfUtil {
|
|
|
26
26
|
|
|
27
27
|
async _cfRun(...args) {
|
|
28
28
|
const cmdLine = `${CF_COMMAND} ${args.join(' ')}`;
|
|
29
|
-
|
|
29
|
+
if (DEBUG) {
|
|
30
|
+
console.time(cmdLine);
|
|
31
|
+
LOG.debug('>>> ' + cmdLine);
|
|
32
|
+
}
|
|
30
33
|
|
|
31
34
|
try {
|
|
32
35
|
return await new Promise((resolve, reject) => {
|
|
@@ -43,6 +46,7 @@ class CfUtil {
|
|
|
43
46
|
});
|
|
44
47
|
|
|
45
48
|
child.on('error', (err) => {
|
|
49
|
+
DEBUG && LOG.debug(`${stdout}\n${stderr}`);
|
|
46
50
|
if (err.code === 'ENOENT') {
|
|
47
51
|
reject(new Error(`Command ${bold(CF_COMMAND)} not found. Make sure to install the Cloud Foundry Command Line Interface.`));
|
|
48
52
|
} else {
|
|
@@ -51,6 +55,7 @@ class CfUtil {
|
|
|
51
55
|
});
|
|
52
56
|
|
|
53
57
|
child.on('close', (code) => {
|
|
58
|
+
DEBUG && LOG.debug(`${stdout}\n${stderr}`);
|
|
54
59
|
if (!code) {
|
|
55
60
|
resolve(stdout.trim());
|
|
56
61
|
} else {
|
|
@@ -87,36 +92,28 @@ class CfUtil {
|
|
|
87
92
|
return result;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
_extract(string, pattern,
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (match) {
|
|
95
|
-
return match[1];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (typeof defaultValue === 'undefined') {
|
|
100
|
-
throw Error(`Pattern not found: ${pattern}`);
|
|
101
|
-
} else {
|
|
102
|
-
return defaultValue;
|
|
95
|
+
_extract(string, pattern, errorMsg) {
|
|
96
|
+
const match = string.match(pattern);
|
|
97
|
+
if (!match || !match[1]) {
|
|
98
|
+
throw new Error(errorMsg);
|
|
103
99
|
}
|
|
100
|
+
return match[1];
|
|
104
101
|
}
|
|
105
102
|
|
|
106
103
|
async getCfTargetFromCli() {
|
|
107
104
|
const result = await this._cfRun('target');
|
|
108
105
|
|
|
109
106
|
return {
|
|
110
|
-
apiEndpoint: this._extract(result, /api endpoint
|
|
111
|
-
user: this._extract(result, /user
|
|
112
|
-
org: this._extract(result, /org
|
|
113
|
-
space: this._extract(result, /space
|
|
107
|
+
apiEndpoint: this._extract(result, /api endpoint\s*:\s*(.*)/i, `CF API endpoint is missing. Use 'cf login' to login.`),
|
|
108
|
+
user: this._extract(result, /user\s*:\s*(.*)/i, `CF user is missing. Use 'cf login' to login.`),
|
|
109
|
+
org: this._extract(result, /org\s*:\s*(.*)/i, `CF org is missing. Use 'cf target -o <ORG> to specify.`),
|
|
110
|
+
space: this._extract(result, /space\s*:\s*(.*)/i, `CF space is missing. Use 'cf target -s <SPACE>' to specify.`),
|
|
114
111
|
};
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
async getCfSpaceInfo() {
|
|
118
115
|
if (!this.spaceInfo) {
|
|
119
|
-
LOG.debug('getting space info');
|
|
116
|
+
DEBUG && LOG.debug('getting space info');
|
|
120
117
|
|
|
121
118
|
const target = await this.getCfTargetFromCli();
|
|
122
119
|
|
|
@@ -36,7 +36,7 @@ class HanaDeployer {
|
|
|
36
36
|
|
|
37
37
|
this.logger.log(`${bold('Starting deploy to SAP HANA ...')}`);
|
|
38
38
|
if (bindCallback) {
|
|
39
|
-
this.logger.log('Using
|
|
39
|
+
this.logger.log('Using cds bind');
|
|
40
40
|
}
|
|
41
41
|
this.logger.log();
|
|
42
42
|
|
|
@@ -181,7 +181,10 @@ class HanaDeployer {
|
|
|
181
181
|
async _build(buildTaskOptions, model) {
|
|
182
182
|
buildTaskOptions = buildTaskOptions || {
|
|
183
183
|
root: process.env._TEST_CWD || process.cwd(),
|
|
184
|
-
cli: true
|
|
184
|
+
cli: true,
|
|
185
|
+
cmdOptions: {
|
|
186
|
+
for: buildConstants.BUILD_TASK_HANA
|
|
187
|
+
}
|
|
185
188
|
};
|
|
186
189
|
|
|
187
190
|
if (typeof model === 'string') {
|
|
@@ -190,31 +193,11 @@ class HanaDeployer {
|
|
|
190
193
|
|
|
191
194
|
this.logger.log(`Creating build tasks`);
|
|
192
195
|
const buildTaskFactory = new BuildTaskFactory(null, cds);
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
const hanaTasks = allTasks.filter((task => {
|
|
196
|
-
return task.for === buildConstants.BUILD_TASK_HANA && (!model || model.includes(task.src));
|
|
197
|
-
}));
|
|
198
|
-
|
|
199
|
-
let srcFolder = cds.env.folders.db || 'db';
|
|
200
|
-
if (Array.isArray(srcFolder)) {
|
|
201
|
-
srcFolder = srcFolder[0] || 'db';
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (hanaTasks.length === 0) {
|
|
205
|
-
hanaTasks.push({
|
|
206
|
-
for: buildConstants.BUILD_TASK_HANA,
|
|
207
|
-
src: srcFolder,
|
|
208
|
-
options: {
|
|
209
|
-
model: cds.env.requires.db && cds.env.requires.db.model || cds.resolve('*', false)
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
196
|
+
const hanaTasks = await buildTaskFactory.getTasks(buildTaskOptions);
|
|
214
197
|
this.logger.log(`Running build`);
|
|
215
198
|
|
|
216
199
|
const buildResults = await new BuildTaskEngine().processTasks(hanaTasks, buildTaskOptions);
|
|
217
|
-
return { buildResults,
|
|
200
|
+
return { buildResults, hanaTasks }
|
|
218
201
|
}
|
|
219
202
|
|
|
220
203
|
|
|
@@ -16,6 +16,10 @@ class HdiDeployUtil {
|
|
|
16
16
|
this.deployerVersionSpec = '^4'
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
async deployTenant(dbDir, env, logger) {
|
|
20
|
+
await this._executeDeploy(dbDir, env, logger);
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
async deploy(dbDir, vcapServices, options = {}) {
|
|
20
24
|
LOG.log();
|
|
21
25
|
LOG.log(`Deploying to HANA from ${dbDir}`);
|
|
@@ -85,18 +89,18 @@ Add it either as a devDependency using 'npm install -D ${this.deployerName}' or
|
|
|
85
89
|
async _npmSearchPaths(cwd) {
|
|
86
90
|
const npmRootCall = await execAsync('npm root -g');
|
|
87
91
|
const globalNodeModules = npmRootCall.stdout.toString().trim();
|
|
88
|
-
return [cwd, globalNodeModules]
|
|
92
|
+
return [cwd, globalNodeModules, '@sap/hdi-deploy']
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
|
|
92
|
-
async _executeDeploy(dbDir, env) {
|
|
96
|
+
async _executeDeploy(dbDir, env, logger) {
|
|
93
97
|
const hdiDeployLib = await this._getHdiDeployLib(dbDir);
|
|
94
98
|
return new Promise((resolve, reject) => {
|
|
95
99
|
const callbacks = {
|
|
96
|
-
stderrCB: error => LOG.error(error.toString())
|
|
100
|
+
stderrCB: error => (logger || LOG).error(error.toString())
|
|
97
101
|
}
|
|
98
102
|
if (LOG.level !== SILENT) {
|
|
99
|
-
callbacks.stdoutCB = (data) =>
|
|
103
|
+
callbacks.stdoutCB = (data) => (logger || LOG).log(data.toString());
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
hdiDeployLib.deploy(dbDir, env, (error, response) => {
|
package/bin/mtx/in-cds.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const cds = require('../build/cds')
|
|
2
|
-
if (cds.requires.multitenancy) try {
|
|
2
|
+
if (cds.requires.multitenancy && !cds.env.features.streamlined_mtx) try {
|
|
3
3
|
const mtx = module.exports = require ('@sap/cds-mtx')()
|
|
4
4
|
mtx.inject (cds)
|
|
5
5
|
cds.on('served', () => cds.emit('mtx'))
|
|
6
|
-
} catch(e) {
|
|
6
|
+
} catch(e) {
|
|
7
7
|
if (e.code === 'MODULE_NOT_FOUND') throw new Error('Error serving MTX APIs: @sap/cds-mtx is not installed')
|
|
8
8
|
else throw e
|
|
9
9
|
}
|
package/bin/serve.js
CHANGED
|
@@ -9,7 +9,7 @@ module.exports = Object.assign ( serve, {
|
|
|
9
9
|
'--mocked', '--with-mocks', '--with-bindings',
|
|
10
10
|
'--watch',
|
|
11
11
|
],
|
|
12
|
-
shortcuts: [ '-s', undefined, '-2', '-a', '-w', '-p' ],
|
|
12
|
+
shortcuts: [ '-s', undefined, '-2', '-a', '-w', undefined, '-p' ],
|
|
13
13
|
help: `
|
|
14
14
|
# SYNOPSIS
|
|
15
15
|
|
|
@@ -183,6 +183,13 @@ async function serve (all=[], o={}) { // NOSONAR
|
|
|
183
183
|
}
|
|
184
184
|
server.listening ? _started(server) : server.once('listening',_started)
|
|
185
185
|
server.on ('error',_reject) // startup errors like EADDRINUSE
|
|
186
|
+
|
|
187
|
+
// graceful server shutdown
|
|
188
|
+
const close = () => server.close()
|
|
189
|
+
process.once('SIGTERM', close)
|
|
190
|
+
process.once('SIGINT', close)
|
|
191
|
+
process.once('SIGHUP', close)
|
|
192
|
+
process.once('SIGUSR2', close) // by nodemon
|
|
186
193
|
return server
|
|
187
194
|
})
|
|
188
195
|
}
|
|
@@ -216,8 +223,8 @@ function _prepare_logging () { // NOSONAR
|
|
|
216
223
|
})
|
|
217
224
|
|
|
218
225
|
// print information about each connected service
|
|
219
|
-
cds.on ('connect', ({name,kind,options:{use,credentials}})=>{
|
|
220
|
-
log (`connect to ${name} > ${use||kind}`, credentials ? _redacted(credentials) : '')
|
|
226
|
+
cds.on ('connect', ({name,kind,options:{use,credentials,impl}})=>{
|
|
227
|
+
log (`connect to ${name} > ${use||kind||impl}`, credentials ? _redacted(credentials) : '')
|
|
221
228
|
})
|
|
222
229
|
|
|
223
230
|
// print information about each provided service
|
package/bin/version.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
const { dirname, join, resolve } = require ('path')
|
|
3
|
+
const { cwd } = require('process')
|
|
3
4
|
module.exports = Object.assign(list_versions, {
|
|
4
5
|
flags: [ '--info', '--markdown', '--all', '--npm-list', '--npm-tree' ],
|
|
5
6
|
shortcuts: [ '-i', '-m','-a', '-ls', '-ll' ],
|
|
@@ -31,6 +32,8 @@ module.exports = Object.assign(list_versions, {
|
|
|
31
32
|
|
|
32
33
|
`})
|
|
33
34
|
|
|
35
|
+
const MISSING = '-- missing --'
|
|
36
|
+
|
|
34
37
|
function list_versions(args, options) { //NOSONAR
|
|
35
38
|
if (options['npm-list'] || options['npm-tree']) {
|
|
36
39
|
let [pattern] = args, re = pattern ? RegExp(pattern) : /@sap\/cd[rs]|@sap\/eslint-plugin-cds/
|
|
@@ -51,13 +54,16 @@ function list_versions(args, options) { //NOSONAR
|
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
function info(o) {
|
|
57
|
+
const { npmGlobalModules } = require('./utils/modules');
|
|
54
58
|
const main = _findPackage (require.main.filename)
|
|
55
59
|
return {
|
|
56
60
|
..._versions4(main, {}, true), // usually sap/cds-dk or sap/cds
|
|
57
61
|
..._versions4('@sap/cds-dk', {}, null, o), // make sure cds-dk is there, cds-maven-plugin uses it
|
|
62
|
+
..._versions4('@sap/cds-dk', {}, null, {...o, label: '@sap/cds-dk (global)', pkg: join(npmGlobalModules(), '@sap/cds-dk')}),
|
|
58
63
|
..._versions4('@sap/eslint-plugin-cds', {}, null, o),
|
|
59
64
|
..._versions4(process.cwd(), {}, null, o),
|
|
60
65
|
..._versions4('..', {}, null, o),
|
|
66
|
+
..._findMTX(),
|
|
61
67
|
'Node.js': process.version,
|
|
62
68
|
'home': __dirname.slice(0,-4)
|
|
63
69
|
}
|
|
@@ -66,13 +72,21 @@ function info(o) {
|
|
|
66
72
|
function _versions4 (pkg_name, info, parent, o={}) {
|
|
67
73
|
if (!pkg_name) return info
|
|
68
74
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
let path = join(o.pkg || pkg_name, 'package.json')
|
|
76
|
+
if(o.here) {
|
|
77
|
+
// path.join(['./', x]) is immediately resolved to x.
|
|
78
|
+
// Calling require() on that will then follow the standard (global) module resolution strategy.
|
|
79
|
+
// If we want to look into a directory relative to CWD,
|
|
80
|
+
// turning it into a global path is the most convenient way.
|
|
81
|
+
path = join(cwd(), path)
|
|
82
|
+
}
|
|
83
|
+
const pkg = require(path)
|
|
84
|
+
info[o.label || pkg.name] = pkg.version
|
|
71
85
|
if (!parent || o.all) for (let d in pkg.dependencies) { // recurse sap packages in dependencies...
|
|
72
86
|
if (!(d in info) && d.startsWith('@sap/')) _versions4(d, info, pkg.name, o)
|
|
73
87
|
}
|
|
74
88
|
} catch (e) {
|
|
75
|
-
if (e.code !== 'MODULE_NOT_FOUND') info[pkg_name] =
|
|
89
|
+
if (e.code !== 'MODULE_NOT_FOUND') info[pkg_name] = MISSING // unknown error
|
|
76
90
|
// require fails for indirect packages if node_modules layout is nested, e.g. on Windows.
|
|
77
91
|
// Try one more time with nested node_modules dir.
|
|
78
92
|
else if (parent) _versions4(parent + '/node_modules/' + pkg_name, info)
|
|
@@ -117,3 +131,42 @@ function _findPackage (dir) {
|
|
|
117
131
|
return _findPackage (dirname (dir))
|
|
118
132
|
}
|
|
119
133
|
}
|
|
134
|
+
|
|
135
|
+
function _findMTX() {
|
|
136
|
+
// looks for any occurrence of cds-mtx.
|
|
137
|
+
// In node projects, cds-mtx can be resolved via _versions4 like all the other SAP modules
|
|
138
|
+
// In Java-flavoured projects cds-mtx may be deployed through a separate node project
|
|
139
|
+
// with just sidecar in it. So we can not rely on the global require() resolution strategy
|
|
140
|
+
// and will as a fallback...
|
|
141
|
+
// (1) ...look for an MTX project within cds.env
|
|
142
|
+
// (2) ...look within a few preselected subdirectories which often contain MTX projects
|
|
143
|
+
const cds = require('../lib')
|
|
144
|
+
const cdsmtx = '@sap/cds-mtx'
|
|
145
|
+
let res = _versions4 (cdsmtx, {}, null)
|
|
146
|
+
|
|
147
|
+
if (res[cdsmtx] === undefined) {
|
|
148
|
+
// not resolvable -> look in cds.env
|
|
149
|
+
if ('build' in cds.env && 'tasks' in cds.env.build) {
|
|
150
|
+
let i = 0
|
|
151
|
+
while (res[cdsmtx] === undefined && i < cds.env.build.tasks.length) {
|
|
152
|
+
const task = cds.env.build.tasks[i]
|
|
153
|
+
if ('for' in task && task.for === 'mtx' && 'dest' in task) {
|
|
154
|
+
res = _versions4 (join(task.dest, 'node_modules', cdsmtx), {}, null, {here: true})
|
|
155
|
+
}
|
|
156
|
+
i++
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// mtx still not found via cds.env? Try looking in well-known subdirectories
|
|
161
|
+
const folders = cds.env.folders
|
|
162
|
+
? [cds.env.folders.db, cds.env.folders.srv].filter(d => d)
|
|
163
|
+
: []
|
|
164
|
+
let i = 0
|
|
165
|
+
while(res[cdsmtx] === undefined && i < folders.length) {
|
|
166
|
+
res = _versions4 (join(folders[i], 'node_modules', cdsmtx), {}, null, {here: true})
|
|
167
|
+
i++
|
|
168
|
+
}
|
|
169
|
+
res[cdsmtx] = res[cdsmtx] || MISSING
|
|
170
|
+
}
|
|
171
|
+
return res
|
|
172
|
+
}
|
package/lib/compile/cdsc.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const
|
|
1
|
+
const cds = require ('../index')
|
|
2
|
+
const {cdsc,odata,sql,features} = cds.env
|
|
2
3
|
const constraints = {
|
|
3
4
|
assertIntegrity: features.assert_integrity,
|
|
4
5
|
assertIntegrityType: features.assert_integrity_type
|
|
@@ -75,7 +76,11 @@ const _options = {for: Object.assign (_options4, {
|
|
|
75
76
|
},
|
|
76
77
|
|
|
77
78
|
hana(o) {
|
|
78
|
-
let cdsc = this.sql (o,hana)
|
|
79
|
+
let cdsc = this.sql (o, cds.env.hana) // returns clone
|
|
80
|
+
cdsc.sqlChangeMode = cdsc.journal && cdsc.journal['change-mode']
|
|
81
|
+
cdsc.disableHanaComments = !cdsc.comments
|
|
82
|
+
delete cdsc.journal // cleanup avoiding side effects
|
|
83
|
+
delete cdsc.comments
|
|
79
84
|
return cdsc
|
|
80
85
|
},
|
|
81
86
|
|
|
@@ -100,7 +105,25 @@ const _options = {for: Object.assign (_options4, {
|
|
|
100
105
|
*/
|
|
101
106
|
module.exports = exports = {__proto__:compile, _options,
|
|
102
107
|
for: {__proto__: compile.for,
|
|
103
|
-
odata: (csn,o) =>
|
|
108
|
+
odata: (csn,o) => {
|
|
109
|
+
if (features.ucsn) {
|
|
110
|
+
const { cloneCsn } = require('@sap/cds-compiler/lib/model/csnUtils') // REVISIT: This should be done by the compiler
|
|
111
|
+
if (compile.version() >= "2.12.1") {
|
|
112
|
+
const generateDrafts = require('@sap/cds-compiler/lib/transform/draft/odata')
|
|
113
|
+
const compiled = generateDrafts(cloneCsn(csn, {}), { messages: [] })
|
|
114
|
+
compiled.meta._4odata = true
|
|
115
|
+
return compiled
|
|
116
|
+
} else {
|
|
117
|
+
// not yet in compiler branch, can't add drafts
|
|
118
|
+
const cloned = cloneCsn(csn, {})
|
|
119
|
+
cloned.meta._4odata = true
|
|
120
|
+
return cloned
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const compiled = compile.for.odata (csn, _options.for.odata(o))
|
|
124
|
+
compiled.meta._4odata = true
|
|
125
|
+
return compiled
|
|
126
|
+
},
|
|
104
127
|
},
|
|
105
128
|
to: {__proto__: compile.to,
|
|
106
129
|
edmx: Object.assign ((csn,o) => compile.to.edmx (csn, _options.for.edm(o)), {
|
|
@@ -5,10 +5,11 @@ const _locales_4sql = {
|
|
|
5
5
|
plain : env.i18n.for_sql || [],
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
// FIXME: we reliably need to now if we'll be on sqlite even before the connect happened
|
|
9
|
-
const _on_sqlite = (env.requires.db || env.requires.sql).dialect === 'sqlite'
|
|
10
8
|
const { _texts_entries, _localized_entries } = env.cdsc.cv2 || {}
|
|
11
9
|
const _been_here = Symbol('is _localized')
|
|
10
|
+
const _conf = env.requires.db || env.requires.sql
|
|
11
|
+
const _on_sqlite = _conf.kind === 'sqlite' || _conf.dialect === 'sqlite'
|
|
12
|
+
//> FIXME: we reliably need to now if we'll be on sqlite even before the connect happened
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
|
|
@@ -18,11 +19,11 @@ const _been_here = Symbol('is _localized')
|
|
|
18
19
|
*/
|
|
19
20
|
function unfold_ddl (ddl, csn, o={}) { // NOSONAR
|
|
20
21
|
const _locales = _locales_4sql[o.dialect]; if (!_locales) return ddl
|
|
21
|
-
const localized_views = ddl.filter (each => each.startsWith
|
|
22
|
-
for (
|
|
23
|
-
for (
|
|
22
|
+
const localized_views = ddl.filter (each => each.startsWith('CREATE VIEW localized_'))
|
|
23
|
+
for (const localized_view of localized_views) {
|
|
24
|
+
for (const locale of _locales) ddl.push (localized_view
|
|
24
25
|
.replace (/localized_/g, `localized_${locale}_`)
|
|
25
|
-
.replace (/\.locale = 'en'
|
|
26
|
+
.replace (/\.locale = 'en'/g, `.locale = '${locale}'`)
|
|
26
27
|
)
|
|
27
28
|
}
|
|
28
29
|
DEBUG && localized_views.length && DEBUG ('Added localized views to DDL for', csn.$sources)
|
|
@@ -48,33 +49,31 @@ function unfold_csn (m) { // NOSONAR
|
|
|
48
49
|
const _locales = _on_sqlite && _locales_4sql.sqlite
|
|
49
50
|
|
|
50
51
|
// Pass 1 - add localized.<locale> entities and views
|
|
51
|
-
for (
|
|
52
|
+
for (const each in cds.linked(m).definitions) {
|
|
52
53
|
const d = m.definitions [each]
|
|
53
54
|
// Add <entry>_texts proxies for all <entry>.texts entities
|
|
54
55
|
if (_texts_entries !== false && each.endsWith('.texts')) {
|
|
55
56
|
_add_proxy4 (d, each.slice(0,-6)+'_texts')
|
|
56
57
|
}
|
|
57
|
-
// Add localized.<entry> for all entities
|
|
58
|
-
if (_localized_entries !== false && d
|
|
59
|
-
|
|
60
|
-
if (x) pass2.push ([x])
|
|
58
|
+
// Add localized.<entry> for all entities having localized views in db
|
|
59
|
+
if (_localized_entries !== false && _is_localized(d)) {
|
|
60
|
+
_add_proxy4 (d,`localized.${each}`, x => pass2.push([x]))
|
|
61
61
|
// if running on sqlite add additional localized.<locale>. views
|
|
62
|
-
if (_locales) for (
|
|
63
|
-
|
|
64
|
-
if (x) pass2.push ([x,locale])
|
|
62
|
+
if (_locales) for (const locale of _locales) {
|
|
63
|
+
_add_proxy4 (d,`localized.${locale}.${each}`, x => pass2.push([x,locale]))
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
// Pass 2 - redirect associations/compositions in elements to localized.<locale> targets
|
|
70
|
-
for (
|
|
69
|
+
for (const [x,locale] of pass2) {
|
|
71
70
|
let overlayed = null
|
|
72
|
-
for (
|
|
73
|
-
|
|
74
|
-
if (e._target && e._target
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
for (const each in x.elements) {
|
|
72
|
+
const e = x.elements [each]
|
|
73
|
+
if (e._target && _is_localized(e._target)) {
|
|
74
|
+
const elements = overlayed || (overlayed = x.elements = {__proto__:x.elements})
|
|
75
|
+
const target = locale ? `localized.${locale}.${e.target}` : `localized.${e.target}`
|
|
76
|
+
const _target = m.definitions[target]
|
|
78
77
|
if (_target) {
|
|
79
78
|
elements[each] = Object.defineProperty ({__proto__:e,target},'_target',{value:_target})
|
|
80
79
|
DEBUG && DEBUG ('overriding:', each, ':', elements[each], 'in', { entity: x.name })
|
|
@@ -88,12 +87,24 @@ function unfold_csn (m) { // NOSONAR
|
|
|
88
87
|
DEBUG && pass2.length && DEBUG ('Added localized views for sqlite to csn for', m.$sources)
|
|
89
88
|
return Object.defineProperty (m, _been_here, {value:true})
|
|
90
89
|
|
|
91
|
-
function _add_proxy4 (d, name) {
|
|
90
|
+
function _add_proxy4 (d, name, callback) {
|
|
92
91
|
if (name in m.definitions) return DEBUG && DEBUG ('NOT overriding existing:', name)
|
|
93
|
-
|
|
94
|
-
DEBUG && DEBUG ('adding proxy:', x)
|
|
92
|
+
const x = {__proto__:d, name }; DEBUG && DEBUG ('adding proxy:', x)
|
|
95
93
|
Object.defineProperty (m.definitions, name, {value:x,writable:true,configurable:true})
|
|
96
|
-
|
|
94
|
+
if (callback) callback(x)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
const $localized = '$$localized', _is_localized = (d,_path) => {
|
|
100
|
+
if (d.own($localized)) return true
|
|
101
|
+
if (!d.elements || d.name.endsWith('.texts')) return false
|
|
102
|
+
// if (d.elements.texts && d.elements.texts.target === `${d.name}.texts`) return d.set($localized,true)
|
|
103
|
+
for (let each in d.elements) {
|
|
104
|
+
const e = d.elements [each]
|
|
105
|
+
if (e.localized || e._target && !(_path && e._target.name in _path) && _is_localized(e._target,{..._path, [d.name]:1 })) {
|
|
106
|
+
return d.set($localized,true)
|
|
107
|
+
}
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
|
package/lib/compile/etc/csv.js
CHANGED
|
@@ -17,14 +17,14 @@ function parse (csv) {
|
|
|
17
17
|
for (let line of lines) {
|
|
18
18
|
if (!rows.length && _ignoreLine (line)) continue
|
|
19
19
|
if (!sep) [sep] = SEPARATOR.exec(line)||[';']
|
|
20
|
-
const values=[]; let val, currCol=0, c, inString=false
|
|
20
|
+
const values=[]; let val, currCol=0, c, inString=false, quoted=false
|
|
21
21
|
for (let i=0; i<line.length; ) {
|
|
22
22
|
c = line[i++]
|
|
23
23
|
if (c === sep && !inString) { // separator
|
|
24
24
|
currCol++
|
|
25
25
|
if (!rows.length && val !== undefined) headers.push (currCol) // skip column if header value is empty
|
|
26
|
-
if (headers.includes(currCol)) values.push (_value4(val)) // skip value if column was skipped
|
|
27
|
-
val = undefined //> start new val
|
|
26
|
+
if (headers.includes(currCol)) values.push (_value4(val, quoted)) // skip value if column was skipped
|
|
27
|
+
val = undefined, quoted = false //> start new val
|
|
28
28
|
}
|
|
29
29
|
else if (c === '"' && val === undefined) { // start quoted string
|
|
30
30
|
val = ''
|
|
@@ -32,7 +32,7 @@ function parse (csv) {
|
|
|
32
32
|
}
|
|
33
33
|
else if (c === '"' && inString) { // within quoted string
|
|
34
34
|
if (line[i] === '"') val += line[i++] // escape quote: "" > "
|
|
35
|
-
else inString = false // stop string
|
|
35
|
+
else inString = false, quoted = true // stop string
|
|
36
36
|
}
|
|
37
37
|
else { // normal char
|
|
38
38
|
if (val === undefined) val = ''
|
|
@@ -42,16 +42,16 @@ function parse (csv) {
|
|
|
42
42
|
// remaining value
|
|
43
43
|
currCol++
|
|
44
44
|
if (!rows.length && val !== undefined) headers.push(currCol) // skip column if header value is empty
|
|
45
|
-
if ((val !== undefined || c === sep) && headers.includes(currCol)) values.push (_value4(val))
|
|
45
|
+
if ((val !== undefined || c === sep) && headers.includes(currCol)) values.push (_value4(val, quoted))
|
|
46
46
|
if (values.length > 0) rows.push (values)
|
|
47
47
|
}
|
|
48
48
|
return rows
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function _value4 (val) { //NOSONAR
|
|
51
|
+
function _value4 (val, quoted = false) { //NOSONAR
|
|
52
52
|
if (val) val = val.trim()
|
|
53
|
-
if (val === 'true') return true
|
|
54
|
-
if (val === 'false') return false
|
|
53
|
+
if (!quoted && val === 'true') return true
|
|
54
|
+
if (!quoted && val === 'false') return false
|
|
55
55
|
else return val
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const cds = require ('../../index')
|
|
2
|
+
module.exports = function cds_compile_for_drafts (csn,o) {
|
|
3
|
+
if (!cds.env.features._ucsn_) return cds.compile.for.odata (csn,o)
|
|
4
|
+
const unfold = cds_compile_for_drafts.unfold || (
|
|
5
|
+
cds_compile_for_drafts.unfold = require ('@sap/cds-compiler/lib/transform/draft/odata')
|
|
6
|
+
)
|
|
7
|
+
// csn = JSON.parse (JSON.stringify (csn)) // REVISIT: workaround for bad test setup
|
|
8
|
+
return unfold (csn,o||{})
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const cds = require ('../../index')
|
|
2
|
+
const _cached = Symbol('for Java')
|
|
3
|
+
|
|
4
|
+
module.exports = function cds_compile_for_java (csn,o) {
|
|
5
|
+
if (!csn) return
|
|
6
|
+
const cached = csn[_cached]; if (cached) return cached
|
|
7
|
+
csn = cds.minify (csn)
|
|
8
|
+
csn = cds.compile.for.drafts (csn,o)
|
|
9
|
+
// Add a parsed _where clause for @restrict.{grant,where} annotations
|
|
10
|
+
if (csn.definitions) for (let {'@restrict':rr} of Object.values(csn.definitions)) if (rr) {
|
|
11
|
+
for (let r of rr) if (r.grant && r.where) try {
|
|
12
|
+
r._where = JSON.stringify (cds.parse.xpr(r.where))
|
|
13
|
+
} catch(e){/* ignored */}
|
|
14
|
+
}
|
|
15
|
+
return csn[_cached] = csn
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const cds = require ('../../index')
|
|
2
|
+
const _cached = Symbol('for Node.js')
|
|
3
|
+
|
|
4
|
+
module.exports = function cds_compile_for_nodejs (csn,o) {
|
|
5
|
+
if (!csn) return
|
|
6
|
+
const cached = csn[_cached]; if (cached) return cached
|
|
7
|
+
csn = cds.minify (csn)
|
|
8
|
+
csn = cds.compile.for.drafts (csn,o) //> creates a partial copy -> avoid any cds.linked() before
|
|
9
|
+
csn = cds.compile._localized.unfold_csn (csn)
|
|
10
|
+
csn = cds.linked (csn)
|
|
11
|
+
return csn[_cached] = csn
|
|
12
|
+
}
|
package/lib/compile/for/odata.js
CHANGED
package/lib/compile/index.js
CHANGED
|
@@ -9,6 +9,9 @@ const {lazified} = require ('../lazy'); require = lazified (module) // eslint-d
|
|
|
9
9
|
const compile = module.exports = Object.assign (cds_compile, {
|
|
10
10
|
|
|
11
11
|
for: lazified ({
|
|
12
|
+
java: require('./for/java'),
|
|
13
|
+
nodejs: require('./for/nodejs'),
|
|
14
|
+
drafts: require('./for/drafts'),
|
|
12
15
|
odata: require('./for/odata'),
|
|
13
16
|
sql: require('./for/sql'),
|
|
14
17
|
}),
|