@sap/cds-dk 9.3.2 → 9.4.2
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 +59 -0
- package/bin/bind.js +1 -1
- package/bin/cds.js +3 -0
- package/bin/compile/index.js +53 -3
- package/bin/data-products/get-csn-via-dp-cli.js +41 -0
- package/bin/data-products/get-csn.js +76 -0
- package/bin/data-products/import.js +114 -0
- package/bin/data-products/index.js +30 -0
- package/bin/data-products/merge-csns.js +46 -0
- package/bin/data-products/prepare-csn.js +282 -0
- package/bin/data-products/prepare-files.js +69 -0
- package/bin/export.js +240 -0
- package/bin/help/export.md +37 -0
- package/bin/help/import.md +11 -0
- package/bin/help/minify.md +23 -0
- package/bin/import.js +13 -3
- package/bin/inspect.js +226 -0
- package/bin/minify.js +123 -0
- package/bin/up.js +2 -2
- package/bin/util/cli.js +132 -0
- package/bin/util/log.js +2 -0
- package/bin/version.js +2 -1
- package/bin/watch.js +21 -3
- package/lib/bind/shared.js +3 -1
- package/lib/build/buildTaskEngine.js +2 -1
- package/lib/build/plugins/helm/files/templates/NOTES.txt +1 -1
- package/lib/build/plugins/helm/index.js +1 -2
- package/lib/build/provider/internalBuildTaskProvider.js +3 -3
- package/lib/build/provider/nodejs/index.js +62 -3
- package/lib/deploy/index.js +1 -1
- package/lib/deploy/to-hana/hana.js +18 -16
- package/lib/import/odata/v2parser.js +2 -2
- package/lib/import/odata/v4parser.js +21 -2
- package/lib/import/odata.package.json +4 -4
- package/lib/init/constants.js +4 -1
- package/lib/init/index.js +6 -5
- package/lib/init/mvn.js +3 -2
- package/lib/init/projectReader.js +65 -55
- package/lib/init/registries/mta.js +6 -0
- package/lib/init/template/ams/files/manifest.yml.hbs +1 -1
- package/lib/init/template/ams/files/mta.yaml.hbs +1 -1
- package/lib/init/template/ams/index.js +7 -6
- package/lib/init/template/app-frontend/files/app-package.json.hbs +20 -0
- package/lib/init/template/app-frontend/files/index.html.hbs +34 -0
- package/lib/init/template/app-frontend/files/manifest.json +13 -0
- package/lib/init/template/app-frontend/files/mta.yaml.hbs +64 -0
- package/lib/init/template/app-frontend/files/package.json.hbs +17 -0
- package/lib/init/template/app-frontend/files/ui5-deploy.yaml.hbs +25 -0
- package/lib/init/template/app-frontend/files/ui5.yaml.hbs +6 -0
- package/lib/init/template/app-frontend/files/values.yaml.hbs +20 -0
- package/lib/init/template/app-frontend/files/xs-app.json.hbs +17 -0
- package/lib/init/template/app-frontend/index.js +98 -0
- package/lib/init/template/application-logging/index.js +13 -10
- package/lib/init/template/approuter/files/mta.yaml.hbs +0 -2
- package/lib/init/template/approuter/index.js +15 -9
- package/lib/init/template/attachments/index.js +7 -13
- package/lib/init/template/audit-logging/files/package.json.hbs +5 -0
- package/lib/init/template/audit-logging/index.js +4 -4
- package/lib/init/template/cloud-logging/index.js +13 -10
- package/lib/init/template/connectivity/index.js +3 -3
- package/lib/init/template/destination/index.js +6 -6
- package/lib/init/template/dynatrace/index.js +13 -10
- package/lib/init/template/enterprise-messaging/index.js +5 -5
- package/lib/init/template/enterprise-messaging-shared/index.js +4 -4
- package/lib/init/template/extensibility/index.js +2 -2
- package/lib/init/template/file-based-messaging/index.js +2 -2
- package/lib/init/template/github-actions/index.js +3 -3
- package/lib/init/template/hana/index.js +19 -22
- package/lib/init/template/handler/index.js +1 -0
- package/lib/init/template/helm/index.js +34 -21
- package/lib/init/template/html5-repo/files/containerize.yaml.hbs +0 -1
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +10 -2
- package/lib/init/template/html5-repo/index.js +8 -6
- package/lib/init/template/http/index.js +31 -10
- package/lib/init/template/ias/files/manifest.yml.hbs +1 -1
- package/lib/init/template/ias/files/mta.yaml.hbs +9 -5
- package/lib/init/template/ias/files/values.yaml.hbs +14 -2
- package/lib/init/template/ias/index.js +8 -8
- package/lib/init/template/kafka/index.js +3 -3
- package/lib/init/template/local-messaging/index.js +2 -2
- package/lib/init/template/malware-scanner/index.js +3 -7
- package/lib/init/template/mta/files/mta.yaml.hbs +10 -0
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +16 -3
- package/lib/init/template/multitenancy/files/package.json.hbs +5 -0
- package/lib/init/template/multitenancy/files/values.yaml.hbs +1 -6
- package/lib/init/template/multitenancy/index.js +8 -10
- package/lib/init/template/notifications/index.js +2 -2
- package/lib/init/template/portal/files/mta.yaml.hbs +18 -2
- package/lib/init/template/portal/index.js +7 -7
- package/lib/init/template/postgres/index.js +4 -4
- package/lib/init/template/redis/index.js +2 -2
- package/lib/init/template/redis-messaging/index.js +2 -2
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +2 -2
- package/lib/init/template/sample/files/db/schema.cds +5 -8
- package/lib/init/template/sample/files/javascript/admin-service.js.hbs +24 -0
- package/lib/init/template/sample/files/javascript/cat-service.js.hbs +43 -0
- package/lib/init/template/sample/files/typescript/admin-service.ts.hbs +16 -0
- package/lib/init/template/sample/files/typescript/cat-service.ts.hbs +31 -0
- package/lib/init/template/test/files/test/test.xs.hbs +1 -1
- package/lib/init/template/test/index.js +2 -2
- package/lib/init/template/tiny-sample/index.js +1 -1
- package/lib/init/template/typer/files/xsconfig.json +2 -1
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/typescript/files/tsconfig.json +4 -1
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +4 -0
- package/lib/init/template/workzone-standard/index.js +8 -8
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +0 -2
- package/lib/init/template/xsuaa/files/package.json.hbs +3 -0
- package/lib/init/template/xsuaa/index.js +23 -18
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/util/term.js +2 -4
- package/npm-shrinkwrap.json +28 -28
- package/package.json +1 -1
|
@@ -143,7 +143,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
|
|
|
143
143
|
sidecarEnv = cds.env.for("cds", sidecarPath)
|
|
144
144
|
}
|
|
145
145
|
if (
|
|
146
|
-
cds.env.profiles?.includes('with-mtx-sidecar') || // new presets
|
|
146
|
+
cds.env.profiles?.includes('with-mtx-sidecar') || // new presets // FIXME: BAD hard-coded dependency to profile
|
|
147
147
|
cds.env.requires["cds.xt.ModelProviderService"]?.external // for compatibility with former mtxs presets
|
|
148
148
|
) {
|
|
149
149
|
DEBUG?.("MTX app with sidecar")
|
|
@@ -161,7 +161,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
if (sidecarEnv?.requires["cds.xt.ModelProviderService"]?._in_sidecar || sidecarEnv?.profiles?.includes('mtx-sidecar')) {
|
|
164
|
-
throw new BuildError(`MTX sidecar requires profile 'with-mtx-sidecar' in project root configuration.`)
|
|
164
|
+
throw new BuildError(`MTX sidecar requires profile 'with-mtx-sidecar' in project root configuration.`) // FIXME: BAD hard-coded dependency to profile
|
|
165
165
|
}
|
|
166
166
|
if (cds.env.requires["cds.xt.ModelProviderService"]?._in_sidecar || cds.env.profiles?.includes('mtx-sidecar')) {
|
|
167
167
|
// cds build is executed in sidecar folder
|
|
@@ -222,7 +222,7 @@ class InternalBuildTaskProvider extends BuildTaskProvider {
|
|
|
222
222
|
*/
|
|
223
223
|
static _isMtxs() {
|
|
224
224
|
return cds.env.requires.toggles
|
|
225
|
-
|| cds.env.profiles.includes('with-mtx-sidecar')
|
|
225
|
+
|| cds.env.profiles.includes('with-mtx-sidecar') // FIXME: BAD hard-coded dependency to profile
|
|
226
226
|
|| cds.env.requires['cds.xt.ModelProviderService']
|
|
227
227
|
|| (typeof cds.env.requires.multitenancy === "object")
|
|
228
228
|
}
|
|
@@ -6,10 +6,13 @@ const EdmxBuildPlugin = require('../edmxBuildPlugin')
|
|
|
6
6
|
const { BuildError, getWorkspaces, findWorkspaceRoot } = require('../../util')
|
|
7
7
|
const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, ODATA_VERSION_V2, FOLDER_GEN, CONTENT_EDMX, CONTENT_PACKAGELOCK_JSON,
|
|
8
8
|
CONTENT_NPMRC, CONTENT_CDSRC_JSON, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, FLAVOR_LOCALIZED_EDMX,
|
|
9
|
-
OPTION_WS_PACK} = require('../../constants')
|
|
9
|
+
OPTION_WS_PACK} = require('../../constants');
|
|
10
10
|
const { WARNING } = EdmxBuildPlugin
|
|
11
|
-
const LOG = cds.log('cli|build')
|
|
11
|
+
const LOG = cds.log('cli|build')
|
|
12
|
+
const DEBUG = cds.debug('cli|build')
|
|
12
13
|
const NODE_ENGINE_VERSION = '>=20'
|
|
14
|
+
const { exec } = require('node:child_process')
|
|
15
|
+
const pexec = require('node:util').promisify(exec);
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* @param {T | T[]} x
|
|
@@ -84,9 +87,65 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
84
87
|
await this._packWorkspaceDependencies(destRoot)
|
|
85
88
|
}
|
|
86
89
|
}
|
|
90
|
+
|
|
91
|
+
await this.#cleanupPackageJson(destRoot)
|
|
92
|
+
|
|
87
93
|
return this._result
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Removes devDeps that are invalid semver, pointing to workspace or file locations,
|
|
98
|
+
* and also removes workspace entries. If needed, creates a new package-lock.json in build destination.
|
|
99
|
+
*/
|
|
100
|
+
async #cleanupPackageJson() {
|
|
101
|
+
/** @param {string | undefined} version */
|
|
102
|
+
const valid = version => version && !version.match('^(?:workspace|file):')
|
|
103
|
+
|
|
104
|
+
const packageJsonPath = path.join(this.task.dest, 'package.json')
|
|
105
|
+
try {
|
|
106
|
+
const packageJson = await cds.utils.read(packageJsonPath)
|
|
107
|
+
|
|
108
|
+
DEBUG?.(`Sanitizing the package.json for "${this.task.src}'...`)
|
|
109
|
+
|
|
110
|
+
let modified = false
|
|
111
|
+
// remove the workspace configuration
|
|
112
|
+
if (packageJson.workspaces) {
|
|
113
|
+
delete packageJson.workspaces
|
|
114
|
+
modified = true
|
|
115
|
+
}
|
|
116
|
+
// remove the workspace dev dependencies and the cds-plugin-ui5
|
|
117
|
+
if (packageJson.devDependencies) {
|
|
118
|
+
packageJson.devDependencies = Object.entries(packageJson.devDependencies)
|
|
119
|
+
.reduce((acc, [dep, version]) => {
|
|
120
|
+
if (valid(version)) {
|
|
121
|
+
acc[dep] = version
|
|
122
|
+
}
|
|
123
|
+
return acc
|
|
124
|
+
}, {})
|
|
125
|
+
modified = true
|
|
126
|
+
}
|
|
127
|
+
// overwrite the package.json if it was modified only
|
|
128
|
+
if (modified) {
|
|
129
|
+
await cds.utils.write(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8')
|
|
130
|
+
// update the package-lock.json if it exists
|
|
131
|
+
if (cds.utils.exists(path.join(this.task.dest, 'package-lock.json'))) {
|
|
132
|
+
DEBUG?.(`Updating the package-lock.json for '${this.task.src}'...`)
|
|
133
|
+
// run the npm install --package-lock-only to only update the package-lock.json
|
|
134
|
+
// without installing the dependencies to node_modules
|
|
135
|
+
try {
|
|
136
|
+
await pexec('npm install --package-lock-only', { cwd: this.task.dest })
|
|
137
|
+
} catch (e) {
|
|
138
|
+
DEBUG?.(`Failed to update the package-lock.json for '${this.task.src}'! Error: ${e.code} - ${e.message}`)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
// ENOENT: package.json not found -> this is okay for monorepos
|
|
144
|
+
if (e.code !== 'ENOENT') throw e
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
|
|
90
149
|
async clean() {
|
|
91
150
|
// staging build content is deleted by BuildTaskEngine
|
|
92
151
|
if (cds.env.build.target === '.') {
|
|
@@ -186,7 +245,7 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
186
245
|
async _packWorkspaceDependencies(dest) {
|
|
187
246
|
const wsRoot = findWorkspaceRoot(cds.root)
|
|
188
247
|
const appPkg = require(path.join(dest, 'package.json'))
|
|
189
|
-
const allWorkspaces = await getWorkspaces(wsRoot, true, false)
|
|
248
|
+
const allWorkspaces = await getWorkspaces(wsRoot, true, false)
|
|
190
249
|
let workspaces
|
|
191
250
|
if (this.task.options.workspaces) {
|
|
192
251
|
const relevantWorkspaces = new Set(arrayify(this.task.options.workspaces))
|
package/lib/deploy/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
options: /** @type{const} */(['--to', '--for', '--out', '--on', '--tunnel-address', '--vcap-file', '--delta-from']),
|
|
3
|
-
flags: /** @type{const} */(['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--no-build', '--model-only', '--script', '--with-auto-schema-evolution']),
|
|
3
|
+
flags: /** @type{const} */(['--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--no-build', '--model-only', '--script', '--with-auto-schema-evolution', '--resolve-bindings']),
|
|
4
4
|
shortcuts: ['-2', '-4', '-o', '-n']
|
|
5
5
|
}
|
|
@@ -30,7 +30,8 @@ const allowList = [
|
|
|
30
30
|
'--tunnel-address',
|
|
31
31
|
'--vcap-file',
|
|
32
32
|
'--with-mocks',
|
|
33
|
-
'--no-build'
|
|
33
|
+
'--no-build',
|
|
34
|
+
'--resolve-bindings'
|
|
34
35
|
]
|
|
35
36
|
|
|
36
37
|
module.exports = new class HanaDeployer {
|
|
@@ -190,7 +191,22 @@ spec:
|
|
|
190
191
|
serviceName ??= cfServiceInstanceName;
|
|
191
192
|
serviceKeyName ??= cfServiceInstanceKeyName
|
|
192
193
|
if (!vcapEnv.VCAP_SERVICES || serviceName) {
|
|
193
|
-
|
|
194
|
+
const base = process.env.VCAP_SERVICES ? JSON.parse(process.env.VCAP_SERVICES) : (vcapEnv.VCAP_SERVICES ?? {});
|
|
195
|
+
const hanas = Array.isArray(base.hana) ? base.hana : [];
|
|
196
|
+
let hanaTagged = hanas.filter(s => s?.name === cfServiceInstanceName || (Array.isArray(s?.tags) && s.tags.includes('hana')));
|
|
197
|
+
if (hanaTagged.length === 0) {
|
|
198
|
+
const entry = { name: cfServiceInstanceName, label: 'hana', tags: ['hana'], credentials: {} };
|
|
199
|
+
hanas.push(entry);
|
|
200
|
+
hanaTagged = [entry];
|
|
201
|
+
}
|
|
202
|
+
for (const entry of hanaTagged) {
|
|
203
|
+
entry.name ??= cfServiceInstanceName;
|
|
204
|
+
entry.tags = Array.from(new Set([...entry.tags || [], 'hana']));
|
|
205
|
+
entry.credentials = { ...(entry.credentials || {}), ...serviceKey };
|
|
206
|
+
}
|
|
207
|
+
base.hana = hanas;
|
|
208
|
+
vcapEnv.VCAP_SERVICES = base;
|
|
209
|
+
process.env.VCAP_SERVICES = JSON.stringify(base);
|
|
194
210
|
}
|
|
195
211
|
|
|
196
212
|
if (!hasVCAPEnv) {
|
|
@@ -229,7 +245,6 @@ spec:
|
|
|
229
245
|
return buildResult;
|
|
230
246
|
}
|
|
231
247
|
|
|
232
|
-
|
|
233
248
|
async _getOrCreateCFService(currentModelFolder, serviceName, serviceKeyName, tunnelAddress) {
|
|
234
249
|
|
|
235
250
|
// get from param
|
|
@@ -297,19 +312,6 @@ spec:
|
|
|
297
312
|
return buildResult[0].result;
|
|
298
313
|
}
|
|
299
314
|
|
|
300
|
-
_getVCAPServicesEntry(serviceInstanceName, serviceKey) {
|
|
301
|
-
return {
|
|
302
|
-
hana: [
|
|
303
|
-
{
|
|
304
|
-
name: serviceInstanceName,
|
|
305
|
-
tags: ['hana'],
|
|
306
|
-
credentials: serviceKey
|
|
307
|
-
}
|
|
308
|
-
]
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
315
|
_injectTunnelAddress(credentials, tunnelAddress) {
|
|
314
316
|
if (!/\w+:\d+/.test(tunnelAddress)) {
|
|
315
317
|
throw `Invalid tunnel address '${tunnelAddress}' - must be in form 'host:port'`;
|
|
@@ -10,7 +10,7 @@ let versionInfo = require('../../../package.json').version;
|
|
|
10
10
|
const { warn } = require('../../util/term');
|
|
11
11
|
|
|
12
12
|
const edmxncdsdatatype = {
|
|
13
|
-
"Edm.String": "cds.
|
|
13
|
+
"Edm.String": "cds.String",
|
|
14
14
|
"Edm.Boolean": "cds.Boolean",
|
|
15
15
|
"Edm.Int16": "cds.Integer",
|
|
16
16
|
"Edm.Int32": "cds.Integer",
|
|
@@ -592,7 +592,7 @@ function _getServiceEntityProperty(
|
|
|
592
592
|
}
|
|
593
593
|
|
|
594
594
|
if (defaultValue !== -1 && defaultValue) {
|
|
595
|
-
propertyJson = propertyJson + ', \n"default": {\n"val":
|
|
595
|
+
propertyJson = propertyJson + ', \n"default": {\n"val": ' + JSON.stringify(defaultValue) + '\n}';
|
|
596
596
|
}
|
|
597
597
|
|
|
598
598
|
if (propertyName)
|
|
@@ -33,7 +33,7 @@ const edmToCdsTypeMapping = {
|
|
|
33
33
|
'Edm.Int16': 'cds.Integer',
|
|
34
34
|
'Edm.Int32': 'cds.Integer',
|
|
35
35
|
'Edm.Int64': 'cds.Integer64',
|
|
36
|
-
'Edm.String': 'cds.
|
|
36
|
+
'Edm.String': 'cds.String',
|
|
37
37
|
'Edm.TimeOfDay': 'cds.Time',
|
|
38
38
|
};
|
|
39
39
|
|
|
@@ -261,7 +261,26 @@ function _captureAnnotationInCSN(targetString, annotationObject, csnDefsTargetOb
|
|
|
261
261
|
annotationObject = { "=": annotationObject.$Path };
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
|
|
264
|
+
/**
|
|
265
|
+
* Annotations need to be flattened in CSN. E.g.
|
|
266
|
+
*
|
|
267
|
+
* @Core.ContentDisposition : {
|
|
268
|
+
* Type : 'inline',
|
|
269
|
+
* Filename: typedImageFileName
|
|
270
|
+
* }
|
|
271
|
+
*
|
|
272
|
+
* is represented as:
|
|
273
|
+
*
|
|
274
|
+
* @Core.ContentDisposition.Type : 'inline',
|
|
275
|
+
* @Core.ContentDisposition.Filename : {'=': 'typedImageFileName'},
|
|
276
|
+
*/
|
|
277
|
+
if (annotationObject instanceof Object && !(annotationObject instanceof Array) && !(Object.keys(annotationObject).length === 1 && (Object.keys(annotationObject)[0] === '=' || Object.keys(annotationObject)[0] === 'xpr' || Object.keys(annotationObject)[0] === '#'))) {
|
|
278
|
+
Object.keys(annotationObject).forEach(innerTargetString => {
|
|
279
|
+
_captureAnnotationInCSN(targetString + '.' + innerTargetString, annotationObject[innerTargetString], csnDefsTargetObject);
|
|
280
|
+
})
|
|
281
|
+
} else {
|
|
282
|
+
csnDefsTargetObject[targetString] = annotationObject;
|
|
283
|
+
}
|
|
265
284
|
}
|
|
266
285
|
|
|
267
286
|
function _replaceSpecialCharacters(text) {
|
package/lib/init/constants.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = {
|
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
7
|
JAVA_LTS_VERSIONS: [17, 21],
|
|
8
|
-
MAVEN_ARCHETYPE_VERSION: '4.
|
|
8
|
+
MAVEN_ARCHETYPE_VERSION: '4.4.1',
|
|
9
9
|
|
|
10
10
|
OPTIONS: Object.freeze({
|
|
11
11
|
COMPLETION: 'completion',
|
|
@@ -54,8 +54,11 @@ module.exports = {
|
|
|
54
54
|
CONNECTIVITY: 'connectivity',
|
|
55
55
|
DESTINATION: 'destination',
|
|
56
56
|
HTML5_REPO: 'html5-repo',
|
|
57
|
+
APP_FRONTEND: 'app-frontend',
|
|
57
58
|
PORTAL: 'portal',
|
|
58
59
|
APPLICATION_LOGGING: 'application-logging',
|
|
60
|
+
CLOUD_LOGGING: 'cloud-logging',
|
|
61
|
+
TELEMETRY: 'telemetry',
|
|
59
62
|
AUDIT_LOGGING: 'audit-logging',
|
|
60
63
|
NOTIFICATIONS: 'notifications',
|
|
61
64
|
WORKZONE: 'workzone',
|
package/lib/init/index.js
CHANGED
|
@@ -161,9 +161,7 @@ module.exports = class CDSGenerator {
|
|
|
161
161
|
if (!cds.cli.options.dry) console.log(`adding ${term.bold(facet)}`)
|
|
162
162
|
const template = this.templateList[i]
|
|
163
163
|
await template.run()
|
|
164
|
-
await template.combine()
|
|
165
164
|
}
|
|
166
|
-
|
|
167
165
|
DEBUG && console.log()
|
|
168
166
|
DEBUG && console.log('plugins active for production:')
|
|
169
167
|
const fromDk = readdirSync(join(__dirname, './template'))
|
|
@@ -176,7 +174,7 @@ module.exports = class CDSGenerator {
|
|
|
176
174
|
for (const plugin of sorted) {
|
|
177
175
|
const Plugin = registered.get(plugin) ?? require('./template/' + plugin)
|
|
178
176
|
const template = new Plugin()
|
|
179
|
-
const inProduction = Plugin.hasInProduction(env4('production')) || cds.cli.argv
|
|
177
|
+
const inProduction = Plugin.hasInProduction(env4('production')) || cds.cli.argv[0]?.includes(plugin) || cds.cli.options.add?.has(plugin)
|
|
180
178
|
DEBUG && console.log(inProduction ? '✅' : '❌', plugin)
|
|
181
179
|
if (inProduction) await template.combine()
|
|
182
180
|
}
|
|
@@ -233,21 +231,24 @@ module.exports = class CDSGenerator {
|
|
|
233
231
|
const templates = new Map
|
|
234
232
|
for (let plugin of plugins) {
|
|
235
233
|
// Compat
|
|
234
|
+
if (plugin === 'appfront') plugin = 'app-front'
|
|
236
235
|
if (plugin === 'helm' && cds.cli.options['internal-unified-runtime-charts']) {
|
|
237
236
|
plugin = 'helm-unified-runtime'
|
|
238
|
-
cds.cli.options.add
|
|
239
|
-
cds.cli.options.add
|
|
237
|
+
cds.cli.options.add?.delete('helm')
|
|
238
|
+
cds.cli.options.add?.add('helm-unified-runtime')
|
|
240
239
|
}
|
|
241
240
|
if (plugin === 'sample-tiny') plugin = 'tiny-sample'
|
|
242
241
|
if (plugin in { 'kibana-logging': 1, 'kibana': 1 }) plugin = 'application-logging'
|
|
243
242
|
if (plugin === 'postgresql') plugin = 'postgres'
|
|
244
243
|
if (plugin === 'gha') plugin = 'github-actions'
|
|
244
|
+
if (plugin === 'app-front') plugin = 'app-frontend'
|
|
245
245
|
|
|
246
246
|
if (!templates.has(plugin)) {
|
|
247
247
|
const template = await this._createTemplate(plugin)
|
|
248
248
|
if (await template.canRun()) {
|
|
249
249
|
templates.set(plugin, template)
|
|
250
250
|
const dependencies = await template.requires()
|
|
251
|
+
dependencies?.forEach(d => cds.cli.options.add?.add(d))
|
|
251
252
|
dependencies?.forEach(d => plugins.add(d))
|
|
252
253
|
} else {
|
|
253
254
|
throw 'cannot run plugin \'' + plugin + '\'' + (DEBUG ? 'Does not satisfy the canRun() function:\n ' + template.canRun : '')
|
package/lib/init/mvn.js
CHANGED
|
@@ -21,8 +21,9 @@ module.exports.add = async function (feature, featureOptions={}) {
|
|
|
21
21
|
}
|
|
22
22
|
params.set(`-Dfeature`, feature)
|
|
23
23
|
|
|
24
|
-
const profile = cds.cli.options.for
|
|
25
|
-
params.set(`-Dprofile`, profile
|
|
24
|
+
const profile = cds.cli.options.for === 'production' ? 'cloud' : cds.cli.options.for ?? 'default'
|
|
25
|
+
params.set(`-Dprofile`, profile)
|
|
26
|
+
if (feature === 'mtx' && profile === 'default') params.set('-Dprofile', 'with-mtx')
|
|
26
27
|
|
|
27
28
|
Object.entries(featureOptions).forEach(([k,v]) => params.set(`-Doptions.${k}`, v))
|
|
28
29
|
|
|
@@ -60,58 +60,6 @@ module.exports = new class ProjectReader {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/**
|
|
64
|
-
* @typedef {Object} ProjectConfig
|
|
65
|
-
* @property {string} appVersion The version of the application.
|
|
66
|
-
* @property {string} appName The name of the application.
|
|
67
|
-
* @property {string} appId The ID of the application.
|
|
68
|
-
* @property {string} appDescription The description of the application.
|
|
69
|
-
* @property {'java' | 'nodejs'} language The programming language of the project.
|
|
70
|
-
* @property {string} srvPath The path to the server module.
|
|
71
|
-
* @property {string} archiveName The name of the archive.
|
|
72
|
-
* @property {Object} db Database configuration.
|
|
73
|
-
* @property {string} configFile The name of the configuration file. This is typically the `package.json` for Node.js and `.cdsrc.json` for Java.
|
|
74
|
-
* @property {string} appPath The path to the app folder.
|
|
75
|
-
* @property {string} approuterPath The path to the approuter folder.
|
|
76
|
-
* @property {boolean} hasUIEmbedded Indicates if the project uses an embedded UI.
|
|
77
|
-
* @property {boolean} hasUIModule Indicates if the project is using a modular UI.
|
|
78
|
-
* @property {boolean} hasUI Indicates if the project has a UI.
|
|
79
|
-
* @property {boolean} hasUI5 Indicates if the project is a UI5 project.
|
|
80
|
-
* @property {boolean} isUI5 Indicates if the project is a UI5 project.
|
|
81
|
-
* @property {boolean} isJava Indicates if the project is using Java.
|
|
82
|
-
* @property {boolean} isNodejs Indicates if the project is using Node.js.
|
|
83
|
-
* @property {boolean} isESM Indicates if the project is an ESM project (type 'module')
|
|
84
|
-
* @property {boolean} hasEsmStyle Indicates if code supports ESM-style imports and exports. This is true for ESM and Typescript projects.
|
|
85
|
-
* @property {boolean} isTypescript Indicates if the project is a Typescript project.
|
|
86
|
-
* @property {boolean} hasTyper Indicates if code supports CDS typer.
|
|
87
|
-
* @property {boolean} hasHelmUnifiedRuntime Indicates if the project uses Unified Runtime Helm deployment.
|
|
88
|
-
* @property {boolean} hasHelm Indicates if the project uses CAP Helm deployment.
|
|
89
|
-
* @property {boolean} hasMta Indicates if the project uses MTA deployment.
|
|
90
|
-
* @property {boolean} hasConnectivity Indicates if the project uses connectivity.
|
|
91
|
-
* @property {boolean} hasMultitenancy Indicates if the project is multitenant.
|
|
92
|
-
* @property {boolean} hasToggles Indicates if the project uses feature toggles.
|
|
93
|
-
* @property {boolean} hasExtensibility Indicates if the project is extensible.
|
|
94
|
-
* @property {boolean} hasXsuaa Indicates if the project uses XSUAA.
|
|
95
|
-
* @property {boolean} hasHana Indicates if the project uses HANA.
|
|
96
|
-
* @property {boolean} hasPostgres Indicates if the project uses PostgreSQL.
|
|
97
|
-
* @property {boolean} hasEnterpriseMessaging Indicates if the project uses SAP BTP Event Mesh.
|
|
98
|
-
* @property {boolean} hasAttachments Indicates if the project uses SAP BTP Object Store Service.
|
|
99
|
-
* @property {boolean} hasApprouter Indicates if the project uses the SAP Application Router.
|
|
100
|
-
* @property {boolean} hasHtml5Repo Indicates if the project uses the SAP BTP HTML5 Application Repository.
|
|
101
|
-
* @property {boolean} hasPortal Indicates if the project uses the SAP Cloud Portal service.
|
|
102
|
-
* @property {boolean} hasWorkzoneStandard Indicates if the project uses the SAP Build Work Zone, Standard Edition service.
|
|
103
|
-
* @property {boolean} hasDestination Indicates if the project uses the SAP BTP Destination service.
|
|
104
|
-
* @property {boolean} hasMTXRoute Indicates if the approuter should have a multitenant route.
|
|
105
|
-
* @property {boolean} hasMTXRouteJava Indicates if the approuter should have a multitenant subscription route (java).
|
|
106
|
-
* @property {boolean} hasMalwareScanner Indicates if the project uses the SAP Malware Scanning service.
|
|
107
|
-
* @property {boolean} hasDynatrace Indicates if the project uses Dynatrace.
|
|
108
|
-
* @property {boolean} hasCloudLogging Indicates if the project uses Cloud Logging.
|
|
109
|
-
* @property {String} extendsApp Indicates which project is extended if any.
|
|
110
|
-
* @property {String} githubSlug GitHub org/repo.
|
|
111
|
-
* @property {boolean} isMonorepoMicroservice Indicates if the project is a monorepo microservice.
|
|
112
|
-
* @property {String} npmWorkspaceRoot The root path of the monorepo workspace.
|
|
113
|
-
*/
|
|
114
|
-
|
|
115
63
|
/**
|
|
116
64
|
* Reads the project configuration and constructs a project object.
|
|
117
65
|
* This function dynamically resolves project properties and returns an object with these properties.
|
|
@@ -128,7 +76,7 @@ module.exports = new class ProjectReader {
|
|
|
128
76
|
const _isESM = () => pkgJson().type === 'module'
|
|
129
77
|
const _isTypescript = () => !!pkgJson().dependencies?.typescript || !!pkgJson().devDependencies?.typescript
|
|
130
78
|
const _hasTyper = () => !!pkgJson().dependencies?.['@cap-js/cds-typer'] || !!pkgJson().devDependencies?.['@cap-js/cds-typer']
|
|
131
|
-
const _inProd = plugin => require(`./template/${plugin}`).hasInProduction(env) || cds.cli.argv
|
|
79
|
+
const _inProd = plugin => require(`./template/${plugin}`).hasInProduction(env) || cds.cli.argv[0]?.includes(plugin) || cds.cli.options.add?.has(plugin)
|
|
132
80
|
const _uiEmbedded = () => exists(join(env.folders.app, 'xs-app.json'))
|
|
133
81
|
const _uiModule = () => !_uiEmbedded() && isdir(env.folders.app) && fs.readdirSync(resolve(cds.root, env.folders.app)).length > 0
|
|
134
82
|
const _isJava = () => this.isJava
|
|
@@ -141,6 +89,7 @@ module.exports = new class ProjectReader {
|
|
|
141
89
|
devDependencies: () => pkgJson().devDependencies,
|
|
142
90
|
has: x => _inProd(x),
|
|
143
91
|
profile: () => cds.cli.options?.for,
|
|
92
|
+
profileSpecified: () => !!cds.cli.options.for,
|
|
144
93
|
language: () => _isJava() ? 'java' : 'nodejs',
|
|
145
94
|
isJava: () => _isJava(),
|
|
146
95
|
isNodejs: () => !_isJava(),
|
|
@@ -222,8 +171,15 @@ module.exports = new class ProjectReader {
|
|
|
222
171
|
const defined = {}
|
|
223
172
|
const _get = property => { const p = property
|
|
224
173
|
if (p in reserved) return reserved[p]()
|
|
225
|
-
for (const prefix of ['has', 'is']) if (p.startsWith(prefix) && p.length > prefix.length) {
|
|
226
|
-
|
|
174
|
+
for (const prefix of ['has', 'is', 'add']) if (p.startsWith(prefix) && p.length > prefix.length) {
|
|
175
|
+
const facet = p.slice(prefix.length).replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
|
176
|
+
const inProd = _inProd(facet)
|
|
177
|
+
if (prefix === 'add') {
|
|
178
|
+
const adding = facet => cds.cli.argv[0]?.includes(facet) || cds.cli.options.add?.has(facet)
|
|
179
|
+
const caller = new Error().stack.split('\n')[3].replace(/\\/g, '/').match(/lib\/init\/template\/([^/]+)\/index\.js/)[1]
|
|
180
|
+
return inProd && (adding(facet) || adding(caller))
|
|
181
|
+
}
|
|
182
|
+
return inProd
|
|
227
183
|
}
|
|
228
184
|
}
|
|
229
185
|
return new Proxy({}, {
|
|
@@ -287,3 +243,57 @@ function _normalizeSpringBootCfg(obj) {
|
|
|
287
243
|
})
|
|
288
244
|
return obj
|
|
289
245
|
}
|
|
246
|
+
|
|
247
|
+
/* Types */
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @typedef {Object} ProjectConfig
|
|
251
|
+
* @property {string} appVersion The version of the application.
|
|
252
|
+
* @property {string} appName The name of the application.
|
|
253
|
+
* @property {string} appId The ID of the application.
|
|
254
|
+
* @property {string} appDescription The description of the application.
|
|
255
|
+
* @property {'java' | 'nodejs'} language The programming language of the project.
|
|
256
|
+
* @property {string} srvPath The path to the server module.
|
|
257
|
+
* @property {string} archiveName The name of the archive.
|
|
258
|
+
* @property {Object} db Database configuration.
|
|
259
|
+
* @property {string} configFile The name of the configuration file. This is typically the `package.json` for Node.js and `.cdsrc.json` for Java.
|
|
260
|
+
* @property {string} appPath The path to the app folder.
|
|
261
|
+
* @property {string} approuterPath The path to the approuter folder.
|
|
262
|
+
* @property {boolean} hasUIEmbedded Indicates if the project uses an embedded UI.
|
|
263
|
+
* @property {boolean} hasUIModule Indicates if the project is using a modular UI.
|
|
264
|
+
* @property {boolean} hasUI Indicates if the project has a UI.
|
|
265
|
+
* @property {boolean} hasUI5 Indicates if the project is a UI5 project.
|
|
266
|
+
* @property {boolean} isUI5 Indicates if the project is a UI5 project.
|
|
267
|
+
* @property {boolean} isJava Indicates if the project is using Java.
|
|
268
|
+
* @property {boolean} isNodejs Indicates if the project is using Node.js.
|
|
269
|
+
* @property {boolean} isESM Indicates if the project is an ESM project (type 'module')
|
|
270
|
+
* @property {boolean} hasEsmStyle Indicates if code supports ESM-style imports and exports. This is true for ESM and Typescript projects.
|
|
271
|
+
* @property {boolean} isTypescript Indicates if the project is a Typescript project.
|
|
272
|
+
* @property {boolean} hasTyper Indicates if code supports CDS typer.
|
|
273
|
+
* @property {boolean} hasHelmUnifiedRuntime Indicates if the project uses Unified Runtime Helm deployment.
|
|
274
|
+
* @property {boolean} hasHelm Indicates if the project uses CAP Helm deployment.
|
|
275
|
+
* @property {boolean} hasMta Indicates if the project uses MTA deployment.
|
|
276
|
+
* @property {boolean} hasConnectivity Indicates if the project uses connectivity.
|
|
277
|
+
* @property {boolean} hasMultitenancy Indicates if the project is multitenant.
|
|
278
|
+
* @property {boolean} hasToggles Indicates if the project uses feature toggles.
|
|
279
|
+
* @property {boolean} hasExtensibility Indicates if the project is extensible.
|
|
280
|
+
* @property {boolean} hasXsuaa Indicates if the project uses XSUAA.
|
|
281
|
+
* @property {boolean} hasHana Indicates if the project uses HANA.
|
|
282
|
+
* @property {boolean} hasPostgres Indicates if the project uses PostgreSQL.
|
|
283
|
+
* @property {boolean} hasEnterpriseMessaging Indicates if the project uses SAP BTP Event Mesh.
|
|
284
|
+
* @property {boolean} hasAttachments Indicates if the project uses SAP BTP Object Store Service.
|
|
285
|
+
* @property {boolean} hasApprouter Indicates if the project uses the SAP Application Router.
|
|
286
|
+
* @property {boolean} hasHtml5Repo Indicates if the project uses the SAP BTP HTML5 Application Repository.
|
|
287
|
+
* @property {boolean} hasPortal Indicates if the project uses the SAP Cloud Portal service.
|
|
288
|
+
* @property {boolean} hasWorkzoneStandard Indicates if the project uses the SAP Build Work Zone, Standard Edition service.
|
|
289
|
+
* @property {boolean} hasDestination Indicates if the project uses the SAP BTP Destination service.
|
|
290
|
+
* @property {boolean} hasMTXRoute Indicates if the approuter should have a multitenant route.
|
|
291
|
+
* @property {boolean} hasMTXRouteJava Indicates if the approuter should have a multitenant subscription route (java).
|
|
292
|
+
* @property {boolean} hasMalwareScanner Indicates if the project uses the SAP Malware Scanning service.
|
|
293
|
+
* @property {boolean} hasDynatrace Indicates if the project uses Dynatrace.
|
|
294
|
+
* @property {boolean} hasCloudLogging Indicates if the project uses Cloud Logging.
|
|
295
|
+
* @property {String} extendsApp Indicates which project is extended if any.
|
|
296
|
+
* @property {String} githubSlug GitHub org/repo.
|
|
297
|
+
* @property {boolean} isMonorepoMicroservice Indicates if the project is a monorepo microservice.
|
|
298
|
+
* @property {String} npmWorkspaceRoot The root path of the monorepo workspace.
|
|
299
|
+
*/
|
|
@@ -10,6 +10,11 @@ const srv4 = isJava ? srvJava4 : srvNode4
|
|
|
10
10
|
|
|
11
11
|
const approuter = { in: 'modules', where: { type: 'approuter.nodejs' } }
|
|
12
12
|
|
|
13
|
+
const appFront = {
|
|
14
|
+
in: 'resources',
|
|
15
|
+
where: { type: 'org.cloudfoundry.managed-service', 'parameters.service': 'app-front' }
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
const xsuaa = {
|
|
14
19
|
in: 'resources',
|
|
15
20
|
where: { type: 'org.cloudfoundry.managed-service', 'parameters.service': 'xsuaa', 'parameters.service-plan': 'application' }
|
|
@@ -233,6 +238,7 @@ module.exports = {
|
|
|
233
238
|
applicationLogging,
|
|
234
239
|
approuterMTXRoute,
|
|
235
240
|
approuterMTXRouteJava,
|
|
241
|
+
appFront,
|
|
236
242
|
html5RepoHost,
|
|
237
243
|
html5Runtime,
|
|
238
244
|
appDeployer,
|
|
@@ -18,7 +18,7 @@ applications:
|
|
|
18
18
|
buildpack: nodejs_buildpack
|
|
19
19
|
command: (npm start && echo "This application may now be stopped to free resources." || echo "AMS Policy Deployment unsuccessful.") && sleep infinity
|
|
20
20
|
services:
|
|
21
|
-
- name: {{appName}}-
|
|
21
|
+
- name: {{appName}}-ias
|
|
22
22
|
parameters:
|
|
23
23
|
credential-type: X509_GENERATED
|
|
24
24
|
app-identifier: ams-policy-deployer
|
|
@@ -14,7 +14,8 @@ module.exports = class AmsTemplate extends require('../../plugin') {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
static hasInProduction(env) {
|
|
17
|
-
|
|
17
|
+
const { dependencies, devDependencies } = readProject()
|
|
18
|
+
return env.requires?.auth?.ams || devDependencies?.['@sap/ams-dev'] || dependencies?.['@sap/ams']
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
async run() {
|
|
@@ -27,21 +28,21 @@ module.exports = class AmsTemplate extends require('../../plugin') {
|
|
|
27
28
|
|
|
28
29
|
async combine() {
|
|
29
30
|
const project = readProject()
|
|
30
|
-
const {
|
|
31
|
+
const { addMta, addCfManifest, addHelm, addHelmUnifiedRuntime, addContainerize } = project
|
|
31
32
|
|
|
32
|
-
if (
|
|
33
|
+
if (addMta) {
|
|
33
34
|
await this.#combineWithMta(project)
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
if (
|
|
37
|
+
if (addCfManifest) {
|
|
37
38
|
await this.#combineWithCfManifest(project)
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
if (
|
|
41
|
+
if (addHelm || addHelmUnifiedRuntime) {
|
|
41
42
|
await this.#combineWithHelm(project)
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
if (
|
|
45
|
+
if (addContainerize) {
|
|
45
46
|
await this.#combineWithContainerize(project)
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{app}}"{{#hasUI5}},
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "webapp/index.html",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "ui5 build preload --clean-dest --config ui5-deploy.yaml",
|
|
7
|
+
"build-local": "ui5 build preload --clean-dest",
|
|
8
|
+
"start": "ui5 serve"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@ui5/cli": "^4",
|
|
12
|
+
"ui5-task-zipper": "^3"
|
|
13
|
+
},
|
|
14
|
+
"ui5": {
|
|
15
|
+
"dependencies": [
|
|
16
|
+
"ui5-task-zipper"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
{{/hasUI5}}
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>{{appName}} - {{app}}</title>
|
|
7
|
+
<style>
|
|
8
|
+
html, body, body > div, #container, #container-uiarea {
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
</style>
|
|
12
|
+
<script
|
|
13
|
+
id="sap-ui-bootstrap"
|
|
14
|
+
src="https://sapui5.hana.ondemand.com/1.140.0/resources/sap-ui-core.js"
|
|
15
|
+
data-sap-ui-theme="sap_horizon"
|
|
16
|
+
data-sap-ui-resourceroots='{
|
|
17
|
+
"{{appName}}.{{app}}": "./"
|
|
18
|
+
}'
|
|
19
|
+
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
|
|
20
|
+
data-sap-ui-compatVersion="edge"
|
|
21
|
+
data-sap-ui-async="true"
|
|
22
|
+
data-sap-ui-frameOptions="trusted"
|
|
23
|
+
></script>
|
|
24
|
+
</head>
|
|
25
|
+
<body class="sapUiBody sapUiSizeCompact" id="content">
|
|
26
|
+
<div
|
|
27
|
+
data-sap-ui-component
|
|
28
|
+
data-name="{{appName}}.{{app}}"
|
|
29
|
+
data-id="container"
|
|
30
|
+
data-settings='{"id" : "{{appName}}.{{app}}" }'
|
|
31
|
+
data-handle-validation="true"
|
|
32
|
+
></div>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|