@sap/cds-dk 8.1.0 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/bin/version.js +2 -3
- package/lib/build/buildTaskFactory.js +29 -12
- package/lib/build/constants.js +1 -1
- package/lib/build/provider/internalBuildTaskProvider.js +2 -35
- package/lib/build/provider/mtx/resourcesTarBuilder.js +2 -2
- package/lib/cds.js +1 -0
- package/lib/compile/to_openapi.js +2 -1
- package/lib/deploy/to-hana/hdiDeployUtil.js +1 -0
- package/lib/import/common.js +1 -1
- package/lib/import/message.js +2 -2
- package/lib/import/odata/v2parser.js +2 -2
- package/lib/init/bas.js +73 -32
- package/lib/init/constants.js +2 -5
- package/lib/init/merge.js +5 -3
- package/lib/init/projectReader.js +0 -1
- package/lib/init/template/data/as-json.js +22 -12
- package/lib/init/template/data/index.js +1 -1
- package/lib/init/template/helm-unified-runtime/index.js +3 -1
- package/lib/init/template/multitenancy/index.js +9 -31
- package/lib/init/template/sample/files/nodejs/cat-service.js +2 -2
- package/lib/init/template/sample/files/srv/cat-service.cds +5 -1
- package/lib/init/template/xsuaa/index.js +10 -3
- package/lib/mtx/push.js +3 -1
- package/npm-shrinkwrap.json +8 -8
- package/package.json +1 -1
- package/lib/init/template/cov2ap/files/dependencies.package.json +0 -5
- package/lib/init/template/cov2ap/index.js +0 -31
- package/lib/init/template/event-queue/files/dependencies.package.json +0 -5
- package/lib/init/template/event-queue/index.js +0 -35
- package/lib/init/template/websocket/files/dependencies.package.json +0 -5
- package/lib/init/template/websocket/index.js +0 -35
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
9
9
|
|
|
10
|
+
## Version 8.1.1 - 2024-08-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add more features to CAP project creation wizard in SAP Business Application Studio.
|
|
15
|
+
- `cds.add.merge` now you specify a `key` in its `deletions` semantics.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- `cds init` uses latest Maven Java archetype version 3.1.0 for creating Java projects.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- `cds import` now gives proper error message for OData import in case of invalid OData version or invalid encoding.
|
|
24
|
+
- `cds import` now able to ignore invalid escape sequence in the description of properties for OData V2.
|
|
25
|
+
- `cds add mta` does not error when the `app/router` folder was deleted.
|
|
26
|
+
- `cds version -i` does not show a globally installed version when none is installed or linked.
|
|
27
|
+
- `cds compile --to openapi` no longer fails with `Error: Unknown protocol: graphql`.
|
|
28
|
+
- `cds add data` can now correctly handle circular dependencies in entities that point to themselves via associations and compositions.
|
|
29
|
+
- `cds add` returns correct suggestions for shell completion.
|
|
30
|
+
- `cds version` reports correct `@sap/cds-compiler` version.
|
|
31
|
+
- `cds deploy` falls back correctly to `@sap/hana-client` when `HDI_DEPLOY_OPTIONS='{"use_hdb":false}'` is set.
|
|
32
|
+
|
|
10
33
|
## Version 8.1.0 - 2024-07-26
|
|
11
34
|
|
|
12
35
|
### Added
|
|
@@ -63,6 +86,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
|
63
86
|
- `cds add helm` removed `saasRegistryParameters` key and moved parameters to `saas-registry`.
|
|
64
87
|
- `cds init` no longer creates a `.cdsrc.json` for Node.js projects.
|
|
65
88
|
- `cds build` configuration cleanup for `data.model` and `service.model` to only support configuration of a single model folder.
|
|
89
|
+
- `cds build` now fully supports default model definitions for custom build plugins.
|
|
66
90
|
|
|
67
91
|
## Version 8.0.1 - 2024-07-09
|
|
68
92
|
|
package/bin/version.js
CHANGED
|
@@ -71,13 +71,12 @@ function info({ root:cwd=process.cwd() }) {
|
|
|
71
71
|
|
|
72
72
|
const npmRoot = execSync('npm root -g').toString().trim()
|
|
73
73
|
let versions = {
|
|
74
|
-
..._versions_from(_pkg_path('@sap/cds-dk',
|
|
75
|
-
..._versions_from(_pkg_path('@sap/cds-dk', npmRoot), '@sap/cds-dk (global)'), // ... or installed globally
|
|
74
|
+
..._versions_from(_pkg_path('@sap/cds-dk', npmRoot), '@sap/cds-dk (global)'), // linked in cap/dev or installed globally
|
|
76
75
|
..._versions_from(_pkg_path('@sap/cds-dk', cwd)), // local dk, important for Java projects
|
|
77
76
|
..._versions_from(_pkg_path('@sap/cds', __dirname)), // @sap/cds from here
|
|
78
77
|
..._versions_from(_pkg_path('@sap/cds', cds.home)), // ... or local @sap/cds
|
|
79
78
|
..._versions_from(cwd), // ... more from local app dependencies
|
|
80
|
-
|
|
79
|
+
'@sap/cds-compiler': cds.compiler.version(),
|
|
81
80
|
'Node.js': process.version,
|
|
82
81
|
'home': cds.home, // effective cds home
|
|
83
82
|
}
|
|
@@ -3,7 +3,7 @@ const path = require('path')
|
|
|
3
3
|
const cds = require('../cds')
|
|
4
4
|
const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
|
|
5
5
|
const { hasJavaNature, getProperty, getDefaultModelOptions, hasOptionValue, BuildError } = require('./util')
|
|
6
|
-
const { FILE_EXT_CDS, OPTION_WS } = require("./constants")
|
|
6
|
+
const { FILE_EXT_CDS, OPTION_WS, IGNORE_DEFAULT_MODELS, NODEJS_MODEL_EXCLUDE_LIST, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF } = require("./constants")
|
|
7
7
|
const term = require('../util/term')
|
|
8
8
|
const DEBUG = cds.debug('cli|build')
|
|
9
9
|
|
|
@@ -95,11 +95,7 @@ class BuildTaskFactory {
|
|
|
95
95
|
task.options.model = [task.options.model]
|
|
96
96
|
}
|
|
97
97
|
})
|
|
98
|
-
|
|
99
|
-
if (!tasks.some(task => !task.options?.model?.length > 0)) {
|
|
100
|
-
return
|
|
101
|
-
}
|
|
102
|
-
const modelPaths = await getDefaultModelOptions()
|
|
98
|
+
const modelPaths = await getDefaultModelOptions(false)
|
|
103
99
|
let wsModelPaths
|
|
104
100
|
// calculate only once
|
|
105
101
|
if (cds.cli.options?.[OPTION_WS] || tasks.some(task => hasOptionValue(task.options?.[OPTION_WS], true))) {
|
|
@@ -107,10 +103,12 @@ class BuildTaskFactory {
|
|
|
107
103
|
}
|
|
108
104
|
// set default model options
|
|
109
105
|
tasks.forEach(task => {
|
|
110
|
-
this._setTaskModelOptions(task, cds.cli.options?.[OPTION_WS] || hasOptionValue(task.options?.[OPTION_WS], true) ? wsModelPaths : modelPaths)
|
|
111
106
|
if (!task.src) {
|
|
112
107
|
throw new BuildError(`Mandatory property 'src' not defined for build task '${task.for}'.`)
|
|
113
108
|
}
|
|
109
|
+
const optionWs = cds.cli.options?.[OPTION_WS] || hasOptionValue(task.options?.[OPTION_WS], true)
|
|
110
|
+
// shallow copy model paths
|
|
111
|
+
this._setTaskModelOptions(task, optionWs ? [...wsModelPaths] : [...modelPaths])
|
|
114
112
|
})
|
|
115
113
|
}
|
|
116
114
|
|
|
@@ -180,14 +178,33 @@ class BuildTaskFactory {
|
|
|
180
178
|
}
|
|
181
179
|
|
|
182
180
|
static _setTaskModelOptions(task, defaultModelPaths) {
|
|
181
|
+
// bootstrap service model is only required for Nodejs build task - issues/12770#issuecomment-1805719
|
|
182
|
+
if (task.for !== BUILD_TASK_NODEJS && task.for !== BUILD_TASK_NODE_CF) {
|
|
183
|
+
defaultModelPaths = defaultModelPaths.filter(p => !NODEJS_MODEL_EXCLUDE_LIST.includes(p))
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let taskModelPaths = task.options?.model
|
|
187
|
+
if (taskModelPaths && !Array.isArray(taskModelPaths)) {
|
|
188
|
+
taskModelPaths = [taskModelPaths]
|
|
189
|
+
}
|
|
190
|
+
const allowList = new RegExp(`^@sap/cds${cds.env.requires.toggles ? '|^' + cds.env.features.folders.replace('*', '') : ''}`)
|
|
183
191
|
task.options = task.options || {}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (task.
|
|
187
|
-
defaultModelPaths.
|
|
192
|
+
let modelPaths = []
|
|
193
|
+
if (taskModelPaths?.length) {
|
|
194
|
+
if (!hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
|
|
195
|
+
modelPaths = defaultModelPaths.filter(p => p.match(allowList))
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
modelPaths = [...defaultModelPaths]
|
|
199
|
+
if (!modelPaths.includes(task.src)) {
|
|
200
|
+
modelPaths.push(task.src)
|
|
201
|
+
}
|
|
202
|
+
if (hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
|
|
203
|
+
// all default models except the built-in models
|
|
204
|
+
modelPaths = modelPaths.filter(p => !p.match(allowList))
|
|
188
205
|
}
|
|
189
|
-
task.options.model = [...defaultModelPaths]
|
|
190
206
|
}
|
|
207
|
+
task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(modelPaths) : modelPaths)]
|
|
191
208
|
}
|
|
192
209
|
|
|
193
210
|
static _stringifyTask(task) {
|
package/lib/build/constants.js
CHANGED
|
@@ -48,7 +48,7 @@ exports.FILE_EXT_CDS = ".cds"
|
|
|
48
48
|
exports.MTX_SIDECAR_FOLDER = "mtx/sidecar" // default name of the mtx sidecar folder
|
|
49
49
|
exports.DEFAULT_CSN_FILE_NAME = "csn.json"
|
|
50
50
|
// REVISIT: the models are not required if a custom server.js file is used for MTX bootstrap
|
|
51
|
-
exports.NODEJS_MODEL_EXCLUDE_LIST = ['@sap/cds
|
|
51
|
+
exports.NODEJS_MODEL_EXCLUDE_LIST = ['@sap/cds-mtxs/srv/bootstrap']
|
|
52
52
|
|
|
53
53
|
exports.CDS_CONFIG_PATH_SEP = "/"
|
|
54
54
|
exports.SEVERITY_ERROR = "Error"
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const cds = require('../../cds')
|
|
4
|
-
const { hasJavaNature,
|
|
4
|
+
const { hasJavaNature, BuildError, normalizePath } = require('../util')
|
|
5
5
|
const BuildTaskProvider = require('../buildTaskProvider')
|
|
6
6
|
const { FILE_EXT_CDS, BUILD_TASK_HANA, BUILD_TASK_FIORI, BUILD_TASK_JAVA, BUILD_TASK_JAVA_CF, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF, BUILD_TASK_MTX,
|
|
7
|
-
BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION
|
|
8
|
-
IGNORE_DEFAULT_MODELS, OPTION_WS } = require("../constants")
|
|
7
|
+
BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION } = require("../constants")
|
|
9
8
|
const ResourcesTarBuilder = require('./mtx/resourcesTarBuilder')
|
|
10
9
|
const DEBUG = cds.debug('cli|build')
|
|
11
10
|
|
|
@@ -19,10 +18,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
async applyTaskDefaults(task) {
|
|
22
|
-
// src folder needs to be initialized first
|
|
23
21
|
InternalBuildTaskProvider._setDefaultSrcFolder(task)
|
|
24
|
-
|
|
25
|
-
await InternalBuildTaskProvider._setDefaultModel(task)
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
getPlugin(task) {
|
|
@@ -284,35 +280,6 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
|
|
|
284
280
|
}
|
|
285
281
|
}
|
|
286
282
|
|
|
287
|
-
static async _setDefaultModel(task) {
|
|
288
|
-
const ws = hasOptionValue(task.options?.[OPTION_WS], true) || cds.cli.options?.[OPTION_WS]
|
|
289
|
-
// REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
|
|
290
|
-
const filter = hasJavaNature() ? (m) => !NODEJS_MODEL_EXCLUDE_LIST.includes(m) : null
|
|
291
|
-
let taskModelPaths = task.options?.model
|
|
292
|
-
if (taskModelPaths && !Array.isArray(taskModelPaths)) {
|
|
293
|
-
taskModelPaths = [taskModelPaths]
|
|
294
|
-
}
|
|
295
|
-
const allowList = new RegExp(`^@sap/cds${cds.env.requires.toggles ? '|^' + cds.env.features.folders.replace('*', '') : ''}`)
|
|
296
|
-
task.options = task.options || {}
|
|
297
|
-
let defaultModelPaths = []
|
|
298
|
-
if (taskModelPaths?.length) {
|
|
299
|
-
if (!hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
|
|
300
|
-
defaultModelPaths = await getDefaultModelOptions(ws, filter)
|
|
301
|
-
defaultModelPaths = defaultModelPaths.filter(p => p.match(allowList))
|
|
302
|
-
}
|
|
303
|
-
} else {
|
|
304
|
-
defaultModelPaths = await getDefaultModelOptions(ws, filter)
|
|
305
|
-
defaultModelPaths.push(task.src)
|
|
306
|
-
if (hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
|
|
307
|
-
// all default models except the built-in models
|
|
308
|
-
defaultModelPaths = defaultModelPaths.filter(p => !p.match(allowList))
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (defaultModelPaths.length) {
|
|
312
|
-
task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(defaultModelPaths) : defaultModelPaths)]
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
283
|
/**
|
|
317
284
|
* Determines the module folder from the given list that may represent files or folders w or w/o .cds file extension.
|
|
318
285
|
* @param {Array} filesOrFolders
|
|
@@ -92,10 +92,10 @@ class ResourcesTarBuilder {
|
|
|
92
92
|
|
|
93
93
|
return hanaTasks.find(hanaTask => {
|
|
94
94
|
// if called from internalBuildTaskProvider, the src folder for the tenant db task might still not set
|
|
95
|
-
// while an existing second shared db always requires src to be
|
|
95
|
+
// while an existing second shared db always requires src to be set
|
|
96
96
|
if (!hanaTask.src) return true
|
|
97
97
|
const srcFolder = path.isAbsolute(hanaTask.src) ? path.relative(cds.root, hanaTask.src) : hanaTask.src
|
|
98
|
-
return mtxTask.options?.model?.includes(srcFolder)
|
|
98
|
+
return mtxTask.options?.model?.includes(srcFolder) || srcFolder === cds.env.folders.db.replace('/', '')
|
|
99
99
|
})
|
|
100
100
|
}
|
|
101
101
|
}
|
package/lib/cds.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @type { import('@sap/cds/lib') } */
|
|
2
2
|
const cds = _local ('@sap/cds')
|
|
3
3
|
|
|
4
|
+
/** @type { import('@sap/cds/lib') & {_local: (id: string) => any} } */
|
|
4
5
|
module.exports = Object.defineProperties (cds, {
|
|
5
6
|
// for internal use in cds-dk only
|
|
6
7
|
_log: { value: _local ('../bin/util/log'), configurable: true },
|
|
@@ -37,6 +37,7 @@ module.exports = new class HdiDeployUtil {
|
|
|
37
37
|
else throw e
|
|
38
38
|
}
|
|
39
39
|
if (options.use_hdb !== false) options.use_hdb = true
|
|
40
|
+
if (options.use_hdb === false) options.use_hdb = undefined
|
|
40
41
|
deployerEnv.HDI_DEPLOY_OPTIONS = JSON.stringify(options)
|
|
41
42
|
|
|
42
43
|
const asyncDeploy = util.promisify(deploy);
|
package/lib/import/common.js
CHANGED
package/lib/import/message.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const messages = {
|
|
4
4
|
INVALID_EDMX_METADATA: 'The OData model is not valid. Specify the correct OData model.',
|
|
5
|
-
|
|
5
|
+
INVALID_ODATA_VERSION_OR_UNSUPPORTED_ENCODING: 'Either the OData version is not valid, or the encoding of the file is not utf-8. Please specify the supported OData version and file encoding. OData version is expected one of [1.0, 2.0, 4.0, 4.01] and the input file encoding is expected UTF-8.',
|
|
6
6
|
INVALID_OUTPUT_FILE: 'Please provide an output file with one of these [cds, csn, json] file extension.',
|
|
7
7
|
SPECIFY_INPUT_FILE: 'Specify an input file that exists.',
|
|
8
8
|
SPECIFY_OUTPUT_FILE: 'Specify an output file or correct the output file path provided.',
|
|
@@ -45,4 +45,4 @@ function getMessages() {
|
|
|
45
45
|
|
|
46
46
|
module.exports = {
|
|
47
47
|
getMessages
|
|
48
|
-
};
|
|
48
|
+
};
|
|
@@ -355,7 +355,7 @@ function _extractAllFunctionImports(functionImports, parserContext) {
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
function _replaceSpecialCharacters(text) {
|
|
358
|
-
return text.replace(/(?:\\[rn]|[\r\n]+)+/gm, "\\n").replace(/\s+/g, ' ').replace(/"/g, """).trim();
|
|
358
|
+
return text.replace(/\\/g, "\\\\").replace(/(?:\\[rn]|[\r\n]+)+/gm, "\\n").replace(/\s+/g, ' ').replace(/"/g, """).trim();
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
// to parse the documentation tag
|
|
@@ -972,7 +972,7 @@ function _parseEntityProperty(properties, parserContext) {
|
|
|
972
972
|
// Has more than one entities
|
|
973
973
|
for (let i = 0; i < properties.length; i++) {
|
|
974
974
|
propAttributes = properties[i]._attributes;
|
|
975
|
-
// if the property contains
|
|
975
|
+
// if the property contains documentation tag
|
|
976
976
|
if (properties[i] && properties[i].Documentation)
|
|
977
977
|
propAttributes.doc = _parseDocumentationTag(properties[i].Documentation);
|
|
978
978
|
retProperties[propAttributes.Name] = _getPropertyAttributes(propAttributes, parserContext);
|
package/lib/init/bas.js
CHANGED
|
@@ -5,8 +5,10 @@ const { bold } = require('../util/term')
|
|
|
5
5
|
const { OPTIONS } = require('./constants')
|
|
6
6
|
const {
|
|
7
7
|
NODEJS, JAVA,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
XSUAA, APPROUTER, CONNECTIVITY, DESTINATION, HTML5_REPO, PORTAL, APPLICATION_LOGGING, AUDIT_LOGGING, NOTIFICATIONS,
|
|
9
|
+
ENTERPRISE_MESSAGING, KAFKA, REDIS_MESSAGING,
|
|
10
|
+
HANA, POSTGRES,
|
|
11
|
+
MTA, HELM, CONTAINERIZE, MULTITENANCY, PIPELINE,
|
|
10
12
|
TINY_SAMPLE, SAMPLE
|
|
11
13
|
} = OPTIONS
|
|
12
14
|
const cwd = process.cwd()
|
|
@@ -17,75 +19,114 @@ module.exports = [{
|
|
|
17
19
|
default: '',
|
|
18
20
|
target: 'projectName',
|
|
19
21
|
validate: async projectName => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
try {
|
|
23
|
+
cds.root = path.resolve(cwd, projectName || '.')
|
|
24
|
+
validate.projectName(projectName)
|
|
25
|
+
validate.projectFolder(path.join(cwd, projectName), cwd)
|
|
26
|
+
} catch (e) {
|
|
27
|
+
return e // BAS Yeoman generator requires error to be returned
|
|
28
|
+
}
|
|
29
|
+
return true
|
|
28
30
|
},
|
|
29
31
|
guiOptions: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
breadcrumb: 'Project Name',
|
|
33
|
+
hint: 'This name is restricted to certain characters. A valid project name is compatible across platforms.',
|
|
34
|
+
mandatory: true
|
|
32
35
|
}
|
|
33
36
|
}, {
|
|
34
37
|
title: 'Type',
|
|
35
38
|
description: `Select your runtime.`,
|
|
36
39
|
default: NODEJS,
|
|
37
40
|
choices: [
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
{ name: 'Node.js', value: NODEJS },
|
|
42
|
+
{ name: 'Java', value: JAVA }
|
|
40
43
|
],
|
|
41
44
|
multiple: false,
|
|
42
45
|
target: 'add',
|
|
43
46
|
guiOptions: {
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
breadcrumb: 'Runtime',
|
|
48
|
+
hint: `The preferred runtime can't be changed afterwards. To use a different runtime, create a new project.`,
|
|
49
|
+
mandatory: true
|
|
46
50
|
}
|
|
47
51
|
}, {
|
|
48
|
-
title: '
|
|
49
|
-
description: 'Choose
|
|
52
|
+
title: 'Databases',
|
|
53
|
+
description: 'Choose a database for your application.',
|
|
50
54
|
default: '',
|
|
51
55
|
choices: [
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{ name: 'User Authentication via XSUAA', value: XSUAA },
|
|
55
|
-
{ name: 'Application Logging', value: APPLICATION_LOGGING },
|
|
56
|
-
{ name: 'SAP BTP Event Mesh', value: ENTERPRISE_MESSAGING }
|
|
56
|
+
{ name: 'SAP HANA Cloud', value: HANA },
|
|
57
|
+
{ name: 'PostgreSQL', value: POSTGRES }
|
|
57
58
|
],
|
|
58
59
|
multiple: true,
|
|
59
60
|
target: 'add',
|
|
60
61
|
guiOptions: {
|
|
61
|
-
|
|
62
|
+
breadcrumb: 'Databases',
|
|
63
|
+
hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
|
|
62
64
|
}
|
|
63
65
|
}, {
|
|
64
66
|
title: 'Deployment',
|
|
65
67
|
description: 'Choose which way to deploy your project.',
|
|
66
68
|
default: '',
|
|
67
69
|
choices: [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
{ name: 'Cloud Foundry: MTA Deployment', value: MTA },
|
|
71
|
+
{ name: 'Kyma: Helm Deployment', value: HELM },
|
|
72
|
+
{ name: 'Kyma: Containerization using ctz CLI', value: CONTAINERIZE },
|
|
73
|
+
{ name: 'Multitenancy', value: MULTITENANCY },
|
|
74
|
+
{ name: 'CI/CD Pipeline Integration', value: PIPELINE }
|
|
75
|
+
],
|
|
76
|
+
multiple: true,
|
|
77
|
+
target: 'add',
|
|
78
|
+
guiOptions: {
|
|
79
|
+
breadcrumb: 'Deployment',
|
|
80
|
+
hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
|
|
81
|
+
}
|
|
82
|
+
}, {
|
|
83
|
+
title: 'Runtime Features',
|
|
84
|
+
description: 'Choose productive runtime capabilities for your application.',
|
|
85
|
+
default: '',
|
|
86
|
+
choices: [
|
|
87
|
+
{ name: 'SAP BTP Authorization and Trust Management Service (XSUAA)', value: XSUAA },
|
|
88
|
+
{ name: 'SAP BTP Application Router', value: APPROUTER },
|
|
89
|
+
{ name: 'SAP BTP Connectivity Service', value: CONNECTIVITY },
|
|
90
|
+
{ name: 'SAP BTP Destination Service', value: DESTINATION },
|
|
91
|
+
{ name: 'SAP BTP HTML5 Application Repository', value: HTML5_REPO },
|
|
92
|
+
{ name: 'SAP BTP Portal Service', value: PORTAL },
|
|
93
|
+
{ name: 'SAP BTP Application Logging Service', value: APPLICATION_LOGGING },
|
|
94
|
+
{ name: 'SAP BTP Audit Logging Service', value: AUDIT_LOGGING },
|
|
95
|
+
{ name: 'SAP BTP Notification Service', value: NOTIFICATIONS }
|
|
96
|
+
],
|
|
97
|
+
multiple: true,
|
|
98
|
+
target: 'add',
|
|
99
|
+
guiOptions: {
|
|
100
|
+
breadcrumb: 'Runtime Features',
|
|
101
|
+
hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
|
|
102
|
+
}
|
|
103
|
+
}, {
|
|
104
|
+
title: 'Messaging',
|
|
105
|
+
description: 'Choose messaging capabilities for your application.',
|
|
106
|
+
default: '',
|
|
107
|
+
choices: [
|
|
108
|
+
{ name: 'SAP BTP Event Mesh', value: ENTERPRISE_MESSAGING },
|
|
109
|
+
{ name: 'Apache Kafka', value: KAFKA },
|
|
110
|
+
{ name: 'Redis', value: REDIS_MESSAGING }
|
|
72
111
|
],
|
|
73
112
|
multiple: true,
|
|
74
113
|
target: 'add',
|
|
75
114
|
guiOptions: {
|
|
76
|
-
|
|
115
|
+
breadcrumb: 'Messaging',
|
|
116
|
+
hint: `Choose any combination of features enriching the capabilities of your project. You can also add features later with ${bold('cds add')}`
|
|
77
117
|
}
|
|
78
118
|
}, {
|
|
79
119
|
title: 'Samples',
|
|
80
120
|
description: `Add sample content to your project.`,
|
|
81
121
|
default: '',
|
|
82
122
|
choices: [
|
|
83
|
-
|
|
84
|
-
|
|
123
|
+
{ name: 'Minimal Sample', value: TINY_SAMPLE },
|
|
124
|
+
{ name: 'Extended Sample with UI', value: SAMPLE }
|
|
85
125
|
],
|
|
86
126
|
multiple: true,
|
|
87
127
|
target: 'add',
|
|
88
128
|
guiOptions: {
|
|
89
|
-
|
|
129
|
+
breadcrumb: 'Samples',
|
|
130
|
+
hint: 'Speed up your ramp-up phase with sample files in your project.'
|
|
90
131
|
}
|
|
91
132
|
}]
|
package/lib/init/constants.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = {
|
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
7
|
JAVA_LTS_VERSIONS: [17, 21],
|
|
8
|
-
MAVEN_ARCHETYPE_VERSION: '3.
|
|
8
|
+
MAVEN_ARCHETYPE_VERSION: '3.1.1',
|
|
9
9
|
|
|
10
10
|
OPTIONS: Object.freeze({
|
|
11
11
|
COMPLETION: 'completion',
|
|
@@ -57,10 +57,7 @@ module.exports = {
|
|
|
57
57
|
LINT_DEV: 'lint:dev',
|
|
58
58
|
PIPELINE: 'pipeline',
|
|
59
59
|
TYPER: 'typer',
|
|
60
|
-
TYPESCRIPT: 'typescript'
|
|
61
|
-
EVENT_QUEUE: 'event-queue',
|
|
62
|
-
COV2AP: 'cov2ap',
|
|
63
|
-
WEBSOCKET: 'websocket'
|
|
60
|
+
TYPESCRIPT: 'typescript'
|
|
64
61
|
}),
|
|
65
62
|
|
|
66
63
|
REGEX_JAVA_PACKAGE: /^[a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*)*$/g,
|
package/lib/init/merge.js
CHANGED
|
@@ -70,7 +70,8 @@ module.exports.mergeGitignore = async function(into, from) {
|
|
|
70
70
|
/**
|
|
71
71
|
* @typedef {Object} Deletion
|
|
72
72
|
* @property {MatchedNode} item - matched node to delete
|
|
73
|
-
* @property {
|
|
73
|
+
* @property {MatchedNode} [key] - key path to property to delete in node (optional)
|
|
74
|
+
* @property {Object[]} [relationships] - list of relationships to delete
|
|
74
75
|
* @property {string} relationships[].removeProperty - key path to to-be-removed property
|
|
75
76
|
* @property {string[]} relationships[].allWithin - key path to relationship
|
|
76
77
|
*/
|
|
@@ -285,10 +286,11 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
285
286
|
})
|
|
286
287
|
|
|
287
288
|
// 4. Delete entries from the project (e.g. separate deployer module when adding mtx)
|
|
288
|
-
deletions?.forEach(({ item, relationships }) => {
|
|
289
|
+
deletions?.forEach(({ item, relationships, key }) => {
|
|
289
290
|
const entry = entryMap.get(item)
|
|
290
291
|
if (!entry) return
|
|
291
|
-
entry.collection.
|
|
292
|
+
if (key) entry.collection.deleteIn([entry.index, ...key.split('.')])
|
|
293
|
+
else entry.collection.delete(entry.index)
|
|
292
294
|
|
|
293
295
|
relationships?.forEach(relationship => {
|
|
294
296
|
const [allWithinKeyPath, inKeyPath, into] = relationship.allWithin
|
|
@@ -3,7 +3,6 @@ const { join, resolve, basename } = require('path')
|
|
|
3
3
|
const { fs, exists, isdir, path } = cds.utils
|
|
4
4
|
const { parseXml } = require('./xml')
|
|
5
5
|
const { REGEX_JAVA_VERSION, JAVA_LTS_VERSIONS } = require('./constants')
|
|
6
|
-
const DEBUG = cds.debug('cli')
|
|
7
6
|
const TRACE = cds.debug('trace')
|
|
8
7
|
|
|
9
8
|
module.exports = new class ProjectReader {
|
|
@@ -15,7 +15,7 @@ const MAX_ASSOC_DEPTH = 5
|
|
|
15
15
|
* @returns {Record<string, object[]>} the filled data
|
|
16
16
|
*/
|
|
17
17
|
const asJson = module.exports = async (data, csn, numRecords=1, options={}) => {
|
|
18
|
-
let { referenceData } = options
|
|
18
|
+
let { referenceData, contentType } = options
|
|
19
19
|
|
|
20
20
|
// if no entity restrictions are given, use all entities
|
|
21
21
|
if (!data) data = csn.all('entity').reduce((all, e) => { all[e.name] = []; return all }, {})
|
|
@@ -63,6 +63,14 @@ const asJson = module.exports = async (data, csn, numRecords=1, options={}) => {
|
|
|
63
63
|
// remove records w/ duplicate keys. This can happen if the key is an enum (and we have less enum values than requested records).
|
|
64
64
|
data[name] = uniqRecords(data[name], entity)
|
|
65
65
|
}
|
|
66
|
+
for (let [key, d] of Object.entries(data)) {
|
|
67
|
+
if (contentType === 'json' && d.deleteReference && !d.keepReferece) {
|
|
68
|
+
delete data[key]
|
|
69
|
+
}
|
|
70
|
+
delete d.keepReferece
|
|
71
|
+
delete d.deleteReference
|
|
72
|
+
uniqRecords(d, csn.definitions[key])
|
|
73
|
+
}
|
|
66
74
|
return data
|
|
67
75
|
}
|
|
68
76
|
|
|
@@ -222,17 +230,16 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
|
|
|
222
230
|
}
|
|
223
231
|
case 'cds.Composition': {
|
|
224
232
|
const target = csn.definitions[element.target]
|
|
225
|
-
if (!target)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (target
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const targetRecords = []
|
|
233
|
+
if (!target || entity.name === target.name || depth > MAX_ASSOC_DEPTH) return
|
|
234
|
+
|
|
235
|
+
let targetRecords = [] // in findKeysInOnCondition target records are linked to the entity, we don't want to overwrite any existing data
|
|
236
|
+
if (data[target.name]) data[target.name].deleteReference = true // for json composites references are nested and will be deleted when writing to file
|
|
237
|
+
|
|
232
238
|
const targetRecordCount = element.is2many ? 2 : 1 // TODO: make this configurable
|
|
233
239
|
const targetRecordID = randomNumber()
|
|
234
240
|
for (let i = 0; i < targetRecordCount; i++) {
|
|
235
|
-
|
|
241
|
+
const newRecord = fillRecord({}, targetRecordID+i, target, csn, data, entity, depth+1, referenceData)
|
|
242
|
+
if (newRecord) targetRecords.push(newRecord)
|
|
236
243
|
}
|
|
237
244
|
|
|
238
245
|
const [ownKey, ownKeyStructured, targetKey] = findKeysInOnCondition(element, target)
|
|
@@ -268,11 +275,14 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
|
|
|
268
275
|
return
|
|
269
276
|
|
|
270
277
|
if (targetRecords.length > 0) { // use record generated by following asociation
|
|
271
|
-
targetRecord = targetRecords
|
|
278
|
+
targetRecord = targetRecords.at(-1) // make sure the localized record references the newly generated texts
|
|
272
279
|
} else {
|
|
273
280
|
targetRecord = fillRecord({}, randomNumber(), target, csn, data, entity, depth+1, referenceData)
|
|
274
|
-
|
|
275
|
-
|
|
281
|
+
if (targetRecord) {
|
|
282
|
+
targetRecords.push(targetRecord)
|
|
283
|
+
uniqRecords(targetRecords, target)
|
|
284
|
+
}
|
|
285
|
+
if (parentEntity && (parentEntity.name != entity.name)) data[target.name].keepReferece = true
|
|
276
286
|
}
|
|
277
287
|
}
|
|
278
288
|
|
|
@@ -77,7 +77,7 @@ module.exports = class DataTemplate extends require('../../plugin') {
|
|
|
77
77
|
.filter (e => queries || !e.query) // remove all projection-like entities unless specified differently
|
|
78
78
|
.reduce((all, e) => { all[e.name] = []; return all }, {})
|
|
79
79
|
|
|
80
|
-
await asJson(data, csn, records)
|
|
80
|
+
await asJson(data, csn, records, {contentType})
|
|
81
81
|
|
|
82
82
|
if (contentType === 'csv') {
|
|
83
83
|
const headerOnly = !cds.cli.options['records'] // compat to old behavior which only creates headers
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const cds = require('../../..')
|
|
2
2
|
const { rimraf, exists, readFileSync, yaml } = cds.utils
|
|
3
3
|
const { join } = require('path')
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
const { readProject } = require('../../projectReader')
|
|
6
|
+
const { merge } = require('../../merge')
|
|
5
7
|
|
|
6
8
|
module.exports = class HelmUnifiedRuntimeTemplate extends require('../helm') {
|
|
7
9
|
|
|
@@ -8,7 +8,7 @@ const { copyRenderedJSON } = require('../../../util/fs')
|
|
|
8
8
|
const {
|
|
9
9
|
srv4, // Server
|
|
10
10
|
mtxSidecar4, // Additional Modules
|
|
11
|
-
saasRegistry,
|
|
11
|
+
saasRegistry, // BTP Services
|
|
12
12
|
srvApi4, providedMtxApiSidecar4, requiredMtxSidecarApi4 // APIs
|
|
13
13
|
} = require('../../registries/mta')
|
|
14
14
|
|
|
@@ -47,13 +47,9 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
47
47
|
const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
|
|
48
48
|
const modules = [srv, mtxSidecar]
|
|
49
49
|
const services = [saasRegistry]
|
|
50
|
-
if (hasXsuaa) services.push(xsuaa)
|
|
51
50
|
const apis = [srvApi4(srv), providedMtxApiSidecar4(mtxSidecar)]
|
|
52
51
|
if (isJava) apis.push(requiredMtxSidecarApi4(srv))
|
|
53
52
|
const additions = [...modules, ...services, ...apis]
|
|
54
|
-
|
|
55
|
-
const overwrites = hasXsuaa ? [{ item: [xsuaa, 'parameters.config.tenant-mode'], withValue: 'shared' }] : []
|
|
56
|
-
|
|
57
53
|
const relationships = [{
|
|
58
54
|
insert: [saasRegistry, 'name'],
|
|
59
55
|
into: [isJava ? srv : mtxSidecar, 'requires', 'name']
|
|
@@ -64,34 +60,16 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
64
60
|
into: [mtxSidecar, 'build-parameters.requires', 'name']
|
|
65
61
|
})
|
|
66
62
|
}
|
|
67
|
-
if (hasXsuaa) {
|
|
68
|
-
relationships.push({
|
|
69
|
-
insert: [xsuaa, 'name'],
|
|
70
|
-
into: [mtxSidecar, 'requires', 'name']
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
if (hasHana) {
|
|
74
|
-
relationships.push({
|
|
75
|
-
insert: [serviceManager, 'name'],
|
|
76
|
-
into: [mtxSidecar, 'requires', 'name'],
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
63
|
|
|
80
|
-
const templateMtaPath = join(__dirname, 'files
|
|
81
|
-
await merge(templateMtaPath).into('mta.yaml', { with: project, additions,
|
|
64
|
+
const templateMtaPath = join(__dirname, 'files/mta.yaml.hbs')
|
|
65
|
+
await merge(templateMtaPath).into('mta.yaml', { with: project, additions, relationships })
|
|
82
66
|
}
|
|
83
67
|
|
|
84
68
|
if (hasHelm || hasHelmUnifiedRuntime) {
|
|
85
|
-
const overwrites = hasXsuaa ? [{
|
|
86
|
-
item: [{
|
|
87
|
-
in: 'xsuaa',
|
|
88
|
-
where: { serviceOfferingName: 'xsuaa' }
|
|
89
|
-
}, 'parameters.tenant-mode'], withValue: 'shared'
|
|
90
|
-
}] : []
|
|
91
69
|
|
|
92
|
-
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project
|
|
70
|
+
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
|
|
93
71
|
|
|
94
|
-
const domain = hasApprouter ? 'svc.cluster.local:8080' : '{{ .Values.global.domain }}'
|
|
72
|
+
const domain = hasApprouter ? 'svc.cluster.local:8080' : '{{ .Values.global.domain }}'
|
|
95
73
|
const applicationWorkload = hasApprouter ? 'approuter' : 'srv'
|
|
96
74
|
const serviceCommunicatingWithSaasReg = hasApprouter ? 'approuter' : isNodejs ? 'sidecar' : 'srv';
|
|
97
75
|
await merge({
|
|
@@ -102,7 +80,7 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
102
80
|
appUrls: {
|
|
103
81
|
getDependencies: `https://{{ .Release.Name }}-${serviceCommunicatingWithSaasReg}-{{ .Release.Namespace }}.{{ .Values.global.domain }}${isNodejs ? '/-/cds/saas-provisioning' : '/mt/v1.0/subscriptions'}/dependencies`,
|
|
104
82
|
onSubscription: `https://{{ .Release.Name }}-${serviceCommunicatingWithSaasReg}-{{ .Release.Namespace }}.{{ .Values.global.domain }}${isNodejs ? '/-/cds/saas-provisioning/tenant/{tenantId}' : '/mt/v1.0/subscriptions/tenants/{tenantId}'}`,
|
|
105
|
-
}
|
|
83
|
+
}
|
|
106
84
|
}
|
|
107
85
|
},
|
|
108
86
|
...(isNodejs) && { sidecar: {
|
|
@@ -110,12 +88,12 @@ module.exports = class MultitenancyTemplate extends require('../../plugin') {
|
|
|
110
88
|
SUBSCRIPTION_URL: `https://\${tenant_subdomain}-{{ .Release.Name }}-${applicationWorkload}-{{ .Release.Namespace }}.{{ .Values.global.domain }}`
|
|
111
89
|
}
|
|
112
90
|
}},
|
|
113
|
-
...(isJava) && { srv: {
|
|
91
|
+
...(isJava) && { srv: {
|
|
114
92
|
env: {
|
|
115
93
|
CDS_MULTITENANCY_APPUI_URL: `https://{{ .Release.Name }}-${applicationWorkload}-{{ .Release.Namespace }}.{{ .Values.global.domain }}`,
|
|
116
94
|
CDS_MULTITENANCY_SIDECAR_URL: `http${hasApprouter ? '' : 's'}://{{ .Release.Name }}-sidecar${hasApprouter ? '.' : '-'}{{ .Release.Namespace }}.${domain}`
|
|
117
|
-
}
|
|
118
|
-
}}
|
|
95
|
+
}
|
|
96
|
+
}}
|
|
119
97
|
}).into('chart/values.yaml',{ forceOverwrite: true })
|
|
120
98
|
}
|
|
121
99
|
|
|
@@ -13,12 +13,12 @@ class CatalogService extends cds.ApplicationService { init() {
|
|
|
13
13
|
// Reduce stock of ordered books if available stock suffices
|
|
14
14
|
this.on('submitOrder', async req => {
|
|
15
15
|
let { book:id, quantity } = req.data
|
|
16
|
-
let book = await SELECT.from (Books, id, b => b.stock)
|
|
16
|
+
let book = await SELECT.one.from (Books, id, b => b.stock)
|
|
17
17
|
|
|
18
18
|
// Validate input data
|
|
19
19
|
if (!book) return req.error (404, `Book #${id} doesn't exist`)
|
|
20
20
|
if (quantity < 1) return req.error (400, `quantity has to be 1 or more`)
|
|
21
|
-
if (quantity > book.stock) return req.error (409, `${quantity} exceeds stock for book #${id}`)
|
|
21
|
+
if (!book.stock || quantity > book.stock) return req.error (409, `${quantity} exceeds stock for book #${id}`)
|
|
22
22
|
|
|
23
23
|
// Reduce stock in database and return updated stock value
|
|
24
24
|
await UPDATE (Books, id) .with ({ stock: book.stock -= quantity })
|
|
@@ -11,6 +11,10 @@ service CatalogService {
|
|
|
11
11
|
} excluding { createdBy, modifiedBy };
|
|
12
12
|
|
|
13
13
|
@requires: 'authenticated-user'
|
|
14
|
-
action submitOrder (
|
|
14
|
+
action submitOrder (
|
|
15
|
+
book : Books:ID @mandatory,
|
|
16
|
+
quantity: Integer @mandatory
|
|
17
|
+
) returns { stock: Integer };
|
|
18
|
+
|
|
15
19
|
event OrderedBook : { book: Books:ID; quantity: Integer; buyer: String };
|
|
16
20
|
}
|
|
@@ -39,7 +39,7 @@ module.exports = class XsuaaTemplate extends require('../../plugin') {
|
|
|
39
39
|
const additions = [srv, xsuaa]
|
|
40
40
|
const mtxSidecar = mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar')
|
|
41
41
|
if (hasMultitenancy && isJava) additions.push(mtxSidecar)
|
|
42
|
-
|
|
42
|
+
const overwrites = hasMultitenancy ? [{ item: [xsuaa, 'parameters.config.tenant-mode'], withValue: 'shared' }] : []
|
|
43
43
|
const relationships = [{
|
|
44
44
|
insert: [xsuaa, 'name'],
|
|
45
45
|
into: [srv, 'requires', 'name']
|
|
@@ -48,11 +48,18 @@ module.exports = class XsuaaTemplate extends require('../../plugin') {
|
|
|
48
48
|
insert: [xsuaa, 'name'],
|
|
49
49
|
into: [mtxSidecar, 'requires', 'name']
|
|
50
50
|
})
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { project, additions, overwrites, relationships })
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
if (hasHelm || hasHelmUnifiedRuntime) {
|
|
55
|
-
|
|
56
|
+
const overwrites = hasMultitenancy ? [{
|
|
57
|
+
item: [{
|
|
58
|
+
in: 'xsuaa',
|
|
59
|
+
where: { serviceOfferingName: 'xsuaa' }
|
|
60
|
+
}, 'parameters.tenant-mode'], withValue: 'shared'
|
|
61
|
+
}] : []
|
|
62
|
+
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project, overwrites })
|
|
56
63
|
|
|
57
64
|
await merge({
|
|
58
65
|
xsuaa: {
|
package/lib/mtx/push.js
CHANGED
|
@@ -95,7 +95,9 @@ module.exports = class Push {
|
|
|
95
95
|
}, 5 * 60 * 1000);
|
|
96
96
|
|
|
97
97
|
const interval = setInterval(async () => {
|
|
98
|
-
const
|
|
98
|
+
const jobResult = await axios.get(jobUrl, options);
|
|
99
|
+
const { status, tasks } = jobResult.data;
|
|
100
|
+
const error = tasks[0]?.error ?? 'cds push failed'
|
|
99
101
|
if (status === JOB_STATUS.FINISHED || status === JOB_STATUS.FAILED) {
|
|
100
102
|
clearInterval(interval);
|
|
101
103
|
clearTimeout(timeout);
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-dk",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@sap/cds-dk",
|
|
9
|
-
"version": "8.1.
|
|
9
|
+
"version": "8.1.1",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@cap-js/asyncapi": "^1.0.0",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"node_modules/@cap-js/openapi": {
|
|
56
|
-
"version": "1.0.
|
|
56
|
+
"version": "1.0.5",
|
|
57
57
|
"license": "SEE LICENSE IN LICENSE",
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"pluralize": "^8.0.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"@sap/cds": ">=7.
|
|
62
|
+
"@sap/cds": ">=7.6"
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"node_modules/@cap-js/sqlite": {
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
}
|
|
230
230
|
},
|
|
231
231
|
"node_modules/@sap/cds-compiler": {
|
|
232
|
-
"version": "5.1.
|
|
232
|
+
"version": "5.1.2",
|
|
233
233
|
"license": "SEE LICENSE IN LICENSE",
|
|
234
234
|
"dependencies": {
|
|
235
235
|
"antlr4": "4.9.3"
|
|
@@ -265,7 +265,7 @@
|
|
|
265
265
|
}
|
|
266
266
|
},
|
|
267
267
|
"node_modules/@sap/cds-mtxs": {
|
|
268
|
-
"version": "2.0.
|
|
268
|
+
"version": "2.0.5",
|
|
269
269
|
"license": "SEE LICENSE IN LICENSE",
|
|
270
270
|
"dependencies": {
|
|
271
271
|
"@sap/hdi-deploy": ">=4",
|
|
@@ -449,7 +449,7 @@
|
|
|
449
449
|
"license": "MIT"
|
|
450
450
|
},
|
|
451
451
|
"node_modules/axios": {
|
|
452
|
-
"version": "1.7.
|
|
452
|
+
"version": "1.7.3",
|
|
453
453
|
"license": "MIT",
|
|
454
454
|
"dependencies": {
|
|
455
455
|
"follow-redirects": "^1.15.6",
|
|
@@ -2304,7 +2304,7 @@
|
|
|
2304
2304
|
}
|
|
2305
2305
|
},
|
|
2306
2306
|
"node_modules/uglify-js": {
|
|
2307
|
-
"version": "3.19.
|
|
2307
|
+
"version": "3.19.1",
|
|
2308
2308
|
"license": "BSD-2-Clause",
|
|
2309
2309
|
"optional": true,
|
|
2310
2310
|
"bin": {
|
package/package.json
CHANGED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const { readProject } = require('../../projectReader')
|
|
2
|
-
const { merge, sort } = require('../../merge')
|
|
3
|
-
const { link } = require('../../../util/term')
|
|
4
|
-
const { CAP_JS_COMMUNITY_ODATA_V2 } = require('../../constants').URLS
|
|
5
|
-
|
|
6
|
-
module.exports = class Cov2apTemplate extends require('../../plugin') {
|
|
7
|
-
|
|
8
|
-
static help() {
|
|
9
|
-
return 'cap-js-community: expose CDS services via the OData V2 protocol'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
static hasInProduction() {
|
|
13
|
-
const { dependencies } = readProject()
|
|
14
|
-
return !!dependencies?.['@cap-js-community/odata-v2-adapter']
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async canRun() {
|
|
18
|
-
const { isJava } = readProject()
|
|
19
|
-
if (isJava) throw `'cds add cov2ap' is not available for Java`
|
|
20
|
-
return true
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async run() {
|
|
24
|
-
await merge(__dirname, 'files/dependencies.package.json').into('package.json')
|
|
25
|
-
await sort('package.json', 'dependencies')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async finalize() {
|
|
29
|
-
console.log(`Find plugin documentation on ${link(CAP_JS_COMMUNITY_ODATA_V2)}`)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const { readProject } = require('../../projectReader')
|
|
2
|
-
const { merge, sort } = require('../../merge')
|
|
3
|
-
const { link } = require('../../../util/term')
|
|
4
|
-
const { CAP_JS_COMMUNITY_EVENT_QUEUE } = require('../../constants').URLS
|
|
5
|
-
|
|
6
|
-
module.exports = class EventQueueTemplate extends require('../../plugin') {
|
|
7
|
-
|
|
8
|
-
static help() {
|
|
9
|
-
return 'cap-js-community: transactional event processing with automatic load distribution'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async canRun() {
|
|
13
|
-
const { isJava } = readProject()
|
|
14
|
-
if (isJava) throw `'cds add event-queue' is not available for Java`
|
|
15
|
-
return true
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static hasInProduction() {
|
|
19
|
-
const { dependencies } = readProject()
|
|
20
|
-
return !!dependencies?.['@cap-js-community/event-queue']
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
requires() {
|
|
24
|
-
return ['redis']
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async run() {
|
|
28
|
-
await merge(__dirname, 'files/dependencies.package.json').into('package.json')
|
|
29
|
-
await sort('package.json', 'dependencies')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async finalize() {
|
|
33
|
-
console.log(`Find plugin documentation on ${link(CAP_JS_COMMUNITY_EVENT_QUEUE)}`)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const { readProject } = require('../../projectReader')
|
|
2
|
-
const { merge, sort } = require('../../merge')
|
|
3
|
-
const { link } = require('../../../util/term')
|
|
4
|
-
const { CAP_JS_COMMUNITY_WEBSOCKET } = require('../../constants').URLS
|
|
5
|
-
|
|
6
|
-
module.exports = class WebsocketTemplate extends require('../../plugin') {
|
|
7
|
-
|
|
8
|
-
static help() {
|
|
9
|
-
return 'cap-js-community: expose CDS services via the Websocket protocol'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async canRun() {
|
|
13
|
-
const { isJava } = readProject()
|
|
14
|
-
if (isJava) throw `'cds add websocket' is not available for Java`
|
|
15
|
-
return true
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
requires() {
|
|
19
|
-
return ['redis']
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
static hasInProduction() {
|
|
23
|
-
const { dependencies } = readProject()
|
|
24
|
-
return !!dependencies?.['@cap-js-community/websocket']
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async run() {
|
|
28
|
-
await merge(__dirname, 'files/dependencies.package.json').into('package.json')
|
|
29
|
-
await sort('package.json', 'dependencies')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async finalize() {
|
|
33
|
-
console.log(`Find plugin documentation on ${link(CAP_JS_COMMUNITY_WEBSOCKET)}`)
|
|
34
|
-
}
|
|
35
|
-
}
|