@sap/cds-dk 6.8.3 → 7.0.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/bin/activate.js +15 -7
- package/bin/add.js +29 -15
- package/bin/bind.js +49 -116
- package/bin/build.js +114 -0
- package/bin/cds.js +67 -24
- package/bin/compile/index.js +2 -2
- package/bin/deploy/index.js +46 -39
- package/bin/deploy/to-hana.js +11 -8
- package/bin/deploy/to-postgres.js +8 -2
- package/bin/deploy/to-sqlite.js +0 -1
- package/bin/env.js +75 -41
- package/bin/eval.js +3 -3
- package/bin/extend.js +17 -10
- package/bin/help.js +22 -21
- package/bin/import.js +10 -7
- package/bin/init.js +38 -17
- package/bin/login.js +69 -55
- package/bin/logout.js +12 -9
- package/bin/migrate.js +10 -4
- package/bin/pull.js +12 -5
- package/bin/push.js +24 -13
- package/bin/repl.js +1 -0
- package/bin/run.js +25 -0
- package/bin/subscribe.js +13 -8
- package/bin/unsubscribe.js +15 -8
- package/bin/upgrade.js +15 -9
- package/bin/util/log.js +24 -0
- package/bin/version.js +124 -0
- package/bin/watch.js +1 -35
- package/bin/watched.js +39 -0
- package/lib/bind/KubernetesApiAccessor.js +2 -2
- package/lib/bind/bindingManager.js +1 -1
- package/lib/bind/bindingUtil.js +0 -9
- package/lib/bind/cfKeyProvider.js +10 -72
- package/lib/bind/index.js +114 -0
- package/lib/bind/kubernetesCredentialsProvider.js +2 -2
- package/lib/bind/userCdsrcJsonStorageProvider.js +7 -44
- package/lib/build/buildTaskEngine.js +355 -0
- package/lib/build/buildTaskFactory.js +284 -0
- package/lib/build/buildTaskHandler.js +240 -0
- package/lib/build/buildTaskProvider.js +22 -0
- package/lib/build/buildTaskProviderFactory.js +182 -0
- package/lib/build/constants.js +56 -0
- package/lib/build/index.js +21 -0
- package/lib/build/provider/buildTaskHandlerEdmx.js +83 -0
- package/lib/build/provider/buildTaskHandlerFeatureToggles.js +132 -0
- package/lib/build/provider/buildTaskHandlerInternal.js +228 -0
- package/lib/build/provider/buildTaskProviderInternal.js +370 -0
- package/lib/build/provider/fiori/index.js +167 -0
- package/lib/build/provider/hana/2migration.js +179 -0
- package/lib/build/provider/hana/index.js +522 -0
- package/lib/build/provider/hana/migrationtable.js +472 -0
- package/lib/build/provider/hana/template/.hdiconfig-all +163 -0
- package/lib/build/provider/hana/template/.hdiconfig-cloud +137 -0
- package/lib/build/provider/hana/template/.hdinamespace +4 -0
- package/lib/build/provider/hana/template/package.json +12 -0
- package/lib/build/provider/hana/template/undeploy.json +5 -0
- package/lib/build/provider/java/index.js +93 -0
- package/lib/build/provider/java-cf/index.js +1 -0
- package/lib/build/provider/mtx/index.js +37 -0
- package/lib/build/provider/mtx/resourcesTarBuilder.js +94 -0
- package/lib/build/provider/mtx-extension/index.js +131 -0
- package/lib/build/provider/mtx-sidecar/index.js +138 -0
- package/lib/build/provider/node-cf/index.js +1 -0
- package/lib/build/provider/nodejs/index.js +178 -0
- package/lib/build/util.js +263 -0
- package/lib/cds.js +9 -21
- package/lib/client/auth_manager.js +39 -16
- package/lib/client/helper/dependency_helper.js +7 -6
- package/lib/client/push.js +2 -1
- package/lib/client/settings_manager.js +10 -39
- package/lib/deploy/to-hana/hana.js +273 -0
- package/lib/deploy/to-hana/hdiDeployUtil.js +68 -0
- package/lib/deploy/to-hana/mtaUtil.js +171 -0
- package/lib/import/asyncapi/importAsyncAPI.js +3 -2
- package/lib/import/asyncapi/index.js +5 -2
- package/lib/import/asyncapi/parserContext.js +67 -26
- package/lib/import/asyncapi/utils.js +34 -3
- package/lib/import/common.js +40 -30
- package/lib/import/importapi.js +36 -35
- package/lib/index.js +12 -17
- package/lib/init/constants.js +36 -71
- package/lib/init/index.js +18 -52
- package/lib/init/template/_merging/registry-mta.js +21 -3
- package/lib/init/template/approuter/files/mta.yaml.hbs +29 -29
- package/lib/init/template/approuter/files/values.yaml.hbs +5 -5
- package/lib/init/template/approuter/files/xs-app.json.hbs +8 -2
- package/lib/init/template/approuter/index.js +7 -8
- package/lib/init/template/auditlog/files/mta.yaml.hbs +5 -5
- package/lib/init/template/auditlog/files/package.json.hbs +13 -13
- package/lib/init/template/auditlog/index.js +3 -3
- package/lib/init/template/cf-manifest/files/manifest.yml.hbs +22 -22
- package/lib/init/template/cf-manifest/files/services-manifest.yml.hbs +3 -3
- package/lib/init/template/connectivity/files/mta.yaml.hbs +14 -0
- package/lib/init/template/connectivity/files/package.json.hbs +17 -0
- package/lib/init/template/connectivity/index.js +21 -4
- package/lib/init/template/data/index.js +5 -1
- package/lib/init/template/destination/files/mta.yaml.hbs +14 -0
- package/lib/init/template/destination/files/package.json.hbs +17 -0
- package/lib/init/template/{destinations → destination}/index.js +19 -13
- package/lib/init/template/enterprise-messaging/files/event-mesh.json.hbs +3 -3
- package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/enterprise-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/enterprise-messaging/files/xs-security.json.hbs +19 -0
- package/lib/init/template/enterprise-messaging/index.js +27 -6
- package/lib/init/template/enterprise-messaging-shared/files/event-mesh.json.hbs +3 -3
- package/lib/init/template/enterprise-messaging-shared/files/mta.yaml.hbs +5 -5
- package/lib/init/template/enterprise-messaging-shared/files/package.json.hbs +9 -9
- package/lib/init/template/enterprise-messaging-shared/index.js +4 -5
- package/lib/init/template/extensibility/files/package.json.hbs +10 -10
- package/lib/init/template/extensibility/index.js +8 -9
- package/lib/init/template/file-based-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/file-based-messaging/index.js +3 -4
- package/lib/init/template/hana/files/db/package.json +1 -1
- package/lib/init/template/hana/files/mta.yaml.hbs +21 -21
- package/lib/init/template/hana/files/package.json.hbs +16 -22
- package/lib/init/template/hana/files/values.yaml.hbs +1 -1
- package/lib/init/template/hana/index.js +5 -15
- package/lib/init/template/helm/files/Chart.yaml.hbs +4 -4
- package/lib/init/template/helm/files/values.yaml.hbs +6 -6
- package/lib/init/template/helm/index.js +5 -10
- package/lib/init/template/helm/subcharts/content-deployment/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/content-deployment/templates/_helpers.tpl +37 -31
- package/lib/init/template/helm/subcharts/content-deployment/templates/job.yaml +13 -14
- package/lib/init/template/helm/subcharts/content-deployment/templates/secret.yaml +2 -2
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-account.yaml +1 -1
- package/lib/init/template/helm/subcharts/content-deployment/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/content-deployment/values.md +116 -116
- package/lib/init/template/helm/subcharts/service-instance/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/service-instance/templates/_helpers.tpl +9 -9
- package/lib/init/template/helm/subcharts/service-instance/templates/serviceinstance.yaml +2 -2
- package/lib/init/template/helm/subcharts/service-instance/values.md +15 -15
- package/lib/init/template/helm/subcharts/web-application/Chart.yaml +2 -0
- package/lib/init/template/helm/subcharts/web-application/templates/NOTES.txt +15 -0
- package/lib/init/template/helm/subcharts/web-application/templates/_helpers.tpl +23 -23
- package/lib/init/template/helm/subcharts/web-application/templates/api-rule.yaml +4 -4
- package/lib/init/template/helm/subcharts/web-application/templates/deployment.yaml +17 -17
- package/lib/init/template/helm/subcharts/web-application/templates/network-policy.yaml +24 -3
- package/lib/init/template/helm/subcharts/web-application/templates/pod-disruption-budget.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/templates/secret.yaml +2 -2
- package/lib/init/template/helm/subcharts/web-application/templates/service-account.yaml +1 -1
- package/lib/init/template/helm/subcharts/web-application/templates/service-binding.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/templates/service.yaml +3 -3
- package/lib/init/template/helm/subcharts/web-application/values.md +141 -123
- package/lib/init/template/helm/subcharts/web-application/values.schema.json +7 -0
- package/lib/init/template/helm/subcharts/web-application/values.yaml +1 -0
- package/lib/init/template/html5-repo/index.js +4 -5
- package/lib/init/template/java/index.js +5 -5
- package/lib/init/template/kibana-logging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/kibana-logging/files/package.json.hbs +9 -9
- package/lib/init/template/kibana-logging/index.js +3 -4
- package/lib/init/template/lint/index.js +3 -3
- package/lib/init/template/mta/files/mta.yaml.hbs +14 -14
- package/lib/init/template/mta/files/package.json +5 -0
- package/lib/init/template/mta/index.js +12 -13
- package/lib/init/template/mtx/index.js +2 -2
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +29 -27
- package/lib/init/template/multitenancy/files/package.json.hbs +17 -14
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -7
- package/lib/init/template/multitenancy/files/values.yaml.hbs +19 -19
- package/lib/init/template/multitenancy/index.js +14 -16
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/template/nodejs/index.js +5 -8
- package/lib/init/template/redis-messaging/files/mta.yaml.hbs +5 -5
- package/lib/init/template/redis-messaging/files/package.json.hbs +9 -9
- package/lib/init/template/redis-messaging/index.js +4 -5
- package/lib/init/template/sample/files/app/_i18n/i18n.properties +43 -0
- package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +14 -0
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +114 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +8 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +11 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +129 -0
- package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +57 -0
- package/lib/init/template/sample/files/app/common.cds +263 -0
- package/lib/init/template/sample/files/app/index.html +30 -0
- package/lib/init/template/sample/files/app/services.cds +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +6 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books_texts.csv +5 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +16 -0
- package/lib/init/template/sample/files/db/schema.cds +31 -0
- package/lib/init/template/sample/files/nodejs/admin-service.js +12 -0
- package/lib/init/template/sample/files/nodejs/cat-service.js +26 -0
- package/lib/init/template/sample/files/srv/admin-service.cds +5 -0
- package/lib/init/template/sample/files/srv/cat-service.cds +16 -0
- package/lib/init/template/sample/index.js +24 -0
- package/lib/init/template/sample-tiny/index.js +39 -0
- package/lib/init/template/samples/index.js +5 -56
- package/lib/init/template/sqlite/files/package.json.hbs +13 -13
- package/lib/init/template/sqlite/index.js +2 -2
- package/lib/init/template/templateBase.js +24 -1
- package/lib/init/template/toggles/files/package.json.hbs +10 -10
- package/lib/init/template/toggles/index.js +3 -3
- package/lib/init/template/typer/files/gitignore +1 -0
- package/lib/init/template/typer/files/package.json +8 -0
- package/lib/init/template/typer/files/xsconfig.json +9 -0
- package/lib/init/template/typer/index.js +36 -0
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +12 -12
- package/lib/init/template/xsuaa/files/package.json.hbs +13 -13
- package/lib/init/template/xsuaa/files/values.yaml.hbs +8 -8
- package/lib/init/template/xsuaa/index.js +8 -19
- package/lib/init/util/merge.js +73 -59
- package/lib/init/util/mvn.js +21 -17
- package/lib/init/util/projectReader.js +49 -87
- package/lib/init/util/xml.js +14 -23
- package/lib/util/cfUtil.js +366 -0
- package/lib/util/command.js +3 -3
- package/lib/util/gitUtil.js +55 -0
- package/lib/util/version.js +27 -0
- package/npm-shrinkwrap.json +337 -275
- package/package.json +6 -6
- package/CHANGELOG.md +0 -1460
- package/bin/build/all.js +0 -88
- package/bin/build/index.js +0 -82
- package/lib/compile/index.js +0 -14
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data/my.bookshop-Books.csv +0 -0
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/db/data-model.cds +0 -0
- /package/lib/init/template/{samples → sample-tiny}/files/nodejs/srv/cat-service.cds.hbs +0 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const cds = require('../../cds')
|
|
4
|
+
const { hasJavaNature, getDefaultModelOptions, BuildError, hasOptionValue } = require('../util')
|
|
5
|
+
const BuildTaskProvider = require('../buildTaskProvider')
|
|
6
|
+
|
|
7
|
+
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,
|
|
8
|
+
BUILD_TASK_PREFIX, BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION, NODEJS_MODEL_EXCLUDE_LIST,
|
|
9
|
+
DEFAULT_BUILT_IN_MODELS } = require("../constants")
|
|
10
|
+
|
|
11
|
+
class BuildTaskProviderInternal extends BuildTaskProvider {
|
|
12
|
+
constructor(logger) {
|
|
13
|
+
super()
|
|
14
|
+
this._logger = logger
|
|
15
|
+
}
|
|
16
|
+
get logger() {
|
|
17
|
+
return this._logger
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
canHandleTask(task) {
|
|
21
|
+
return BUILD_TASKS.includes(task.for)
|
|
22
|
+
|| task.use && task.use.startsWith(BUILD_TASK_PREFIX)
|
|
23
|
+
// support different build task implementations of the same build task ID defined by 'for'
|
|
24
|
+
//return (BUILD_TASKS.includes(task.for) && !task.use) || (task.use && task.use.startsWith(BUILD_TASK_PREFIX))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
loadHandler(task) {
|
|
28
|
+
return require(`./${BuildTaskProviderInternal._getForValueFromTask(task)}`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async lookupTasks(tasks) {
|
|
32
|
+
return this._createTasks(tasks, tasks.length > 0)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async applyTaskDefaults(task) {
|
|
36
|
+
const taskFor = BuildTaskProviderInternal._getForValueFromTask(task)
|
|
37
|
+
task.for = task.for || taskFor
|
|
38
|
+
task.use = task.use || `${BUILD_TASK_PREFIX}/${taskFor}`
|
|
39
|
+
|
|
40
|
+
// src folder needs to be initialized first
|
|
41
|
+
BuildTaskProviderInternal._setDefaultSrcFolder(task)
|
|
42
|
+
|
|
43
|
+
BuildTaskProviderInternal._setDefaultModel(task)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async _createTasks(tasks, addRequiredTasks) {
|
|
47
|
+
let db = typeof cds.env.folders.db === "string" ? [BuildTaskProviderInternal._normalizePath(cds.env.folders.db)] : cds.env.folders.db
|
|
48
|
+
let srv = typeof cds.env.folders.srv === "string" ? [BuildTaskProviderInternal._normalizePath(cds.env.folders.srv)] : cds.env.folders.srv
|
|
49
|
+
|
|
50
|
+
const dbOptions = {
|
|
51
|
+
model: []
|
|
52
|
+
}
|
|
53
|
+
const srvOptions = {
|
|
54
|
+
model: []
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(db) && db.length > 0) {
|
|
57
|
+
db = BuildTaskProviderInternal._getModuleFolder(db) || null
|
|
58
|
+
if (!db && !addRequiredTasks) { // log once
|
|
59
|
+
this.logger.debug("No database module found")
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (Array.isArray(srv) && srv.length > 0) {
|
|
63
|
+
srv = BuildTaskProviderInternal._getModuleFolder(srv) || null
|
|
64
|
+
if (!srv && !addRequiredTasks) { // log once
|
|
65
|
+
this.logger.debug("No service module found")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// create required build tasks
|
|
69
|
+
if (addRequiredTasks) {
|
|
70
|
+
const mtxTask = tasks.find(task => task.for === BUILD_TASK_MTX || task.for === BUILD_TASK_MTX_SIDECAR)
|
|
71
|
+
if (mtxTask) {
|
|
72
|
+
//restore used tasks as they might have been filtered by 'cds build --for mtx'
|
|
73
|
+
if (mtxTask._uses) {
|
|
74
|
+
mtxTask._uses.map(use => use.task).forEach(task => {
|
|
75
|
+
if (!tasks.includes(task)) {
|
|
76
|
+
tasks.push(task)
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
let dbTask = tasks.find(task => task.for === BUILD_TASK_HANA)
|
|
81
|
+
if (!dbTask) {
|
|
82
|
+
// db task might be missing if mtx task is enforced by 'cds build --for mtx'
|
|
83
|
+
dbTask = this._createDbTask(db, dbOptions)
|
|
84
|
+
if (dbTask) {
|
|
85
|
+
tasks.push(dbTask)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (dbTask && (!mtxTask._uses || !mtxTask._uses.map(use => use.task).includes(dbTask))) {
|
|
89
|
+
const use = { task: dbTask }
|
|
90
|
+
mtxTask._uses ? mtxTask._uses.push(use) : mtxTask._uses = [use]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
!db && this.logger._debug && this.logger.debug(`project doesn't have a database module '${cds.env.folders.db}'`)
|
|
95
|
+
!srv && this.logger._debug && this.logger.debug(`project doesn't have a service module '${cds.env.folders.srv}'`)
|
|
96
|
+
|
|
97
|
+
// create hana build task
|
|
98
|
+
const dbTask = this._createDbTask(db, dbOptions)
|
|
99
|
+
if (dbTask) {
|
|
100
|
+
tasks.push(dbTask)
|
|
101
|
+
}
|
|
102
|
+
// create java or node build task
|
|
103
|
+
const srvTask = this._createSrvTask(srv, srvOptions)
|
|
104
|
+
if (srvTask) {
|
|
105
|
+
tasks.push(srvTask)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// create mtx build task
|
|
109
|
+
const mtxTask = this._createMtxTask(srv, tasks)
|
|
110
|
+
if (mtxTask) {
|
|
111
|
+
tasks.push(mtxTask)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
_createDbTask(src, taskOptions) {
|
|
117
|
+
this.logger.debug("determining database kind")
|
|
118
|
+
if (!src || BuildTaskProviderInternal._isMtxExtension()) {
|
|
119
|
+
return null
|
|
120
|
+
}
|
|
121
|
+
let task = null
|
|
122
|
+
if (this._useHana()) {
|
|
123
|
+
this.logger.debug("found HANA database")
|
|
124
|
+
// legacy build supports dest property
|
|
125
|
+
const compileDest = cds.env.data?.dest
|
|
126
|
+
if (compileDest) {
|
|
127
|
+
//../db/src/gen
|
|
128
|
+
// compileDest is relative to src folder in modular build - resolve correctly
|
|
129
|
+
taskOptions.compileDest = path.relative(path.resolve(cds.root, src), path.resolve(cds.root, compileDest))
|
|
130
|
+
}
|
|
131
|
+
task = {
|
|
132
|
+
src: src,
|
|
133
|
+
for: BUILD_TASK_HANA,
|
|
134
|
+
options: taskOptions
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
this.logger.debug("found sqlite database - skipping HANA build task")
|
|
138
|
+
}
|
|
139
|
+
return task
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
_useHana() {
|
|
143
|
+
if (cds.env.requires.db?.kind === "hana" || cds.env.requires.db?.dialect === "hana") {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
// false if other db has been defined
|
|
147
|
+
if (cds.env.requires.db?.kind) {
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
150
|
+
// check whether cds config represents a legacy build system config for which requires.db was not configured
|
|
151
|
+
// Note: compat layer sets requires.db: {}
|
|
152
|
+
const userEnv = cds.env.for("cds", cds.root, false)
|
|
153
|
+
return userEnv && (userEnv.data?.model || userEnv.service?.model)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
_createMtxTask(src, tasks) {
|
|
157
|
+
this.logger.debug("determining MTX architecture")
|
|
158
|
+
|
|
159
|
+
// preserve order of creation
|
|
160
|
+
if (BuildTaskProviderInternal._isMtxExtension()) {
|
|
161
|
+
this.logger.debug("MTX extension app")
|
|
162
|
+
return { for: BUILD_TASK_MTX_EXTENSION }
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (BuildTaskProviderInternal._isMtxs()) {
|
|
166
|
+
const sidecarPath = path.join(cds.root, MTX_SIDECAR_FOLDER)
|
|
167
|
+
let sidecarEnv
|
|
168
|
+
if (fs.existsSync(sidecarPath)) {
|
|
169
|
+
sidecarEnv = cds.env.for("cds", sidecarPath)
|
|
170
|
+
}
|
|
171
|
+
if (
|
|
172
|
+
cds.env.profiles?.includes('with-mtx-sidecar') || // new presets
|
|
173
|
+
cds.env.requires["cds.xt.ModelProviderService"]?.external // for compatibility with former mtxs presets
|
|
174
|
+
) {
|
|
175
|
+
this.logger.debug("MTX app with sidecar")
|
|
176
|
+
if (!sidecarEnv) {
|
|
177
|
+
throw new BuildError(`MTX sidecar directory '${sidecarPath}' not existing. Custom build task configuration required if the folder is named differently.`)
|
|
178
|
+
}
|
|
179
|
+
if (!sidecarEnv.requires["cds.xt.ModelProviderService"]?._in_sidecar) {
|
|
180
|
+
// correct profile might have been set, but couldn't be resolved
|
|
181
|
+
if (sidecarEnv.profiles?.includes('mtx-sidecar')) {
|
|
182
|
+
throw new BuildError('MTX configuration cannot be resolved. Make sure an up-to-date version of @sap/cds-mtxs is installed.')
|
|
183
|
+
}
|
|
184
|
+
throw new BuildError(`Invalid MTX sidecar configuration - profile 'mtx-sidecar' not set.`)
|
|
185
|
+
}
|
|
186
|
+
return { for: BUILD_TASK_MTX_SIDECAR }
|
|
187
|
+
}
|
|
188
|
+
if (sidecarEnv?.requires["cds.xt.ModelProviderService"]?._in_sidecar || sidecarEnv?.profiles?.includes('mtx-sidecar')) {
|
|
189
|
+
throw new BuildError(`MTX sidecar requires profile 'with-mtx-sidecar' in project root configuration.`)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (cds.env.requires["cds.xt.ModelProviderService"]?._in_sidecar || cds.env.profiles?.includes('mtx-sidecar')) {
|
|
193
|
+
// cds build is executed in sidecar folder
|
|
194
|
+
throw new BuildError(`Seems that you are executing 'cds build' in the 'mtx/sidecar' folder. Execute 'cds build' in the project root folder instead.`)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// mtxs with nodejs, but without sidecar
|
|
198
|
+
if (!tasks.some(task => task.for === BUILD_TASK_JAVA || task.for === BUILD_TASK_JAVA_CF)) {
|
|
199
|
+
this.logger.debug("MTX app without sidecar")
|
|
200
|
+
return {
|
|
201
|
+
for: BUILD_TASK_MTX,
|
|
202
|
+
src
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
_createSrvTask(src, taskOptions) {
|
|
209
|
+
this.logger.debug("determining implementation technology")
|
|
210
|
+
if (!src || BuildTaskProviderInternal._isMtxExtension()) {
|
|
211
|
+
return null
|
|
212
|
+
}
|
|
213
|
+
let task = null
|
|
214
|
+
if (BuildTaskProviderInternal._hasJavaNature(src)) {
|
|
215
|
+
task = this._createJavaTask(src, taskOptions)
|
|
216
|
+
} else {
|
|
217
|
+
task = this._createNodeTask(src, taskOptions)
|
|
218
|
+
}
|
|
219
|
+
return task
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
_createJavaTask(src, taskOptions) {
|
|
223
|
+
this.logger.debug("found implementation technology Java")
|
|
224
|
+
// legacy build supports dest property
|
|
225
|
+
const compileDest = cds.env.service?.dest
|
|
226
|
+
if (compileDest) {
|
|
227
|
+
// compileDest is relative to src folder in modular build - resolve correctly
|
|
228
|
+
taskOptions.compileDest = path.relative(path.resolve(cds.root, src), path.resolve(cds.root, compileDest))
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
src: src,
|
|
232
|
+
for: BUILD_TASK_JAVA,
|
|
233
|
+
options: taskOptions
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
_createNodeTask(src, taskOptions) {
|
|
238
|
+
this.logger.debug("found implementation technology Nodejs")
|
|
239
|
+
return {
|
|
240
|
+
src: src,
|
|
241
|
+
for: BUILD_TASK_NODEJS,
|
|
242
|
+
options: taskOptions
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
static _isMtxExtension() {
|
|
247
|
+
return !!cds.env.extends
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Distinguishes whether the Nodejs project is a Streamlined MTX (cds >=6) or an old MTX project.
|
|
252
|
+
*/
|
|
253
|
+
static _isMtxs() {
|
|
254
|
+
return cds.env.requires.toggles
|
|
255
|
+
|| cds.env.profiles.includes('with-mtx-sidecar')
|
|
256
|
+
|| cds.env.requires['cds.xt.ModelProviderService']
|
|
257
|
+
|| (typeof cds.env.requires.multitenancy === "object")
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static _setDefaultSrcFolder(task) {
|
|
261
|
+
switch (task.for) {
|
|
262
|
+
case BUILD_TASK_HANA:
|
|
263
|
+
task.src = task.src || this._normalizePath(cds.env.folders.db)
|
|
264
|
+
break
|
|
265
|
+
case BUILD_TASK_JAVA:
|
|
266
|
+
case BUILD_TASK_JAVA_CF:
|
|
267
|
+
case BUILD_TASK_NODEJS:
|
|
268
|
+
case BUILD_TASK_NODE_CF:
|
|
269
|
+
task.src = task.src || this._normalizePath(cds.env.folders.srv)
|
|
270
|
+
break
|
|
271
|
+
case BUILD_TASK_FIORI:
|
|
272
|
+
task.src = task.src || this._normalizePath(cds.env.folders.app)
|
|
273
|
+
break
|
|
274
|
+
case BUILD_TASK_MTX_SIDECAR:
|
|
275
|
+
task.src = task.src || MTX_SIDECAR_FOLDER
|
|
276
|
+
break
|
|
277
|
+
case BUILD_TASK_MTX_EXTENSION:
|
|
278
|
+
task.src = task.src || "."
|
|
279
|
+
break
|
|
280
|
+
case BUILD_TASK_MTX:
|
|
281
|
+
require('../../util/version').checkMtx(cds)
|
|
282
|
+
// mtxs with nodejs, but without sidecar
|
|
283
|
+
task.src = task.src || this._normalizePath(cds.env.folders.srv)
|
|
284
|
+
break
|
|
285
|
+
default:
|
|
286
|
+
throw new Error(`Unknown build task '${task.use || task.for}'`)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
static _setDefaultModel(task) {
|
|
291
|
+
let taskModelPaths = task.options?.model
|
|
292
|
+
if (taskModelPaths && !Array.isArray(taskModelPaths)) {
|
|
293
|
+
taskModelPaths = [taskModelPaths]
|
|
294
|
+
}
|
|
295
|
+
task.options = task.options || {}
|
|
296
|
+
let defaultModelPaths = []
|
|
297
|
+
// add default models to custom build tasks if this hasn't been disabled
|
|
298
|
+
if (taskModelPaths?.length) {
|
|
299
|
+
if (!hasOptionValue(task.options?.[DEFAULT_BUILT_IN_MODELS], false)) {
|
|
300
|
+
// get the built-in models
|
|
301
|
+
defaultModelPaths = getDefaultModelOptions().filter(p => p.match('@sap/cds'))
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
defaultModelPaths = getDefaultModelOptions()
|
|
305
|
+
defaultModelPaths.push(task.src)
|
|
306
|
+
if (hasOptionValue(task.options?.[DEFAULT_BUILT_IN_MODELS], false)) {
|
|
307
|
+
// all default models except the built-in models
|
|
308
|
+
defaultModelPaths = defaultModelPaths.filter(p => !p.match('@sap/cds'))
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// REVISIT: filter nodejs bootstrap service models for Java - issues/12770#issuecomment-1805719
|
|
313
|
+
if (this._hasJavaNature(cds.env.folders.srv)) {
|
|
314
|
+
defaultModelPaths = defaultModelPaths.filter(p => !NODEJS_MODEL_EXCLUDE_LIST.includes(p))
|
|
315
|
+
}
|
|
316
|
+
// also add built-in models to custom build tasks already containing model options
|
|
317
|
+
if (!taskModelPaths || defaultModelPaths.length) {
|
|
318
|
+
task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(defaultModelPaths) : defaultModelPaths)]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Returns whether this project is a java project or not.
|
|
324
|
+
* @param {string} srv - the folder name of the service module
|
|
325
|
+
*/
|
|
326
|
+
static _hasJavaNature(srv) {
|
|
327
|
+
srv = this._getModuleFolder(Array.isArray(srv) ? srv : [srv])
|
|
328
|
+
return hasJavaNature([cds.root, srv && path.join(cds.root, srv)])
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
static _getForValueFromTask(task) {
|
|
332
|
+
return task.for ? task.for : task.use && task.use.substring(BUILD_TASK_PREFIX.length + 1)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* For valid paths remove trailing '/'. Otherwise return as is - important!!
|
|
337
|
+
* @param {*} dir
|
|
338
|
+
*/
|
|
339
|
+
static _normalizePath(dir) {
|
|
340
|
+
return typeof dir === "string" ? dir.replace(/\/$/, '') : dir
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Determines the module folder from the past list that may represent files or folders w or w/o .cds file extension.
|
|
345
|
+
* @param {Array} filesOrFolders
|
|
346
|
+
*/
|
|
347
|
+
static _getModuleFolder(filesOrFolders) {
|
|
348
|
+
const resources = [...filesOrFolders]
|
|
349
|
+
filesOrFolders.forEach(fileOrFolder => {
|
|
350
|
+
if (path.extname(fileOrFolder) !== FILE_EXT_CDS) {
|
|
351
|
+
resources.push(fileOrFolder + FILE_EXT_CDS)
|
|
352
|
+
}
|
|
353
|
+
})
|
|
354
|
+
return resources.reduce((acc, resource) => {
|
|
355
|
+
if (!acc) {
|
|
356
|
+
let resourcePath = path.resolve(cds.root, resource)
|
|
357
|
+
if (fs.existsSync(resourcePath)) {
|
|
358
|
+
if (fs.lstatSync(resourcePath).isDirectory()) {
|
|
359
|
+
acc = resource
|
|
360
|
+
} else {
|
|
361
|
+
// represents file
|
|
362
|
+
acc = path.dirname(resource)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return acc
|
|
367
|
+
}, null)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
module.exports = BuildTaskProviderInternal
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const cds = require('../../../cds')
|
|
3
|
+
const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
4
|
+
const URL = require('url')
|
|
5
|
+
const { getProperty, relativePaths } = require('../../util')
|
|
6
|
+
|
|
7
|
+
const { OUTPUT_MODE, OUTPUT_MODE_RESULT, BUILD_TASK_FIORI, CDS_CONFIG_PATH_SEP, OUTPUT_MODE_FILESYSTEM } = require('../../constants')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* With cds 4 service metadata for the UI service binding is no longer created by default.
|
|
11
|
+
* For SAP Web IDE Full-Stack compatibility a corresponding metadata.xml is still generated.
|
|
12
|
+
* Though, 'fiori' build tasks can still be configured for UI5 mock server usage - see https://github.wdf.sap.corp/cap/issues/issues/8673
|
|
13
|
+
*/
|
|
14
|
+
class FioriAppModuleBuilder extends BuildTaskHandlerEdmx {
|
|
15
|
+
init() {
|
|
16
|
+
// enforce
|
|
17
|
+
this._result = {
|
|
18
|
+
dest: this.task.dest,
|
|
19
|
+
edmx: new Map(),
|
|
20
|
+
languages: new Set(),
|
|
21
|
+
services: new Set()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async prepare() {
|
|
26
|
+
this.context.for = this.context.for || {}
|
|
27
|
+
this.context.for[BUILD_TASK_FIORI] = this.context.for[BUILD_TASK_FIORI] || {}
|
|
28
|
+
|
|
29
|
+
// cache for later use across multiple FioriAppModuleBuilder instances
|
|
30
|
+
const fioriBuildOptions = this.context.for[BUILD_TASK_FIORI]
|
|
31
|
+
fioriBuildOptions.appModel = new Map()
|
|
32
|
+
fioriBuildOptions.appEdmx = new Map()
|
|
33
|
+
|
|
34
|
+
// group tasks that have a common application root folder
|
|
35
|
+
const appTaskGroups = new Map()
|
|
36
|
+
this.context.tasks.forEach(task => {
|
|
37
|
+
if (task.for === BUILD_TASK_FIORI) {
|
|
38
|
+
const appFolder = path.relative(cds.root, task.src).split(CDS_CONFIG_PATH_SEP)[0]
|
|
39
|
+
appTaskGroups.has(appFolder) ? appTaskGroups.get(appFolder).push(task) : appTaskGroups.set(appFolder, [task])
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// merge all model references to resolve the model later on
|
|
44
|
+
const appModelGroups = new Map()
|
|
45
|
+
for (let [appFolder, appTaskGroup] of appTaskGroups.entries()) {
|
|
46
|
+
const appModels = new Set()
|
|
47
|
+
appTaskGroup.forEach(task => {
|
|
48
|
+
if (Array.isArray(task.options.model)) {
|
|
49
|
+
task.options.model.forEach(model => appModels.add(model))
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
appModelGroups.set(appFolder, appModels)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const originFioriBuildOption = fioriBuildOptions[OUTPUT_MODE]
|
|
56
|
+
fioriBuildOptions[OUTPUT_MODE] = OUTPUT_MODE_RESULT
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const edmxOptions = { version: cds.env.odata?.version }
|
|
60
|
+
for (let [appFolder, appModelGroup] of appModelGroups.entries()) {
|
|
61
|
+
this.logger.debug(`building module [${appFolder}] using [${this.constructor.name}]`)
|
|
62
|
+
const modelPaths = cds.resolve(Array.from(appModelGroup.values()))
|
|
63
|
+
if (!modelPaths || modelPaths.length === 0) {
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
this.logger._debug && this.logger.debug(`model: ${relativePaths(cds.root, modelPaths).join(", ")}`)
|
|
67
|
+
|
|
68
|
+
//cache model per fiori app root folder
|
|
69
|
+
const options = this.options()
|
|
70
|
+
const model = await cds.load(modelPaths, options)
|
|
71
|
+
fioriBuildOptions.appModel.set(appFolder, model)
|
|
72
|
+
|
|
73
|
+
await this.compileToEdmx(model, null, edmxOptions)
|
|
74
|
+
|
|
75
|
+
// cache edmx per fiori app root folder
|
|
76
|
+
fioriBuildOptions.appEdmx.set(appFolder, this._result.edmx)
|
|
77
|
+
}
|
|
78
|
+
} finally {
|
|
79
|
+
fioriBuildOptions[OUTPUT_MODE] = originFioriBuildOption
|
|
80
|
+
}
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* This version only creates a odata representation for the 'mainService' data source
|
|
86
|
+
* as defined by the fiori wizard - everything else is currently not supported.
|
|
87
|
+
* Therefore errors are only logged, the build does not fail in case a service
|
|
88
|
+
* cannot be resolved based on the defined service URI
|
|
89
|
+
*/
|
|
90
|
+
async build() {
|
|
91
|
+
const model = await this.model()
|
|
92
|
+
if (!model) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
await this._writeEdmxToWebapp(this.task.src, this.task.dest)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async _writeEdmxToWebapp(src, dest) {
|
|
99
|
+
const manifestPath = path.join(src, 'webapp', 'manifest.json')
|
|
100
|
+
let manifest
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
manifest = require(manifestPath)
|
|
104
|
+
} catch (error) {
|
|
105
|
+
this.logger.log(`UI module does not contain a manifest.json [${relativePaths(cds.root, manifestPath)}], skipping build`)
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const mainService = getProperty(manifest, ['sap.app', 'dataSources', 'mainService'])
|
|
110
|
+
if (!mainService) {
|
|
111
|
+
// no mainService defined - not supported
|
|
112
|
+
this.logger._debug && this.logger.debug(`UI module does not have a datasource [mainService], [${relativePaths(cds.root, manifestPath)}], skipping build`)
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const localUri = getProperty(mainService, ['settings', 'localUri'])
|
|
117
|
+
const uri = mainService.uri
|
|
118
|
+
|
|
119
|
+
if (!localUri || !uri) {
|
|
120
|
+
this.logger._debug && this.logger.warn(`local uri setting missing for data source [mainService], [${relativePaths(cds.root, manifestPath)}]`)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const appFolder = path.relative(cds.root, src).split(CDS_CONFIG_PATH_SEP)[0]
|
|
125
|
+
const model = this.context.for[BUILD_TASK_FIORI].appModel.get(appFolder)
|
|
126
|
+
if (!model) {
|
|
127
|
+
this.logger.error(`failed to load model for service uri ${uri}, data source [mainService]`)
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const edmx = this._getEdmxForUri(model, appFolder, uri)
|
|
132
|
+
if (!edmx) {
|
|
133
|
+
this.logger.error(`failed to resolve service definition for service uri ${uri}, data source [mainService]`)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
|
|
138
|
+
const edmxPath = path.resolve(path.join(dest, 'webapp'), this._strippedUrlPath(localUri))
|
|
139
|
+
return this.write(edmx).to(edmxPath)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
_getEdmxForUri(model, appFolder, uri) {
|
|
144
|
+
const uriSegments = this._strippedUrlPath(uri).split('/')
|
|
145
|
+
|
|
146
|
+
// one segment of the URI has to match a service name
|
|
147
|
+
// NOTE: assumption is that the service definition can be resolved - either by
|
|
148
|
+
// - defining corresponding using statement in annotations model or
|
|
149
|
+
// - adding the service module folder to the model option
|
|
150
|
+
let service = cds.reflect(model).find(service => uriSegments.find(segment => service.name === segment))
|
|
151
|
+
|
|
152
|
+
if (service) {
|
|
153
|
+
const allServices = this.context.for[BUILD_TASK_FIORI].appEdmx.get(appFolder)
|
|
154
|
+
if (allServices) {
|
|
155
|
+
return allServices.get(service.name + ".xml")
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return null
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
_strippedUrlPath(urlString) {
|
|
162
|
+
const url = URL.parse(urlString)
|
|
163
|
+
return url.pathname.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = FioriAppModuleBuilder
|