@sap/cds-dk 6.8.2 → 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 +339 -277
- package/package.json +6 -6
- package/CHANGELOG.md +0 -1453
- 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,178 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const cds = require('../../../cds')
|
|
4
|
+
const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
5
|
+
const { BuildError } = require('../../util')
|
|
6
|
+
const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTENT_EDMX,
|
|
7
|
+
CONTENT_PACKAGELOCK_JSON, CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON } = require('../../constants')
|
|
8
|
+
const { WARNING } = BuildTaskHandlerEdmx
|
|
9
|
+
|
|
10
|
+
class NodejsModuleBuilder extends BuildTaskHandlerEdmx {
|
|
11
|
+
init() {
|
|
12
|
+
super.init()
|
|
13
|
+
if (this.task.options.compileDest) {
|
|
14
|
+
throw new BuildError("Option not supported - compileDest")
|
|
15
|
+
}
|
|
16
|
+
// fallback if src has been defined as '.'
|
|
17
|
+
this.destSrv = this.isStagingBuild() ? path.resolve(this.task.dest, cds.env.folders.srv) : path.join(this.task.dest, FOLDER_GEN)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
options() {
|
|
21
|
+
const options = super.options()
|
|
22
|
+
if (cds.env.requires.extensibility || cds.env.requires.toggles) {
|
|
23
|
+
options.flavor = 'xtended'
|
|
24
|
+
}
|
|
25
|
+
return options
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async build() {
|
|
29
|
+
const destSrv = this.isStagingBuild() ? this.destSrv : path.resolve(this.destSrv, cds.env.folders.srv)
|
|
30
|
+
const destRoot = this.isStagingBuild() ? this.task.dest : this.destSrv
|
|
31
|
+
|
|
32
|
+
if (cds.env.odata?.version === ODATA_VERSION_V2) {
|
|
33
|
+
// log warning as nodejs is only supporting odata version V4
|
|
34
|
+
this.pushMessage("OData v2 is not supported by node runtime. Make sure to define OData v2 in cds configuration.", WARNING)
|
|
35
|
+
}
|
|
36
|
+
// by default model contains all features
|
|
37
|
+
const model = await this.model()
|
|
38
|
+
if (!model) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const { dictionary, sources } = await this.compileAll(model, destSrv, destRoot)
|
|
43
|
+
|
|
44
|
+
// collect and write language bundles into single i18n.json file
|
|
45
|
+
await this.collectAllLanguageBundles(dictionary, sources, destSrv, destRoot)
|
|
46
|
+
|
|
47
|
+
if (this.hasBuildOption(CONTENT_EDMX, true)) {
|
|
48
|
+
const m = await cds.load(sources.base, super.options()) // REVISIT: Quick hack to get inferred model as expected by cds.compile.to.edmx()
|
|
49
|
+
await this.compileToEdmx(m, this.destSrv)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (this.isStagingBuild() && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
|
|
53
|
+
const srcSrv = this.task.src === cds.root ? path.resolve(this.task.src, cds.env.folders.srv) : this.task.src
|
|
54
|
+
await this._copyNativeContent(cds.root, srcSrv, destRoot)
|
|
55
|
+
await this._fixCapireSamplesDeps(destRoot)
|
|
56
|
+
}
|
|
57
|
+
return this._result
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// REVISIT: fix for capire samples - needs to be reworked
|
|
61
|
+
// Instead of adding relative paths we may better delete the entire entry as relative paths
|
|
62
|
+
// cannot be resolved in cloud deployments anyway.
|
|
63
|
+
// Support for HANA native artifacts defined in sub-modules required
|
|
64
|
+
async _fixCapireSamplesDeps(dest) {
|
|
65
|
+
const packageJson = path.join(dest, 'package.json')
|
|
66
|
+
try {
|
|
67
|
+
const content = require(packageJson)
|
|
68
|
+
const { dependencies } = content
|
|
69
|
+
let changed
|
|
70
|
+
for (let dependency in dependencies) {
|
|
71
|
+
if (dependency.startsWith('@capire/')) {
|
|
72
|
+
dependencies[dependency] = path.relative(dest, path.dirname(require.resolve(dependency + '/package.json')))
|
|
73
|
+
changed = true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (changed) {
|
|
77
|
+
return this.write(JSON.stringify(content, null, ' ')).to(packageJson)
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {/*ignore*/ }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async clean() {
|
|
83
|
+
// staging build content is deleted by BuildTaskEngine
|
|
84
|
+
if (cds.env.build.target === '.') {
|
|
85
|
+
// delete the entire 'task.dest' folder otherwise, for details see #constructor
|
|
86
|
+
// - the value of the folder 'src' has been appended to the origin 'task.dest' dir
|
|
87
|
+
this.logger._debug && this.logger.debug(`Deleting build target folder ${this.destSrv}`)
|
|
88
|
+
await fs.promises.rm(this.isStagingBuild() ? this.task.dest : this.destSrv, { force: true, recursive: true })
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async _copyNativeContent(srcRoot, srcSrv, destRoot) {
|
|
93
|
+
// project/srv/** -> 'gen/srv/srv/**'
|
|
94
|
+
const filesFilter = await this._copySrvContent(srcSrv, destRoot)
|
|
95
|
+
|
|
96
|
+
// project/* -> 'gen/srv/*'
|
|
97
|
+
await this.copyProjectRootContent(srcRoot, destRoot, (entry) => !filesFilter.includes(path.basename(entry)))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Copy files for nodejs staging builds from the given <em>src</em>' folder (e.g. 'project/srv') to either <em>destRoot</em> (e.g. 'project/gen/srv')
|
|
102
|
+
* or <em>destSrv</em> (e.g. 'project/gen/srv/srv') folders according to the file semantics.
|
|
103
|
+
* Files with project semantics like 'package.json' or '.npmrc' file are copied to <em>destRoot</em> while others like '.js' service handlers
|
|
104
|
+
* are copied to <em>destSrv</em>.
|
|
105
|
+
* @param {*} src
|
|
106
|
+
* @param {*} destRoot - folder name representing the app root folder (e.g. gen/srv)
|
|
107
|
+
* @returns the list of files that have been copied
|
|
108
|
+
*/
|
|
109
|
+
async _copySrvContent(src, destRoot) {
|
|
110
|
+
const srvRootBlockList = RegExp('package\\.json$|package-lock\\.json$|\\.npmrc$|\\.cdsrc\\.json$')
|
|
111
|
+
const srvBlockList = RegExp('\\.cds$|csn\\.json$|\\.csn$|manifest\\.y.?ml$|\\.env($|\\..*$)|default-env\\.json$')
|
|
112
|
+
const srvRootFileNames = []
|
|
113
|
+
|
|
114
|
+
// 1. copy all files to 'destSrv' except those contained in the blocklist (including node_modules)
|
|
115
|
+
// project/srv -> 'gen/srv/srv'
|
|
116
|
+
await super.copyNativeContent(src, destRoot, (entry) => {
|
|
117
|
+
if (fs.statSync(entry).isDirectory()) {
|
|
118
|
+
// TODO shall not copy language bundles - return !/(\/|\\)(node_modules|_i18n)(\/|\\)?$/.test(entry)
|
|
119
|
+
return !/(\/|\\)node_modules(\/|\\)?$/.test(entry)
|
|
120
|
+
}
|
|
121
|
+
// make sure the file exists on srv root level - see https://github.tools.sap/cap/issues/issues/12077
|
|
122
|
+
if (srvRootBlockList.test(entry) && path.dirname(entry) === src) {
|
|
123
|
+
srvRootFileNames.push(path.basename(entry))
|
|
124
|
+
return false
|
|
125
|
+
}
|
|
126
|
+
return !srvBlockList.test(entry)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// 2. copy dedicated files like package.json, .npmrc to 'destRoot'
|
|
130
|
+
// project/srv -> 'gen/srv'
|
|
131
|
+
let srvAllowList = "package\\.json$" // always copy package.json, modify only if CONTENT_PACKAGE_JSON is true
|
|
132
|
+
srvAllowList += !this.hasBuildOption(CONTENT_PACKAGELOCK_JSON, false) ? "|package-lock\\.json$" : ""
|
|
133
|
+
srvAllowList += !this.hasBuildOption(CONTENT_NPMRC, false) ? "|\\.npmrc$" : ""
|
|
134
|
+
srvAllowList += !this.hasBuildOption(CONTENT_CDSRC_JSON, false) ? "|\\.cdsrc\\.json$" : ""
|
|
135
|
+
srvAllowList += this.hasBuildOption(CONTENT_ENV, true) ? "|\\.env($|\\..*$)" : ""
|
|
136
|
+
srvAllowList += this.hasBuildOption(CONTENT_DEFAULT_ENV_JSON, true) ? "|default-env\\.json$" : ""
|
|
137
|
+
srvAllowList = new RegExp(srvAllowList)
|
|
138
|
+
await Promise.all(srvRootFileNames.map(fileName => {
|
|
139
|
+
if (srvAllowList.test(fileName)) {
|
|
140
|
+
return this.copy(path.join(src, fileName)).to(path.join(destRoot, fileName))
|
|
141
|
+
}
|
|
142
|
+
}))
|
|
143
|
+
|
|
144
|
+
return srvRootFileNames
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Copy dedicated files (files with project semantics like package.json, .npmrc, .cdsrc, etc.)
|
|
149
|
+
* from the given <em>src</em> folder (e.g. 'project') into the given <em>dest</em> folder (e.g. 'project/gen/srv')
|
|
150
|
+
* @param {*} src
|
|
151
|
+
* @param {*} dest
|
|
152
|
+
* @param {*} filter - copy file if filter function returns true
|
|
153
|
+
*/
|
|
154
|
+
async copyProjectRootContent(src, dest, filter) {
|
|
155
|
+
let { folders = ['i18n'] } = cds.env.i18n
|
|
156
|
+
folders.push('handlers')
|
|
157
|
+
folders = folders.map(folder => path.join(src, folder))
|
|
158
|
+
let srvAllowList = "package\\.json$" // always copy package.json, modify only if CONTENT_PACKAGE_JSON is true
|
|
159
|
+
srvAllowList += !this.hasBuildOption(CONTENT_PACKAGELOCK_JSON, false) ? "|package-lock\\.json$" : ""
|
|
160
|
+
srvAllowList += !this.hasBuildOption(CONTENT_NPMRC, false) ? "|\\.npmrc$" : ""
|
|
161
|
+
srvAllowList += !this.hasBuildOption(CONTENT_CDSRC_JSON, false) ? "|\\.cdsrc\\.json$" : ""
|
|
162
|
+
srvAllowList += this.hasBuildOption(CONTENT_ENV, true) ? "|\\.env($|\\..*$)" : ""
|
|
163
|
+
srvAllowList += this.hasBuildOption(CONTENT_DEFAULT_ENV_JSON, true) ? "|default-env\\.json$" : ""
|
|
164
|
+
srvAllowList = new RegExp(srvAllowList)
|
|
165
|
+
|
|
166
|
+
await super.copyNativeContent(src, dest, (entry) => {
|
|
167
|
+
if (fs.statSync(entry).isDirectory()) {
|
|
168
|
+
return folders.some(folder => entry.startsWith(folder))
|
|
169
|
+
}
|
|
170
|
+
if (/\.js$|\.properties$/.test(entry)) {
|
|
171
|
+
return true
|
|
172
|
+
}
|
|
173
|
+
return srvAllowList.test(entry) && (!filter || filter.call(this, entry))
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
module.exports = NodejsModuleBuilder
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const cds = require('../cds')
|
|
4
|
+
const { SEVERITY_ERROR, FILE_EXT_CDS } = require('./constants')
|
|
5
|
+
|
|
6
|
+
function getProperty(src, segments) {
|
|
7
|
+
segments = Array.isArray(segments) ? segments : segments.split('.')
|
|
8
|
+
return segments.reduce((p, n) => p && p[n], src)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function setProperty(src, segments, value) {
|
|
12
|
+
segments = Array.isArray(segments) ? segments : segments.split('.')
|
|
13
|
+
segments.reduce((p, n, idx) => {
|
|
14
|
+
if (segments.length === idx + 1) {
|
|
15
|
+
p[n] = value
|
|
16
|
+
} else {
|
|
17
|
+
if (p[n] === undefined) {
|
|
18
|
+
p[n] = {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return p[n]
|
|
22
|
+
}, src)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Returns whether this project is a java project or not.
|
|
27
|
+
* @param {Array} dirs - the absolute path names to check.
|
|
28
|
+
*/
|
|
29
|
+
function hasJavaNature(dirs) {
|
|
30
|
+
return dirs.flat().reduce((acc, dir) => {
|
|
31
|
+
if (dir) {
|
|
32
|
+
const file = path.join(dir, 'pom.xml')
|
|
33
|
+
if (fs.existsSync(file)) {
|
|
34
|
+
acc.push(file)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return acc
|
|
38
|
+
}, []).length > 0
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Determines whether the both values are identical.
|
|
43
|
+
* @param {*} actual
|
|
44
|
+
* @param {*} expected
|
|
45
|
+
*/
|
|
46
|
+
function hasOptionValue(actual, expected) {
|
|
47
|
+
if (typeof expected === 'undefined') {
|
|
48
|
+
return actual !== undefined
|
|
49
|
+
}
|
|
50
|
+
if (typeof actual === 'undefined') {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
if (typeof expected === 'boolean') {
|
|
54
|
+
if (typeof actual === 'string') {
|
|
55
|
+
return String(expected) === actual
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (typeof expected === 'number') {
|
|
59
|
+
return (actual & expected) !== 0
|
|
60
|
+
}
|
|
61
|
+
return actual === expected
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Returning the project relative path representation of the given path(s),
|
|
65
|
+
function relativePaths(root, qualifiedPaths) {
|
|
66
|
+
qualifiedPaths = typeof qualifiedPaths === "string" ? [qualifiedPaths] : qualifiedPaths
|
|
67
|
+
if (Array.isArray(qualifiedPaths)) {
|
|
68
|
+
return qualifiedPaths.map(qualifiedPath => {
|
|
69
|
+
const relPath = path.relative(root, qualifiedPath)
|
|
70
|
+
return relPath || "."
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
return qualifiedPaths
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function redactCredentials(config, o) {
|
|
77
|
+
return JSON.stringify(config, (k, v) => {
|
|
78
|
+
if (!v) {
|
|
79
|
+
return v
|
|
80
|
+
}
|
|
81
|
+
if (k === 'credentials') {
|
|
82
|
+
try {
|
|
83
|
+
return _redacted(v)
|
|
84
|
+
} catch (e) {/* ignored */ }
|
|
85
|
+
}
|
|
86
|
+
return v
|
|
87
|
+
}, o && o.indents || 2)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** redacts password-like strings, also reducing clutter in output */
|
|
91
|
+
function _redacted(cred) {
|
|
92
|
+
const secrets = /(password)|(certificate)|(ca)/i // 'certificate' and 'ca' on HANA
|
|
93
|
+
const newCred = Object.assign({}, cred)
|
|
94
|
+
Object.keys(newCred)
|
|
95
|
+
.filter(k => typeof newCred[k] === 'string' && secrets.test(k))
|
|
96
|
+
.forEach(k => newCred[k] = '...')
|
|
97
|
+
return newCred
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Returns a list of fully qualified model names belonging to the '@sap' namespace that cannot be resolved.
|
|
103
|
+
* E.g. the module might NOT have been installed.
|
|
104
|
+
* @param {Array} modelPaths
|
|
105
|
+
* @returns {Array}
|
|
106
|
+
*/
|
|
107
|
+
function resolveRequiredSapModels(modelPaths) {
|
|
108
|
+
return Array.isArray(modelPaths) && modelPaths.filter(p => {
|
|
109
|
+
if (p.startsWith('@sap/')) {
|
|
110
|
+
const files = cds.resolve(p)
|
|
111
|
+
return !files || files.length === 0
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getDefaultModelOptions() {
|
|
117
|
+
const fts = cds.env.features.folders
|
|
118
|
+
const modelPaths = cds.resolve(!fts ? '*' : ['*', fts], false)
|
|
119
|
+
return _pushModelPaths(modelPaths)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function _pushModelPaths(...modelPaths) {
|
|
123
|
+
const model = new Set()
|
|
124
|
+
// may contain nested arrays
|
|
125
|
+
modelPaths = flatten(modelPaths)
|
|
126
|
+
const { roots } = cds.env
|
|
127
|
+
modelPaths.forEach(m => {
|
|
128
|
+
if (m && !model.has(m) && !model.has(m + "/")) {
|
|
129
|
+
// filter root model paths that do not exist
|
|
130
|
+
// other entries are added as is, e.g. reuse model entries
|
|
131
|
+
if (roots.includes(m)) {
|
|
132
|
+
const dir = path.resolve(cds.root, m)
|
|
133
|
+
if (fs.existsSync(dir)) {
|
|
134
|
+
model.add(m.replace(/\/$/, ''))
|
|
135
|
+
} else if (fs.existsSync(dir + FILE_EXT_CDS)) { //might be cds file name, compatibility to old build configs
|
|
136
|
+
model.add(m)
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
model.add(m)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
return [...model]
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function flatten(modelPaths) {
|
|
147
|
+
return modelPaths.reduce((acc, m) => {
|
|
148
|
+
if (Array.isArray(m)) {
|
|
149
|
+
acc = acc.concat(flatten(m))
|
|
150
|
+
} else if (m) {
|
|
151
|
+
acc.push(m)
|
|
152
|
+
}
|
|
153
|
+
return acc
|
|
154
|
+
}, [])
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Copy a file or directory. The directory can have contents.
|
|
159
|
+
* REVISIT: 'fs.promises.cp' replacement for nodejs 14
|
|
160
|
+
* @param src <String> Note that if src is a directory it will copy everything inside of this directory, not the entire directory itself.
|
|
161
|
+
* @param dest <String> Note that if src is a file, dest cannot be a directory.
|
|
162
|
+
*/
|
|
163
|
+
async function copy(src, dest) {
|
|
164
|
+
if ((await fs.promises.stat(src)).isDirectory()) {
|
|
165
|
+
const entries = await fs.promises.readdir(src)
|
|
166
|
+
return Promise.all(entries.map(async each => copy(path.join(src, each), path.join(dest, each))))
|
|
167
|
+
} else {
|
|
168
|
+
await fs.promises.mkdir(path.dirname(dest), { recursive: true })
|
|
169
|
+
return fs.promises.copyFile(src, dest)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Return gnu-style error string for location `loc`:
|
|
175
|
+
* - 'File:Line:Col' without `loc.end`
|
|
176
|
+
* - 'File:Line:StartCol-EndCol' if Line = start.line = end.line
|
|
177
|
+
* - 'File:StartLine.StartCol-EndLine.EndCol' otherwise
|
|
178
|
+
*
|
|
179
|
+
* @param {CSN.Location|CSN.Location} location
|
|
180
|
+
*/
|
|
181
|
+
function _locationString(loc) {
|
|
182
|
+
if (!loc)
|
|
183
|
+
return '<???>';
|
|
184
|
+
if (!(loc instanceof Object))
|
|
185
|
+
return loc;
|
|
186
|
+
if (!loc.line) {
|
|
187
|
+
return loc.file;
|
|
188
|
+
}
|
|
189
|
+
else if (!loc.endLine) {
|
|
190
|
+
return (loc.col)
|
|
191
|
+
? `${loc.file}:${loc.line}:${loc.col}`
|
|
192
|
+
: `${loc.file}:${loc.line}`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return (loc.line === loc.endLine)
|
|
196
|
+
? `${loc.file}:${loc.line}:${loc.col}-${loc.endCol}`
|
|
197
|
+
: `${loc.file}:${loc.line}.${loc.col}-${loc.endLine}.${loc.endCol}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Class for individual build message.
|
|
202
|
+
*
|
|
203
|
+
* @class BuildMessage
|
|
204
|
+
*/
|
|
205
|
+
class BuildMessage {
|
|
206
|
+
/**
|
|
207
|
+
* Creates an instance of BuildMessage.
|
|
208
|
+
* @param {string} message The message text
|
|
209
|
+
* @param {string} [severity='Error'] Severity: Debug, Info, Warning, Error
|
|
210
|
+
* @param {any} location Location of the message
|
|
211
|
+
*
|
|
212
|
+
* @memberOf BuildMessage
|
|
213
|
+
*/
|
|
214
|
+
constructor(message, severity = SEVERITY_ERROR, location) {
|
|
215
|
+
this.message = message
|
|
216
|
+
this.name = "BuildMessage"
|
|
217
|
+
this.severity = severity
|
|
218
|
+
this.$location = location
|
|
219
|
+
}
|
|
220
|
+
toString() {
|
|
221
|
+
return `${this.$location?.file ? _locationString(this.$location) + ':' : ''} ${this.severity}: ${this.message}`
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Class for combined build and compiler errors.
|
|
227
|
+
* Additional members:
|
|
228
|
+
* messages: vector of detailed build messages
|
|
229
|
+
* @class BuildError
|
|
230
|
+
* @extends {Error}
|
|
231
|
+
*/
|
|
232
|
+
class BuildError extends Error {
|
|
233
|
+
constructor(message, messages = []) {
|
|
234
|
+
super(message)
|
|
235
|
+
this.name = "BuildError"
|
|
236
|
+
this.messages = Array.isArray(messages) ? messages : [messages]
|
|
237
|
+
this.stack = ""
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// for compatibility reasons
|
|
241
|
+
get errors() {
|
|
242
|
+
return this.messages
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
toString() {
|
|
246
|
+
return this.message + (this.messages.length > 0 ? '\n' + this.messages.map(m => m.toString()).join('\n') : '')
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
module.exports = {
|
|
251
|
+
getProperty,
|
|
252
|
+
setProperty,
|
|
253
|
+
hasJavaNature,
|
|
254
|
+
redactCredentials,
|
|
255
|
+
hasOptionValue,
|
|
256
|
+
relativePaths,
|
|
257
|
+
resolveRequiredSapModels,
|
|
258
|
+
getDefaultModelOptions,
|
|
259
|
+
flatten,
|
|
260
|
+
copy,
|
|
261
|
+
BuildMessage,
|
|
262
|
+
BuildError
|
|
263
|
+
}
|
package/lib/cds.js
CHANGED
|
@@ -1,27 +1,15 @@
|
|
|
1
|
-
const _local = id => require(_resolve(id))
|
|
2
|
-
|
|
3
1
|
/** @type { import('@sap/cds/lib') } */
|
|
4
|
-
const cds =
|
|
5
|
-
|
|
6
|
-
// for internal use in cds-dk only
|
|
7
|
-
cds._log = _local ('@sap/cds/bin/utils/log')
|
|
8
|
-
cds._local = _local
|
|
2
|
+
const cds = _local ('@sap/cds')
|
|
9
3
|
|
|
10
|
-
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
value: function cds_debug_patched (module, options) {
|
|
16
|
-
const L = cds.log (module, options)
|
|
17
|
-
if (L._debug) return L.debug
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
}
|
|
4
|
+
module.exports = Object.defineProperties (cds, {
|
|
5
|
+
// for internal use in cds-dk only
|
|
6
|
+
_log: { value: _local ('../bin/util/log') },
|
|
7
|
+
_local: { value: _local },
|
|
8
|
+
})
|
|
21
9
|
|
|
22
|
-
function
|
|
23
|
-
return require.resolve (id, {paths:[
|
|
10
|
+
function _local (id) {
|
|
11
|
+
return require(require.resolve (id, {paths:[
|
|
24
12
|
process.cwd(), // project-local module is preferred
|
|
25
13
|
__dirname // otherwise from our own dependencies
|
|
26
|
-
]})
|
|
14
|
+
]}))
|
|
27
15
|
}
|
|
@@ -22,21 +22,35 @@ function addTokenInfo(params, authData) {
|
|
|
22
22
|
function addUrlInfo(params, authData) {
|
|
23
23
|
params.set('passcodeUrl', authData.passcode_url);
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
function* reqParams(params) {
|
|
26
|
+
const url = params.get('tokenUrl');
|
|
27
|
+
const d = {};
|
|
28
|
+
if (params.has('subdomain')) {
|
|
29
|
+
d.subdomain = params.get('subdomain');
|
|
30
|
+
}
|
|
29
31
|
if (params.has('refreshToken')) {
|
|
30
|
-
|
|
32
|
+
d.refresh_token = params.get('refreshToken');
|
|
31
33
|
} else if (params.has('passcode')) {
|
|
32
|
-
|
|
34
|
+
d.passcode = params.get('passcode');
|
|
33
35
|
}
|
|
34
36
|
if (params.has('clientsecret')) {
|
|
35
|
-
|
|
37
|
+
d.clientid = params.get('clientid');
|
|
38
|
+
d.clientsecret = params.get('clientsecret');
|
|
36
39
|
} else if (params.has('key')) {
|
|
37
|
-
|
|
40
|
+
d.clientid = params.get('clientid');
|
|
41
|
+
d.key = params.get('key');
|
|
38
42
|
}
|
|
39
|
-
|
|
43
|
+
const data = new URLSearchParams(d).toString();
|
|
44
|
+
yield {
|
|
45
|
+
method: 'post',
|
|
46
|
+
url,
|
|
47
|
+
data
|
|
48
|
+
};
|
|
49
|
+
yield {
|
|
50
|
+
method: 'get',
|
|
51
|
+
url: `${url}?${data}`,
|
|
52
|
+
data: undefined
|
|
53
|
+
};
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
async function retrieveTokenOrPasscodeUrl(params) {
|
|
@@ -56,14 +70,23 @@ async function retrieveTokenOrPasscodeUrl(params) {
|
|
|
56
70
|
let retry;
|
|
57
71
|
let authData;
|
|
58
72
|
do {
|
|
59
|
-
const tokenUrl = getTokenUrl(params);
|
|
60
|
-
DEBUG?.(`Getting authentication token or passcode URL from ${(params.obfuscateQueryParams(tokenUrl))}`);
|
|
61
|
-
|
|
62
73
|
let response;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
for (const { method, url, data } of reqParams(params)) {
|
|
75
|
+
try {
|
|
76
|
+
DEBUG?.(`Getting authentication token or passcode URL from ${method.toUpperCase()} ${(params.obfuscateQueryParams(url))}`);
|
|
77
|
+
response = await axios[method](url, data);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error.response?.status === 404) { // may represent 405 in case of wrong method
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
throw new CliError('Failed to get authentication token', { error });
|
|
83
|
+
}
|
|
84
|
+
if (response) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!response) {
|
|
89
|
+
throw new CliError('Failed to get authentication token');
|
|
67
90
|
}
|
|
68
91
|
authData = response.data;
|
|
69
92
|
|
|
@@ -4,16 +4,17 @@ const { execFileSync } = require('child_process');
|
|
|
4
4
|
const cds = require('../../cds');
|
|
5
5
|
const DEBUG = cds.debug('cli');
|
|
6
6
|
|
|
7
|
-
let
|
|
7
|
+
let modulesDir;
|
|
8
8
|
|
|
9
9
|
function globalModulesDir() {
|
|
10
|
-
if (!
|
|
11
|
-
|
|
10
|
+
if (!modulesDir) {
|
|
11
|
+
modulesDir = execFileSync('npm', ['root', '-g'], {
|
|
12
12
|
encoding: 'utf8',
|
|
13
|
-
shell: os.platform() === 'win32'
|
|
13
|
+
shell: os.platform() === 'win32',
|
|
14
|
+
stdio: ['ignore', 'pipe', 'ignore']
|
|
14
15
|
}).trim();
|
|
15
16
|
}
|
|
16
|
-
return
|
|
17
|
+
return modulesDir;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
function requireGlobal(packageId) {
|
|
@@ -27,7 +28,7 @@ function requireGlobal(packageId) {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
function resetCache() {
|
|
30
|
-
|
|
31
|
+
modulesDir = undefined;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
module.exports = {
|
package/lib/client/push.js
CHANGED
|
@@ -7,6 +7,7 @@ const { login } = require('./auth_manager');
|
|
|
7
7
|
const BaseCommand = require('./base_command');
|
|
8
8
|
const { CliError } = require('./helper/errors');
|
|
9
9
|
const { schemaRegex } = require('./helper/url_helper');
|
|
10
|
+
const buildSystem = require('../build')
|
|
10
11
|
|
|
11
12
|
module.exports = class Push extends BaseCommand {
|
|
12
13
|
|
|
@@ -17,7 +18,7 @@ module.exports = class Push extends BaseCommand {
|
|
|
17
18
|
|
|
18
19
|
if (!('extArchive' in pushOptions)) {
|
|
19
20
|
console.log(`Building project`);
|
|
20
|
-
await
|
|
21
|
+
await buildSystem.build();
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const { src, content } = await this.readSource(params, pushOptions);
|