@sap/cds-dk 8.0.2 → 8.0.3
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 +23 -3
- package/bin/cds.js +11 -6
- package/bin/watch.js +12 -4
- package/lib/build/constants.js +1 -0
- package/lib/build/provider/hana/index.js +51 -33
- package/lib/build/provider/internalBuildTaskProvider.js +2 -2
- package/lib/build/provider/nodejs/index.js +4 -3
- package/lib/init/constants.js +5 -1
- package/lib/init/projectReader.js +0 -1
- package/lib/init/template/data/as-json.js +25 -11
- package/lib/init/template/destination/files/mta.yaml.hbs +6 -0
- package/lib/init/template/destination/files/package.sidecar.json +7 -0
- package/lib/init/template/destination/index.js +12 -2
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +6 -58
- package/lib/init/template/html5-repo/files/package.sidecar.json +7 -0
- package/lib/init/template/html5-repo/files/xs-app.json.hbs +1 -15
- package/lib/init/template/html5-repo/index.js +13 -10
- package/lib/init/template/malware-scanner/index.js +1 -1
- package/lib/init/template/mta/files/package.json +1 -1
- package/lib/init/template/redis/files/mta.yaml.hbs +25 -0
- package/lib/init/template/redis/files/package.json.hbs +5 -0
- package/lib/init/template/redis/index.js +44 -0
- package/lib/init/template/redis-messaging/files/package.json.hbs +0 -3
- package/lib/init/template/redis-messaging/index.js +4 -18
- package/lib/init/template/workzone/index.js +4 -0
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +59 -0
- package/lib/init/template/workzone-standard/index.js +24 -8
- package/npm-shrinkwrap.json +14 -14
- package/package.json +1 -1
- package/lib/init/template/redis-messaging/files/mta.yaml.hbs +0 -14
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,23 @@ 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.0.3 - 2024-07-20
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `cds build --ws` no longer creates migration tables in shared db if already existing in a workspace.
|
|
15
|
+
- `cds add destination` adds the destination service as an MTX SaaS dependency.
|
|
16
|
+
- `cds add html5-repo` adds the HTML5 repo runtime as an MTX SaaS dependency.
|
|
17
|
+
- `cds add html5-repo` does not add a destination service any more if not required by other services.
|
|
18
|
+
- `cds add workzone` runs `cds add destination` as a dependent facet.
|
|
19
|
+
- `cds add` plugins don't fail if custom options are provided via the `options` API.
|
|
20
|
+
- `cds add data` can now correctly handle circular associations. The maximum depth of associations is increased to 5.
|
|
21
|
+
- `cds add redis` is separated from `cds add redis-messaging` to allow for separate consumption.
|
|
22
|
+
- `cds add redis` uses the `standard` service plan by default.
|
|
23
|
+
- `cds watch` no longer leads to a warning `'@sap/cds' was loaded from different installations` when local project dependencies are installed.
|
|
24
|
+
- `cds init` uses latest Maven Java archetype version 3.0.0 for creating Java projects.
|
|
25
|
+
|
|
26
|
+
|
|
10
27
|
## Version 8.0.2 - 2024-07-12
|
|
11
28
|
|
|
12
29
|
### Added
|
|
@@ -20,9 +37,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
|
20
37
|
- `cds init` no longer creates a `.cdsrc.json` for Node.js projects.
|
|
21
38
|
- `cds build` configuration cleanup for `data.model` and `service.model` to only support configuration of a single model folder.
|
|
22
39
|
|
|
23
|
-
### Fixed
|
|
24
|
-
|
|
25
|
-
|
|
26
40
|
## Version 8.0.1 - 2024-07-09
|
|
27
41
|
|
|
28
42
|
### Added
|
|
@@ -129,6 +143,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
|
129
143
|
- `cds add notebook` is removed. CAP Jupyter Notebooks have been replaced by custom CAP Notebooks for VS Code which are now part of the CDS Editor. See https://cap.cloud.sap/docs/tools/#add-cds-editor for more.
|
|
130
144
|
|
|
131
145
|
|
|
146
|
+
## Version 7.9.6 - 2024-07-19
|
|
147
|
+
|
|
148
|
+
### Fixed
|
|
149
|
+
|
|
150
|
+
- `cds add data` can now correctly handle circular associations. The maximum depth of associations is increased to 5.
|
|
151
|
+
|
|
132
152
|
## Version 7.9.5 - 2024-07-12
|
|
133
153
|
|
|
134
154
|
### Added
|
package/bin/cds.js
CHANGED
|
@@ -55,7 +55,8 @@ const cli = {
|
|
|
55
55
|
argv = argv.slice(0, endOfOptions)
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const
|
|
58
|
+
const unknown = new Set
|
|
59
|
+
const args = this.args(task, argv, unknown)
|
|
59
60
|
args[0].push(...appendArgs)
|
|
60
61
|
cds.cli = {
|
|
61
62
|
command: cmd,
|
|
@@ -63,13 +64,17 @@ const cli = {
|
|
|
63
64
|
options: args[1],
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
if (cmd === 'add') {
|
|
67
|
+
if (cmd === 'add') { // cds add plugins allow additional custom options
|
|
68
68
|
await cds.plugins
|
|
69
69
|
for (const [, Plugin] of cds.add.registered) {
|
|
70
|
-
|
|
70
|
+
const options = Object.keys((new Plugin).options()).map(key => '--'+key)
|
|
71
|
+
task.options.push(options)
|
|
72
|
+
options.forEach(o => unknown.delete(o))
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
if (unknown.size === 1) throw 'Invalid option: ' + Array.from(unknown)[0]
|
|
76
|
+
if (unknown.size > 1) throw 'Invalid options: ' + Array.from(unknown).join(', ')
|
|
77
|
+
|
|
73
78
|
if (args[1]?.['resolve-bindings']) await _resolveBindings({ silent: cmd === 'env' })
|
|
74
79
|
|
|
75
80
|
// cds.root may for some subcommands not point to the correct directory (e.g. cds w where users can pass a project directory)
|
|
@@ -101,7 +106,7 @@ const cli = {
|
|
|
101
106
|
},
|
|
102
107
|
|
|
103
108
|
// TODO replace w/ common arg parser from node
|
|
104
|
-
args (task, argv) {
|
|
109
|
+
args (task, argv, unknown) {
|
|
105
110
|
|
|
106
111
|
const { options:o=[], flags:f=[], shortcuts:s=[] } = task
|
|
107
112
|
const _global = /^--(profile|production|sql|odata|add-.*|build-.*|cdsc-.*|odata-.*|folders-.*)$/
|
|
@@ -115,7 +120,7 @@ const cli = {
|
|
|
115
120
|
else if ((k = o.indexOf(a)) >= 0) add(o[k],argv[++i])
|
|
116
121
|
else if ((k = f.indexOf(a)) >= 0) add(f[k])
|
|
117
122
|
else if (_global.test(a)) add_global(a, _flags[a] || argv[++i])
|
|
118
|
-
else
|
|
123
|
+
else unknown.add(a)
|
|
119
124
|
}
|
|
120
125
|
// consistent production setting for NODE_ENV and CDS_ENV
|
|
121
126
|
// if (process.env.NODE_ENV !== 'production') process.env.NODE_ENV = process.env.CDS_ENV?.split(',').find(p => p === 'production') || process.env.NODE_ENV
|
package/bin/watch.js
CHANGED
|
@@ -76,6 +76,7 @@ async function watch ([cwd], {
|
|
|
76
76
|
} catch (err) {
|
|
77
77
|
throw `Error: No such folder or package: '${cwd}'`
|
|
78
78
|
}
|
|
79
|
+
const _cwd = cwd || process.cwd()
|
|
79
80
|
|
|
80
81
|
if (!Object.keys(options).includes('with-mocks')) args.push ('--with-mocks')
|
|
81
82
|
if (!Object.keys(options).find(a => /^in-memory\??$/.test(a))) args.push ('--in-memory?')
|
|
@@ -91,18 +92,20 @@ async function watch ([cwd], {
|
|
|
91
92
|
})
|
|
92
93
|
if (process.env.CDS_TYPESCRIPT) {
|
|
93
94
|
// Needed by ts-node/tsc to find the tsconfig.json. Same as `--project`.
|
|
94
|
-
env.TS_NODE_PROJECT = env.TS_NODE_PROJECT ??
|
|
95
|
+
env.TS_NODE_PROJECT = env.TS_NODE_PROJECT ?? _cwd
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
//
|
|
98
|
-
|
|
98
|
+
// if sap/cds is not installed locally, run with cds-dk's deps. (sap/cds, sqlite etc)
|
|
99
|
+
if (!installed('@sap/cds', _cwd)) {
|
|
100
|
+
env.NODE_PATH = [...paths(_cwd), ...paths(__dirname)].join(delimiter)
|
|
101
|
+
}
|
|
99
102
|
|
|
100
103
|
if (typeof ext !== 'string') ext = extDefaults
|
|
101
104
|
const delay = parseInt(process.env.CDS_WATCH_DELAY) || 200
|
|
102
105
|
|
|
103
106
|
let liveReload //= ...
|
|
104
107
|
let firstTime = true
|
|
105
|
-
if (!/false|no/.test(options['livereload']) && cds.env.for('cds',
|
|
108
|
+
if (!/false|no/.test(options['livereload']) && cds.env.for('cds', _cwd).livereload !== false) {
|
|
106
109
|
liveReload = new (require ('../lib/watch/livereload-server'))
|
|
107
110
|
env.CDS_LIVERELOAD_PATH = require.resolve ('../lib/watch/livereload-connect')
|
|
108
111
|
env.CDS_LIVERELOAD_URL = await liveReload.start (options['livereload'], cwd, delay)
|
|
@@ -199,3 +202,8 @@ function paths (dir) {
|
|
|
199
202
|
const parts = resolve(dir).split(sep), n = parts.length, nm = sep+'node_modules'
|
|
200
203
|
return parts.map ((_,i,a)=> a.slice(0,n-i).join(sep)+nm).filter(p => fs.existsSync(p))
|
|
201
204
|
}
|
|
205
|
+
|
|
206
|
+
function installed(id, ...paths) {
|
|
207
|
+
try { return require.resolve (id, { paths }) }
|
|
208
|
+
catch(e) { if (e.code !== 'MODULE_NOT_FOUND') throw e }
|
|
209
|
+
}
|
package/lib/build/constants.js
CHANGED
|
@@ -35,6 +35,7 @@ exports.CONTENT_ENV = "contentEnv" // copy .env fil
|
|
|
35
35
|
exports.CONTENT_DEFAULT_ENV_JSON = "contentDefaultEnvJson" // copy default-env.json file into deployment folder - DISABLED by default
|
|
36
36
|
|
|
37
37
|
exports.OPTION_WS = "ws" // run a workspace build, e.g. including model folders of configured npm workspaces
|
|
38
|
+
exports.OPTION_WS_PACK = "ws-pack" // enable tarball based packaging of workspace dependencies
|
|
38
39
|
exports.CSV_FILE_TARGET = "csvFileTarget" // target folder when copying CSV files to the deployment target folder ./db/src/gen/*, default is 'data'
|
|
39
40
|
exports.CSV_FILE_DETECTION = "csvFileDetection" // detect CSV files based on CDS model location - ENABLED by default
|
|
40
41
|
exports.EXTENSION_POINT_VALIDATION = "extensionPointValidation" // validate extension point restrictions defined by the extended SaaS app - ENABLED by default
|
|
@@ -6,7 +6,7 @@ const InternalBuildPlugin = require('../internalBuildPlugin')
|
|
|
6
6
|
const { BuildError, relativePaths, BuildMessage, getWorkspaces, hasOptionValue, getFiles } = require('../../util')
|
|
7
7
|
const { OUTPUT_MODE_NONE, OUTPUT_MODE, CONTENT_PACKAGE_JSON, CONTENT_HDBTABLEDATA, CSV_FILE_DETECTION,
|
|
8
8
|
CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, OUTPUT_MODE_RESULT, CONTINUE_UNRESOLVED_SCHEMA_CHANGES,
|
|
9
|
-
CSV_FILE_TARGET, OPTION_WS} = require('../../constants')
|
|
9
|
+
CSV_FILE_TARGET, OPTION_WS } = require('../../constants')
|
|
10
10
|
const { WARNING } = InternalBuildPlugin
|
|
11
11
|
const DEFAULT_COMPILE_DEST_FOLDER = path.normalize("src/gen")
|
|
12
12
|
const FILE_EXT_CSV = ".csv"
|
|
@@ -38,9 +38,14 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
38
38
|
if (!model) {
|
|
39
39
|
return
|
|
40
40
|
}
|
|
41
|
+
let workspaceFiles
|
|
42
|
+
if (cds.cli.options?.[OPTION_WS] || hasOptionValue(this.task.options[OPTION_WS], true)) {
|
|
43
|
+
workspaceFiles = await this._getWorkspaceFiles()
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
// the order of 1 and 2 is important
|
|
42
47
|
// 1. compile
|
|
43
|
-
const hdiPlugins = await this._compileToHana(model)
|
|
48
|
+
const hdiPlugins = await this._compileToHana(model, workspaceFiles)
|
|
44
49
|
|
|
45
50
|
if (!this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_NONE)) {
|
|
46
51
|
// 2. copy resources
|
|
@@ -49,9 +54,15 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
49
54
|
} else {
|
|
50
55
|
await this._copyResourcesExt(src, dest, model)
|
|
51
56
|
}
|
|
52
|
-
// copy native hana artifacts from
|
|
53
|
-
if (
|
|
54
|
-
|
|
57
|
+
// copy native hana artifacts from workspaces
|
|
58
|
+
if (workspaceFiles) {
|
|
59
|
+
const dest = path.join(this.task.dest, 'src/gen')
|
|
60
|
+
await Promise.all(
|
|
61
|
+
workspaceFiles.map((src) => {
|
|
62
|
+
const { dir, filePath } = src
|
|
63
|
+
return this.copy(path.join(dir, filePath)).to(path.join(dest, filePath))
|
|
64
|
+
})
|
|
65
|
+
)
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
// create additional stuff in dest
|
|
@@ -254,7 +265,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
254
265
|
*
|
|
255
266
|
* @param {object} model The compiled csn model
|
|
256
267
|
*/
|
|
257
|
-
async _compileToHana(model) {
|
|
268
|
+
async _compileToHana(model, workspaceFiles) {
|
|
258
269
|
// compile to old format (.hdbcds) or new format (.hdbtable / .hdbview)
|
|
259
270
|
const format = this.getBuildOption(DEPLOY_FORMAT) || cds.env.requires.db?.[DEPLOY_FORMAT] || cds.env.hana?.[DEPLOY_FORMAT]
|
|
260
271
|
if (!cds.compile.to[format]) {
|
|
@@ -267,7 +278,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
267
278
|
// compatibility with existing cds.compile.to.hdbtable plugins cds < 8.0.0
|
|
268
279
|
return await this._compileToHdb(model, format)
|
|
269
280
|
} else {
|
|
270
|
-
return await this._compileToHdbmigration(model, format)
|
|
281
|
+
return await this._compileToHdbmigration(model, format, workspaceFiles)
|
|
271
282
|
}
|
|
272
283
|
}
|
|
273
284
|
|
|
@@ -303,7 +314,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
303
314
|
return hdiPlugins
|
|
304
315
|
}
|
|
305
316
|
|
|
306
|
-
async _compileToHdbmigration(model, format) {
|
|
317
|
+
async _compileToHdbmigration(model, format, workspaceFiles) {
|
|
307
318
|
const hdiPlugins = new Set()
|
|
308
319
|
const relDestDir = path.relative(this.task.dest, this.task.options.compileDest)
|
|
309
320
|
const relDbDestDir = path.relative(cds.root, this.task.options.compileDest)
|
|
@@ -326,33 +337,37 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
326
337
|
|
|
327
338
|
for (const { name, suffix, content, changed } of definitions) {
|
|
328
339
|
hdiPlugins.add(suffix)
|
|
329
|
-
const
|
|
340
|
+
const fileName = name + suffix
|
|
330
341
|
if (suffix === FILE_EXT_HDBMIGRATIONTABLE) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
342
|
+
// Skip the .hdbmigrationtable file if its origin is a different workspace.
|
|
343
|
+
// The workspace build copies artifacts located in 'db/src/**' workspace folders.
|
|
344
|
+
if (!workspaceFiles?.find(wsFile => wsFile.fileName === fileName)) {
|
|
345
|
+
migrationTableFiles.push(path.join(relDbSrcDir, fileName))
|
|
346
|
+
if (changed) {
|
|
347
|
+
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
348
|
+
this._result.hana.push(path.join("src", fileName))
|
|
349
|
+
}
|
|
350
|
+
promises.push(this.write(content).to(path.join(dbSrcDir, fileName)))
|
|
351
|
+
} else {
|
|
352
|
+
DEBUG?.(`no change, keep existing ${fileName}`)
|
|
335
353
|
}
|
|
336
|
-
promises.push(this.write(content).to(path.join(dbSrcDir, file)))
|
|
337
|
-
} else {
|
|
338
|
-
DEBUG?.(`no change, keep existing ${file}`)
|
|
339
354
|
}
|
|
340
355
|
} else {
|
|
341
356
|
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
342
|
-
this._result.hana.push(path.join(relDestDir,
|
|
357
|
+
this._result.hana.push(path.join(relDestDir, fileName))
|
|
343
358
|
}
|
|
344
|
-
promises.push(this.write(content).to(path.join(this.task.options.compileDest,
|
|
359
|
+
promises.push(this.write(content).to(path.join(this.task.options.compileDest, fileName)))
|
|
345
360
|
if (suffix === FILE_EXT_HDBTABLE) {
|
|
346
361
|
// issue an error in case a .hdbmigrationtable file already exists
|
|
347
362
|
if (fs.existsSync(path.join(dbSrcDir, name + FILE_EXT_HDBMIGRATIONTABLE))) {
|
|
348
|
-
validationError = new BuildError(`Multiple files exist defining the same HANA artifact - [${path.join(relDbSrcDir, name + FILE_EXT_HDBMIGRATIONTABLE)}, ${path.join(relDbDestDir,
|
|
363
|
+
validationError = new BuildError(`Multiple files exist defining the same HANA artifact - [${path.join(relDbSrcDir, name + FILE_EXT_HDBMIGRATIONTABLE)}, ${path.join(relDbDestDir, fileName)}].\nEither annotate the model entity using @cds.persistence.journal or undeploy the file [${path.join('src', name + FILE_EXT_HDBMIGRATIONTABLE)}] using an undeploy.json file.`)
|
|
349
364
|
}
|
|
350
365
|
}
|
|
351
366
|
}
|
|
352
367
|
}
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
// cds build command is again executed
|
|
368
|
+
// The last-dev CSN shall only be updated, if all .hdbmigrationtable files could be successfully updated.
|
|
369
|
+
// Of course, .hdbmigrationtable files already written would need to be manually reverted before the
|
|
370
|
+
// cds build command is again executed.
|
|
356
371
|
await Promise.all(promises)
|
|
357
372
|
|
|
358
373
|
try {
|
|
@@ -531,35 +546,38 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
531
546
|
}
|
|
532
547
|
}
|
|
533
548
|
|
|
534
|
-
|
|
535
549
|
/**
|
|
536
|
-
*
|
|
550
|
+
* Returns all hana native artifacts located in db/src/** workspace folders.
|
|
551
|
+
* @returns {Array} Array of workspace files, each entry contains the db src directory,
|
|
552
|
+
* the relative file path and the file name.
|
|
537
553
|
*/
|
|
538
|
-
async
|
|
539
|
-
const
|
|
554
|
+
async _getWorkspaceFiles() {
|
|
555
|
+
const dbPaths = new Set()
|
|
540
556
|
const workspaces = await getWorkspaces()
|
|
541
557
|
|
|
542
558
|
workspaces.forEach(workspace => {
|
|
543
559
|
const dbSrc = path.join(cds.root, workspace, 'db/src')
|
|
544
560
|
const dbCfg = path.join(cds.root, workspace, 'db/cfg')
|
|
545
561
|
if (fs.existsSync(dbSrc)) {
|
|
546
|
-
|
|
562
|
+
dbPaths.add(dbSrc)
|
|
547
563
|
}
|
|
548
564
|
if (fs.existsSync(dbCfg)) {
|
|
549
|
-
|
|
565
|
+
dbPaths.add(dbCfg)
|
|
550
566
|
}
|
|
551
567
|
})
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
for (const src of srcPaths) {
|
|
555
|
-
await this.copyNativeContent(src, dest, (entry) => {
|
|
568
|
+
const workspaceFiles = [...dbPaths].reduce((acc, src) => {
|
|
569
|
+
const files = getFiles(src, (entry) => {
|
|
556
570
|
if (entry.match(/(\/|\\)gen(\/|\\)?$/)) {
|
|
557
571
|
// skip gen folder content
|
|
558
572
|
return false
|
|
559
573
|
}
|
|
560
574
|
return true
|
|
561
575
|
})
|
|
562
|
-
|
|
576
|
+
files.forEach(file => acc.add({ dir: src, filePath: path.relative(src, file), fileName: path.basename(file) }))
|
|
577
|
+
return acc
|
|
578
|
+
}, new Set())
|
|
579
|
+
|
|
580
|
+
return [...workspaceFiles]
|
|
563
581
|
}
|
|
564
582
|
|
|
565
583
|
static async _readTemplateAsJson(template) {
|
|
@@ -5,7 +5,7 @@ const { hasJavaNature, getDefaultModelOptions, BuildError, hasOptionValue, norma
|
|
|
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
7
|
BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION, NODEJS_MODEL_EXCLUDE_LIST,
|
|
8
|
-
IGNORE_DEFAULT_MODELS,
|
|
8
|
+
IGNORE_DEFAULT_MODELS, OPTION_WS } = require("../constants")
|
|
9
9
|
const ResourcesTarBuilder = require('./mtx/resourcesTarBuilder')
|
|
10
10
|
const DEBUG = cds.debug('cli|build')
|
|
11
11
|
|
|
@@ -285,7 +285,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
|
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
static async _setDefaultModel(task) {
|
|
288
|
-
const ws = hasOptionValue(task.options?.[
|
|
288
|
+
const ws = hasOptionValue(task.options?.[OPTION_WS], true) || cds.cli.options?.[OPTION_WS]
|
|
289
289
|
// REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
|
|
290
290
|
const filter = hasJavaNature() ? (m) => !NODEJS_MODEL_EXCLUDE_LIST.includes(m) : null
|
|
291
291
|
let taskModelPaths = task.options?.model
|
|
@@ -5,7 +5,8 @@ const cmd = require('../../../util/command');
|
|
|
5
5
|
const EdmxBuildPlugin = require('../edmxBuildPlugin')
|
|
6
6
|
const { BuildError, getWorkspaces } = require('../../util')
|
|
7
7
|
const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTENT_EDMX, CONTENT_PACKAGELOCK_JSON,
|
|
8
|
-
CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX
|
|
8
|
+
CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX,
|
|
9
|
+
OPTION_WS_PACK} = require('../../constants')
|
|
9
10
|
const { WARNING } = EdmxBuildPlugin
|
|
10
11
|
const DEBUG = cds.debug('cli|build')
|
|
11
12
|
|
|
@@ -36,7 +37,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
36
37
|
}
|
|
37
38
|
// by default model contains all features
|
|
38
39
|
const model = await this.model()
|
|
39
|
-
if (!model && !this.context.options[
|
|
40
|
+
if (!model && !this.context.options[OPTION_WS_PACK]) {
|
|
40
41
|
return
|
|
41
42
|
}
|
|
42
43
|
if (model) {
|
|
@@ -55,7 +56,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
55
56
|
if (this.isStagingBuild() && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
|
|
56
57
|
const srcSrv = this.task.src === cds.root ? path.resolve(this.task.src, cds.env.folders.srv) : this.task.src
|
|
57
58
|
await this._copyNativeContent(cds.root, srcSrv, destRoot, destSrv)
|
|
58
|
-
if (this.context.options[
|
|
59
|
+
if (this.context.options[OPTION_WS_PACK]) {
|
|
59
60
|
await this._packWorkspaceDependencies(destRoot)
|
|
60
61
|
}
|
|
61
62
|
}
|
package/lib/init/constants.js
CHANGED
|
@@ -5,9 +5,10 @@ module.exports = {
|
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
7
|
JAVA_LTS_VERSIONS: [17, 21],
|
|
8
|
-
MAVEN_ARCHETYPE_VERSION: '
|
|
8
|
+
MAVEN_ARCHETYPE_VERSION: '3.0.0',
|
|
9
9
|
|
|
10
10
|
OPTIONS: Object.freeze({
|
|
11
|
+
COMPLETION: 'completion',
|
|
11
12
|
JAVA: 'java',
|
|
12
13
|
JAVA_MVN: 'java:mvn',
|
|
13
14
|
JAVA_PACKAGE: 'java:package',
|
|
@@ -30,6 +31,9 @@ module.exports = {
|
|
|
30
31
|
SQLITE: 'sqlite',
|
|
31
32
|
H2: 'h2',
|
|
32
33
|
LIQUIBASE: 'liquibase',
|
|
34
|
+
REDIS: 'redis',
|
|
35
|
+
ATTACHMENTS: 'attachments',
|
|
36
|
+
MALWARE_SCANNER: 'malware-scanner',
|
|
33
37
|
LOCAL_MESSAGING: 'local-messaging',
|
|
34
38
|
FILE_BASED_MESSAGING: 'file-based-messaging',
|
|
35
39
|
ENTERPRISE_MESSAGING: 'enterprise-messaging',
|
|
@@ -3,7 +3,7 @@ const { dirname } = require('node:path')
|
|
|
3
3
|
const cds = require('../../../cds')
|
|
4
4
|
|
|
5
5
|
let counter = Math.round(Math.random() * 10000) // Default random seed // Non-deterministic behaviour
|
|
6
|
-
const MAX_ASSOC_DEPTH =
|
|
6
|
+
const MAX_ASSOC_DEPTH = 5
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates JSON test data for the given entities
|
|
@@ -40,25 +40,35 @@ const asJson = module.exports = async (data, csn, numRecords=1, options={}) => {
|
|
|
40
40
|
|
|
41
41
|
for (const name of entityNames) {
|
|
42
42
|
if (!data[name] // removed on purpose because records are created inline through compositions
|
|
43
|
-
|| data[name].length >= numRecords) { // already created by following associations
|
|
43
|
+
|| data[name].length >= numRecords) { // numRecords already created by following associations
|
|
44
44
|
continue
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
let numRecordsToGenerate // numRecords might be reduced if some records were created by following associations
|
|
48
|
+
let records = []
|
|
49
|
+
if (data[name].length > 0) {
|
|
50
|
+
numRecordsToGenerate = numRecords - data[name].length
|
|
51
|
+
records = Array(numRecordsToGenerate).fill({}).map(() => ({}))
|
|
52
|
+
} else {
|
|
53
|
+
numRecordsToGenerate = numRecords
|
|
54
|
+
records = data[name] = Array(numRecordsToGenerate).fill({}).map(() => ({}))
|
|
55
|
+
}
|
|
48
56
|
const entity = defs[name]
|
|
49
57
|
|
|
50
58
|
const idNum = randomNumber()
|
|
51
|
-
for (let i = 0; i <
|
|
59
|
+
for (let i = 0; i < numRecordsToGenerate; i++) {
|
|
52
60
|
fillRecord(records[i], idNum+i, entity, csn, data, null, 0, referenceData)
|
|
53
61
|
}
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
data[name] = data[name].concat(records) // append the new records to the possibly existingand referenced records
|
|
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
|
+
data[name] = uniqRecords(data[name], entity)
|
|
56
65
|
}
|
|
57
66
|
return data
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
function fillRecord(record, recordID, entity, csn, data, parentEntity, depth, referenceData) {
|
|
61
70
|
Object.defineProperty(record, '$id', {value: recordID, enumerable: false})
|
|
71
|
+
if (data[entity.name]) data[entity.name].push(record) // add id to data, to be referenced by associations to prevent circular dependencies
|
|
62
72
|
|
|
63
73
|
const { elements } = entity
|
|
64
74
|
Object.values(elements).sort(asJson.elementsSorter(csn)).forEach(el => {
|
|
@@ -242,7 +252,7 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
|
|
|
242
252
|
if (element.is2many)
|
|
243
253
|
return
|
|
244
254
|
const target = csn.definitions[element.target]
|
|
245
|
-
if (!target ||
|
|
255
|
+
if (!target || depth > MAX_ASSOC_DEPTH)
|
|
246
256
|
return
|
|
247
257
|
|
|
248
258
|
let targetRecord = randomFromReferenceData(target, csn, referenceData)
|
|
@@ -256,10 +266,14 @@ function dataForField(element, entity, csn, record, data, parentEntity, depth, r
|
|
|
256
266
|
targetRecords = data[target.name] = []
|
|
257
267
|
else if (!targetRecords) // target entity is not in the list of entities to be created
|
|
258
268
|
return
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
269
|
+
|
|
270
|
+
if (targetRecords.length > 0) { // use record generated by following asociation
|
|
271
|
+
targetRecord = targetRecords[0]
|
|
272
|
+
} else {
|
|
273
|
+
targetRecord = fillRecord({}, randomNumber(), target, csn, data, entity, depth+1, referenceData)
|
|
274
|
+
targetRecords.push(targetRecord)
|
|
275
|
+
uniqRecords(targetRecords, target)
|
|
276
|
+
}
|
|
263
277
|
}
|
|
264
278
|
|
|
265
279
|
// TODO: handle foreign keys correctly
|
|
@@ -11,6 +11,12 @@ modules:
|
|
|
11
11
|
requires:
|
|
12
12
|
- name: {{appName}}-destination
|
|
13
13
|
|
|
14
|
+
- name: {{appName}}-mtx
|
|
15
|
+
type: nodejs
|
|
16
|
+
path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
|
|
17
|
+
requires:
|
|
18
|
+
- name: {{appName}}-destination
|
|
19
|
+
|
|
14
20
|
resources:
|
|
15
21
|
- name: {{appName}}-destination
|
|
16
22
|
type: org.cloudfoundry.managed-service
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { readProject } = require('../../projectReader')
|
|
2
2
|
const { merge } = require('../../merge')
|
|
3
|
-
const { srv4, approuter, destination } = require('../../registries/mta')
|
|
3
|
+
const { srv4, approuter, destination, mtxSidecar4 } = require('../../registries/mta')
|
|
4
4
|
|
|
5
5
|
module.exports = class DestinationTemplate extends require('../../plugin') {
|
|
6
6
|
|
|
@@ -24,7 +24,11 @@ module.exports = class DestinationTemplate extends require('../../plugin') {
|
|
|
24
24
|
|
|
25
25
|
async combine() {
|
|
26
26
|
const project = readProject()
|
|
27
|
-
const { hasHelm, hasApprouter, hasHelmUnifiedRuntime, hasMta, srvPath } = project
|
|
27
|
+
const { hasHelm, hasApprouter, hasMultitenancy, hasHelmUnifiedRuntime, hasMta, srvPath, isJava } = project
|
|
28
|
+
|
|
29
|
+
if (hasMultitenancy) {
|
|
30
|
+
await merge(__dirname, 'files/package.sidecar.json').into('mtx/sidecar/package.json')
|
|
31
|
+
}
|
|
28
32
|
|
|
29
33
|
if (hasMta) {
|
|
30
34
|
const srv = srv4(srvPath)
|
|
@@ -39,6 +43,12 @@ module.exports = class DestinationTemplate extends require('../../plugin') {
|
|
|
39
43
|
into: [approuter, 'requires', 'name']
|
|
40
44
|
})
|
|
41
45
|
}
|
|
46
|
+
if (hasMultitenancy) {
|
|
47
|
+
relationships.push({
|
|
48
|
+
insert: [destination, 'name'],
|
|
49
|
+
into: [mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar'), 'requires', 'name']
|
|
50
|
+
})
|
|
51
|
+
}
|
|
42
52
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project, additions, relationships })
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -12,6 +12,12 @@ modules:
|
|
|
12
12
|
requires:
|
|
13
13
|
- name: {{appName}}-html5-runtime
|
|
14
14
|
|
|
15
|
+
- name: {{appName}}-mtx
|
|
16
|
+
type: nodejs
|
|
17
|
+
path: {{#isNodejs}}gen/{{/isNodejs}}mtx/sidecar
|
|
18
|
+
requires:
|
|
19
|
+
- name: {{appName}}-html5-runtime
|
|
20
|
+
|
|
15
21
|
- name: {{appName}}-app-deployer
|
|
16
22
|
type: com.sap.application.content
|
|
17
23
|
path: {{#isNodejs}}gen{{/isNodejs}}{{#isJava}}.{{/isJava}}
|
|
@@ -42,38 +48,6 @@ modules:
|
|
|
42
48
|
supported-platforms: []
|
|
43
49
|
{{/apps}}
|
|
44
50
|
|
|
45
|
-
- name: {{appName}}-destinations
|
|
46
|
-
type: com.sap.application.content
|
|
47
|
-
requires:
|
|
48
|
-
- name: {{appName}}-auth
|
|
49
|
-
parameters:
|
|
50
|
-
service-key:
|
|
51
|
-
name: {{appName}}-auth-key
|
|
52
|
-
- name: {{appName}}-html5-repo-host
|
|
53
|
-
parameters:
|
|
54
|
-
service-key:
|
|
55
|
-
name: {{appName}}-html5-repo-host-key
|
|
56
|
-
- name: srv-api
|
|
57
|
-
- name: {{appName}}-destination
|
|
58
|
-
parameters:
|
|
59
|
-
content-target: true
|
|
60
|
-
build-parameters:
|
|
61
|
-
no-source: true
|
|
62
|
-
parameters:
|
|
63
|
-
content:
|
|
64
|
-
instance:
|
|
65
|
-
existing_destinations_policy: update
|
|
66
|
-
destinations:
|
|
67
|
-
- Name: {{appName}}-html5-repository
|
|
68
|
-
ServiceInstanceName: {{appName}}-html5-repo-host
|
|
69
|
-
ServiceKeyName: {{appName}}-html5-repo-host-key
|
|
70
|
-
sap.cloud.service: {{appName}}.service
|
|
71
|
-
- Name: {{appName}}-auth
|
|
72
|
-
Authentication: OAuth2UserTokenExchange
|
|
73
|
-
ServiceInstanceName: {{appName}}-auth
|
|
74
|
-
ServiceKeyName: {{appName}}-auth-key
|
|
75
|
-
sap.cloud.service: {{appName}}.service
|
|
76
|
-
|
|
77
51
|
resources:
|
|
78
52
|
{{#hasApprouter}}
|
|
79
53
|
- name: {{appName}}-html5-runtime
|
|
@@ -88,29 +62,3 @@ resources:
|
|
|
88
62
|
parameters:
|
|
89
63
|
service: html5-apps-repo
|
|
90
64
|
service-plan: app-host
|
|
91
|
-
|
|
92
|
-
- name: {{appName}}-destination
|
|
93
|
-
type: org.cloudfoundry.managed-service
|
|
94
|
-
parameters:
|
|
95
|
-
service: destination
|
|
96
|
-
service-plan: lite
|
|
97
|
-
config:
|
|
98
|
-
HTML5Runtime_enabled: true
|
|
99
|
-
init_data:
|
|
100
|
-
instance:
|
|
101
|
-
existing_destinations_policy: update
|
|
102
|
-
destinations:
|
|
103
|
-
- Name: {{appName}}-srv-api
|
|
104
|
-
URL: ~{srv-api/srv-url}
|
|
105
|
-
Authentication: NoAuthentication
|
|
106
|
-
Type: HTTP
|
|
107
|
-
ProxyType: Internet
|
|
108
|
-
HTML5.ForwardAuthToken: true
|
|
109
|
-
HTML5.DynamicDestination: true
|
|
110
|
-
requires:
|
|
111
|
-
- name: srv-api
|
|
112
|
-
group: destinations
|
|
113
|
-
properties:
|
|
114
|
-
name: srv-api # must be used in xs-app.json as well
|
|
115
|
-
url: ~{srv-url}
|
|
116
|
-
forwardAuthToken: true
|
|
@@ -4,24 +4,10 @@
|
|
|
4
4
|
{
|
|
5
5
|
"source": "^/?odata/(.*)$",
|
|
6
6
|
"target": "/odata/$1",
|
|
7
|
-
"destination": "
|
|
7
|
+
"destination": "srv-api",
|
|
8
8
|
{{#hasXsuaa}}"authenticationType": "xsuaa",{{/hasXsuaa}}
|
|
9
9
|
"csrfProtection": true
|
|
10
10
|
},
|
|
11
|
-
{{#hasUI5}}
|
|
12
|
-
{
|
|
13
|
-
"source": "^/resources/(.*)$",
|
|
14
|
-
"target": "/resources/$1",
|
|
15
|
-
"authenticationType": "none",
|
|
16
|
-
"destination": "ui5"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"source": "^/test-resources/(.*)$",
|
|
20
|
-
"target": "/test-resources/$1",
|
|
21
|
-
"authenticationType": "none",
|
|
22
|
-
"destination": "ui5"
|
|
23
|
-
},
|
|
24
|
-
{{/hasUI5}}
|
|
25
11
|
{
|
|
26
12
|
"source": "^(.*)$",
|
|
27
13
|
"target": "$1",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
3
|
const { merge } = require('../../merge')
|
|
4
|
-
const { srv4,
|
|
4
|
+
const { srv4, html5RepoHost, html5Runtime, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
|
|
5
5
|
|
|
6
6
|
module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
7
7
|
|
|
@@ -9,10 +9,6 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
9
9
|
return 'SAP BTP HTML5 Application Repository'
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
requires() {
|
|
13
|
-
return ['destination']
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
static hasInProduction(env) {
|
|
17
13
|
return !!env.requires['html5-repo']
|
|
18
14
|
}
|
|
@@ -47,13 +43,17 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
47
43
|
|
|
48
44
|
async combine() {
|
|
49
45
|
const project = readProject()
|
|
50
|
-
const { srvPath, appPath, hasMta, hasHelm, hasHelmUnifiedRuntime, hasApprouter, apps } = project
|
|
46
|
+
const { isJava, srvPath, appPath, hasMta, hasMultitenancy, hasHelm, hasHelmUnifiedRuntime, hasApprouter, apps } = project
|
|
51
47
|
|
|
52
48
|
await Promise.all(apps.map(async ({app}) => {
|
|
53
49
|
project.app = app
|
|
54
50
|
await merge(__dirname, 'files/xs-app.json.hbs').into(join(appPath, app, 'xs-app.json'), { project })
|
|
55
51
|
}))
|
|
56
52
|
|
|
53
|
+
if (hasMultitenancy) {
|
|
54
|
+
await merge(__dirname, 'files/package.sidecar.json').into('mtx/sidecar/package.json')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
57
|
if (hasMta) {
|
|
58
58
|
const srv = srv4(srvPath)
|
|
59
59
|
project.apps = apps
|
|
@@ -61,11 +61,8 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
61
61
|
in: 'modules',
|
|
62
62
|
where: { type: 'html5', path: `${appPath}${app.app}` }
|
|
63
63
|
}))
|
|
64
|
-
const additions = [srv, appDeployer,
|
|
64
|
+
const additions = [srv, appDeployer, html5RepoHost, ...appModules]
|
|
65
65
|
const relationships = [{
|
|
66
|
-
insert: [destination, 'name'],
|
|
67
|
-
into: [appDeployer, 'requires', 'name'],
|
|
68
|
-
}, {
|
|
69
66
|
insert: [html5RepoHost, 'name'],
|
|
70
67
|
into: [appDeployer, 'requires', 'name'],
|
|
71
68
|
}]
|
|
@@ -76,6 +73,12 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
76
73
|
into: [approuter, 'requires', 'name'],
|
|
77
74
|
})
|
|
78
75
|
}
|
|
76
|
+
if (hasMultitenancy) {
|
|
77
|
+
relationships.push({
|
|
78
|
+
insert: [html5Runtime, 'name'],
|
|
79
|
+
into: [mtxSidecar4(isJava ? 'mtx/sidecar' : 'gen/mtx/sidecar'), 'requires', 'name']
|
|
80
|
+
})
|
|
81
|
+
}
|
|
79
82
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project,
|
|
80
83
|
additions,
|
|
81
84
|
relationships
|
|
@@ -5,7 +5,7 @@ const { srv4, malwareScanner } = require('../../registries/mta')
|
|
|
5
5
|
module.exports = class MalwareScannerTemplate extends require('../../plugin') {
|
|
6
6
|
|
|
7
7
|
static help() {
|
|
8
|
-
return 'SAP Malware Scanning
|
|
8
|
+
return 'SAP Malware Scanning Service'
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
static hasInProduction(env) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
modules:
|
|
3
|
+
- name: {{appName}}-srv
|
|
4
|
+
type: {{language}}
|
|
5
|
+
path: {{& srvPath}}
|
|
6
|
+
requires:
|
|
7
|
+
- name: {{appName}}-redis
|
|
8
|
+
|
|
9
|
+
resources:
|
|
10
|
+
- name: {{appName}}-redis
|
|
11
|
+
type: org.cloudfoundry.managed-service
|
|
12
|
+
parameters:
|
|
13
|
+
service: redis-cache
|
|
14
|
+
service-plan: standard
|
|
15
|
+
# config:
|
|
16
|
+
# memory: 2 # GB, can be 2 or 4
|
|
17
|
+
# multi_az: true
|
|
18
|
+
# cluster_mode: true
|
|
19
|
+
# shard_count: 1
|
|
20
|
+
# node_count: 3 # per shard minimum is 3 (for standard plan)
|
|
21
|
+
# engine_version: "6.0" # can be "4.0" or "6.0"
|
|
22
|
+
# maintenance_window:
|
|
23
|
+
# day_of_week: Friday
|
|
24
|
+
# start_hour_utc: 0
|
|
25
|
+
# duration: 5 # hours
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const { readProject } = require('../../projectReader')
|
|
2
|
+
const { merge } = require('../../merge')
|
|
3
|
+
const { srv4, redis } = require('../../registries/mta')
|
|
4
|
+
|
|
5
|
+
module.exports = class extends require('../../plugin') {
|
|
6
|
+
|
|
7
|
+
static help() {
|
|
8
|
+
return 'SAP BTP Redis, Hyperscaler Option'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async canRun() {
|
|
12
|
+
const { hasMta, hasHelm, hasHelmUnifiedRuntime, isJava } = readProject()
|
|
13
|
+
const onlyHelm = !hasMta && (hasHelmUnifiedRuntime || hasHelm)
|
|
14
|
+
if (isJava) throw `'cds add redis' is not available for Java yet`
|
|
15
|
+
if (onlyHelm) throw `'cds add redis' is not available for Kyma yet`
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static hasInProduction() {
|
|
20
|
+
const { dependencies } = readProject()
|
|
21
|
+
return !!dependencies?.['redis']
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async run() {
|
|
25
|
+
await merge(__dirname, 'files/package.json.hbs').into('package.json')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async combine() {
|
|
29
|
+
const project = readProject()
|
|
30
|
+
const { hasMta, srvPath } = project
|
|
31
|
+
|
|
32
|
+
if (hasMta) {
|
|
33
|
+
const srv = srv4(srvPath)
|
|
34
|
+
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
35
|
+
project,
|
|
36
|
+
additions: [srv, redis],
|
|
37
|
+
relationships: [{
|
|
38
|
+
insert: [redis, 'name'],
|
|
39
|
+
into: [srv, 'requires', 'name']
|
|
40
|
+
}]
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -2,7 +2,6 @@ const cds = require('../../../cds')
|
|
|
2
2
|
const { read } = cds.utils
|
|
3
3
|
const { readProject } = require('../../projectReader')
|
|
4
4
|
const { merge } = require('../../merge')
|
|
5
|
-
const { srv4, redis } = require('../../registries/mta')
|
|
6
5
|
|
|
7
6
|
module.exports = class RedisMessagingTemplate extends require('../../plugin') {
|
|
8
7
|
|
|
@@ -10,6 +9,10 @@ module.exports = class RedisMessagingTemplate extends require('../../plugin') {
|
|
|
10
9
|
return 'messaging via Redis'
|
|
11
10
|
}
|
|
12
11
|
|
|
12
|
+
requires() {
|
|
13
|
+
return ['redis']
|
|
14
|
+
}
|
|
15
|
+
|
|
13
16
|
async canRun() {
|
|
14
17
|
const { hasMta, hasHelm, hasHelmUnifiedRuntime, isJava } = readProject()
|
|
15
18
|
const onlyHelm = !hasMta && (hasHelmUnifiedRuntime || hasHelm)
|
|
@@ -28,21 +31,4 @@ module.exports = class RedisMessagingTemplate extends require('../../plugin') {
|
|
|
28
31
|
project.shortcut = !(await read(configFile)).cds?.requires?.messaging?.kind
|
|
29
32
|
await merge(__dirname, 'files/package.json.hbs').into(configFile, { project })
|
|
30
33
|
}
|
|
31
|
-
|
|
32
|
-
async combine() {
|
|
33
|
-
const project = readProject()
|
|
34
|
-
const { hasMta, srvPath } = project
|
|
35
|
-
|
|
36
|
-
if (hasMta) {
|
|
37
|
-
const srv = srv4(srvPath)
|
|
38
|
-
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
39
|
-
project,
|
|
40
|
-
additions: [srv, redis],
|
|
41
|
-
relationships: [{
|
|
42
|
-
insert: [redis, 'name'],
|
|
43
|
-
into: [srv, 'requires', 'name']
|
|
44
|
-
}]
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
34
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
modules:
|
|
3
|
+
- name: {{appName}}-destinations
|
|
4
|
+
type: com.sap.application.content
|
|
5
|
+
requires:
|
|
6
|
+
- name: {{appName}}-auth
|
|
7
|
+
parameters:
|
|
8
|
+
service-key:
|
|
9
|
+
name: {{appName}}-auth-key
|
|
10
|
+
- name: {{appName}}-html5-repo-host
|
|
11
|
+
parameters:
|
|
12
|
+
service-key:
|
|
13
|
+
name: {{appName}}-html5-repo-host-key
|
|
14
|
+
- name: srv-api
|
|
15
|
+
- name: {{appName}}-destination
|
|
16
|
+
parameters:
|
|
17
|
+
content-target: true
|
|
18
|
+
build-parameters:
|
|
19
|
+
no-source: true
|
|
20
|
+
parameters:
|
|
21
|
+
content:
|
|
22
|
+
instance:
|
|
23
|
+
existing_destinations_policy: update
|
|
24
|
+
destinations:
|
|
25
|
+
- Name: {{appName}}-html5-repository
|
|
26
|
+
ServiceInstanceName: {{appName}}-html5-repo-host
|
|
27
|
+
ServiceKeyName: {{appName}}-html5-repo-host-key
|
|
28
|
+
sap.cloud.service: {{appName}}.service
|
|
29
|
+
- Name: {{appName}}-auth
|
|
30
|
+
Authentication: OAuth2UserTokenExchange
|
|
31
|
+
ServiceInstanceName: {{appName}}-auth
|
|
32
|
+
ServiceKeyName: {{appName}}-auth-key
|
|
33
|
+
sap.cloud.service: {{appName}}.service
|
|
34
|
+
|
|
35
|
+
- name: {{appName}}-destination
|
|
36
|
+
type: org.cloudfoundry.managed-service
|
|
37
|
+
parameters:
|
|
38
|
+
service: destination
|
|
39
|
+
service-plan: lite
|
|
40
|
+
config:
|
|
41
|
+
HTML5Runtime_enabled: true
|
|
42
|
+
init_data:
|
|
43
|
+
instance:
|
|
44
|
+
existing_destinations_policy: update
|
|
45
|
+
destinations:
|
|
46
|
+
- Name: {{appName}}-srv-api
|
|
47
|
+
URL: ~{srv-api/srv-url}
|
|
48
|
+
Authentication: NoAuthentication
|
|
49
|
+
Type: HTTP
|
|
50
|
+
ProxyType: Internet
|
|
51
|
+
HTML5.ForwardAuthToken: true
|
|
52
|
+
HTML5.DynamicDestination: true
|
|
53
|
+
requires:
|
|
54
|
+
- name: srv-api
|
|
55
|
+
group: destinations
|
|
56
|
+
properties:
|
|
57
|
+
name: srv-api # must be used in xs-app.json as well
|
|
58
|
+
url: ~{srv-url}
|
|
59
|
+
forwardAuthToken: true
|
|
@@ -2,22 +2,27 @@ const cds = require('../../../cds')
|
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
3
|
const { merge } = require('../../merge')
|
|
4
4
|
const { join } = require('path')
|
|
5
|
+
const { destination, destinations } = require('../../registries/mta')
|
|
5
6
|
|
|
6
7
|
module.exports = class extends require('../../plugin') {
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
throw `SAP BTP Work Zone, Standard Edition does not support multitenancy yet.`
|
|
11
|
-
}
|
|
12
|
-
return true
|
|
9
|
+
static help() {
|
|
10
|
+
return 'SAP BTP Work Zone, Standard Edition'
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
requires() {
|
|
16
|
-
return ['html5-repo']
|
|
14
|
+
return ['html5-repo', 'destination']
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
static
|
|
20
|
-
return
|
|
17
|
+
static hasInProduction(env) {
|
|
18
|
+
return !!env.requires?.workzone
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
canRun() {
|
|
22
|
+
if (cds.requires.multitenancy) {
|
|
23
|
+
throw `SAP BTP Work Zone, Standard Edition does not support multitenancy yet.`
|
|
24
|
+
}
|
|
25
|
+
return true
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
async run() {
|
|
@@ -26,5 +31,16 @@ module.exports = class extends require('../../plugin') {
|
|
|
26
31
|
await Promise.all(appUIPaths.map(p =>
|
|
27
32
|
merge(__dirname, 'files/manifest.json.hbs').into(join(appPath, p, 'webapp/manifest.json'), { project })
|
|
28
33
|
))
|
|
34
|
+
await merge({ cds: { requires: { workzone: true } } }).into('package.json')
|
|
29
35
|
}
|
|
36
|
+
|
|
37
|
+
async combine() {
|
|
38
|
+
const project = readProject()
|
|
39
|
+
const { hasMta } = project
|
|
40
|
+
|
|
41
|
+
if (hasMta) {
|
|
42
|
+
const additions = [destinations, destination]
|
|
43
|
+
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', { with: project, additions })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
30
46
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-dk",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@sap/cds-dk",
|
|
9
|
-
"version": "8.0.
|
|
9
|
+
"version": "8.0.3",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@cap-js/asyncapi": "^1.0.0",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"node_modules/@cap-js/asyncapi": {
|
|
38
|
-
"version": "1.0.
|
|
38
|
+
"version": "1.0.2",
|
|
39
39
|
"license": "SEE LICENSE IN LICENSE",
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@sap/cds": ">=7.
|
|
41
|
+
"@sap/cds": ">=7.6"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"node_modules/@cap-js/db-service": {
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
137
|
"node_modules/@eslint/js": {
|
|
138
|
-
"version": "9.
|
|
138
|
+
"version": "9.7.0",
|
|
139
139
|
"license": "MIT",
|
|
140
140
|
"engines": {
|
|
141
141
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
}
|
|
201
201
|
},
|
|
202
202
|
"node_modules/@sap/cds": {
|
|
203
|
-
"version": "8.0.
|
|
203
|
+
"version": "8.0.4",
|
|
204
204
|
"license": "SEE LICENSE IN LICENSE",
|
|
205
205
|
"dependencies": {
|
|
206
206
|
"@sap/cds-compiler": ">=5",
|
|
@@ -262,7 +262,7 @@
|
|
|
262
262
|
}
|
|
263
263
|
},
|
|
264
264
|
"node_modules/@sap/cds-mtxs": {
|
|
265
|
-
"version": "2.0.
|
|
265
|
+
"version": "2.0.3",
|
|
266
266
|
"license": "SEE LICENSE IN LICENSE",
|
|
267
267
|
"dependencies": {
|
|
268
268
|
"@sap/hdi-deploy": ">=4",
|
|
@@ -866,14 +866,14 @@
|
|
|
866
866
|
}
|
|
867
867
|
},
|
|
868
868
|
"node_modules/eslint": {
|
|
869
|
-
"version": "9.
|
|
869
|
+
"version": "9.7.0",
|
|
870
870
|
"license": "MIT",
|
|
871
871
|
"dependencies": {
|
|
872
872
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
873
|
-
"@eslint-community/regexpp": "^4.
|
|
873
|
+
"@eslint-community/regexpp": "^4.11.0",
|
|
874
874
|
"@eslint/config-array": "^0.17.0",
|
|
875
875
|
"@eslint/eslintrc": "^3.1.0",
|
|
876
|
-
"@eslint/js": "9.
|
|
876
|
+
"@eslint/js": "9.7.0",
|
|
877
877
|
"@humanwhocodes/module-importer": "^1.0.1",
|
|
878
878
|
"@humanwhocodes/retry": "^0.3.0",
|
|
879
879
|
"@nodelib/fs.walk": "^1.2.8",
|
|
@@ -882,7 +882,7 @@
|
|
|
882
882
|
"cross-spawn": "^7.0.2",
|
|
883
883
|
"debug": "^4.3.2",
|
|
884
884
|
"escape-string-regexp": "^4.0.0",
|
|
885
|
-
"eslint-scope": "^8.0.
|
|
885
|
+
"eslint-scope": "^8.0.2",
|
|
886
886
|
"eslint-visitor-keys": "^4.0.0",
|
|
887
887
|
"espree": "^10.1.0",
|
|
888
888
|
"esquery": "^1.5.0",
|
|
@@ -915,7 +915,7 @@
|
|
|
915
915
|
}
|
|
916
916
|
},
|
|
917
917
|
"node_modules/eslint-scope": {
|
|
918
|
-
"version": "8.0.
|
|
918
|
+
"version": "8.0.2",
|
|
919
919
|
"license": "BSD-2-Clause",
|
|
920
920
|
"dependencies": {
|
|
921
921
|
"esrecurse": "^4.3.0",
|
|
@@ -2015,7 +2015,7 @@
|
|
|
2015
2015
|
"license": "ISC"
|
|
2016
2016
|
},
|
|
2017
2017
|
"node_modules/semver": {
|
|
2018
|
-
"version": "7.6.
|
|
2018
|
+
"version": "7.6.3",
|
|
2019
2019
|
"license": "ISC",
|
|
2020
2020
|
"bin": {
|
|
2021
2021
|
"semver": "bin/semver.js"
|
|
@@ -2301,7 +2301,7 @@
|
|
|
2301
2301
|
}
|
|
2302
2302
|
},
|
|
2303
2303
|
"node_modules/uglify-js": {
|
|
2304
|
-
"version": "3.
|
|
2304
|
+
"version": "3.19.0",
|
|
2305
2305
|
"license": "BSD-2-Clause",
|
|
2306
2306
|
"optional": true,
|
|
2307
2307
|
"bin": {
|
package/package.json
CHANGED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
modules:
|
|
3
|
-
- name: {{appName}}-srv
|
|
4
|
-
type: {{language}}
|
|
5
|
-
path: {{& srvPath}}
|
|
6
|
-
requires:
|
|
7
|
-
- name: {{appName}}-redis
|
|
8
|
-
|
|
9
|
-
resources:
|
|
10
|
-
- name: {{appName}}-redis
|
|
11
|
-
type: org.cloudfoundry.managed-service
|
|
12
|
-
parameters:
|
|
13
|
-
service: redis-cache
|
|
14
|
-
service-plan: default
|