@sap/cds-dk 7.7.1 → 7.8.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/add.js +42 -17
- package/bin/bind.js +21 -12
- package/bin/build.js +14 -2
- package/bin/deploy/to-sqlite.js +1 -1
- package/bin/help.js +4 -1
- package/bin/import.js +5 -1
- package/bin/version.js +54 -22
- package/lib/bind/userCdsrcJsonStorageProvider.js +1 -1
- package/lib/build/buildTaskFactory.js +2 -2
- package/lib/build/provider/hana/index.js +1 -1
- package/lib/build/provider/internalBuildTaskProvider.js +19 -5
- package/lib/build/provider/java/index.js +4 -4
- package/lib/build/provider/mtx/resourcesTarBuilder.js +16 -4
- package/lib/build/provider/mtx-extension/extensionCompilation.js +13 -2
- package/lib/build/provider/mtx-extension/index.js +6 -2
- package/lib/build/provider/nodejs/index.js +4 -4
- package/lib/build/util.js +1 -12
- package/lib/compile/openapi/index.js +2 -1
- package/lib/deploy/to-hana/hana.js +19 -17
- package/lib/import/common.js +1 -1
- package/lib/import/importapi.js +1 -1
- package/lib/import/odata/v4parser.js +18 -11
- package/lib/index.js +2 -2
- package/lib/init/constants.js +2 -1
- package/lib/init/index.js +9 -23
- package/lib/init/mvn.js +1 -5
- package/lib/init/plugin.js +8 -0
- package/lib/init/registries/mta.js +6 -0
- package/lib/init/template/data/as-csv.js +60 -0
- package/lib/init/template/data/as-json.js +441 -0
- package/lib/init/template/data/index.js +115 -86
- package/lib/init/template/helm/files/content-deployment/Chart.yaml +1 -1
- package/lib/init/template/helm/files/content-deployment/templates/job.yaml +7 -0
- package/lib/init/template/helm/files/content-deployment/values.schema.json +17 -0
- package/lib/init/template/helm/files/content-deployment/values.yaml +6 -1
- package/lib/init/template/helm/files/service-instance/Chart.yaml +1 -1
- package/lib/init/template/helm/files/service-instance/templates/serviceinstance.yaml +4 -0
- package/lib/init/template/helm/files/service-instance/values.schema.json +17 -1
- package/lib/init/template/helm/files/service-instance/values.yaml +4 -1
- package/lib/init/template/helm/files/values.yaml.hbs +2 -2
- package/lib/init/template/helm/files/web-application/Chart.yaml +1 -1
- package/lib/init/template/helm/files/web-application/templates/api-rule.yaml +4 -0
- package/lib/init/template/helm/files/web-application/templates/network-policy.yaml +15 -0
- package/lib/init/template/helm/files/web-application/values.schema.json +41 -0
- package/lib/init/template/helm/files/web-application/values.yaml +19 -1
- package/lib/init/template/helm-unified-runtime/files/values.yaml.hbs +2 -2
- package/lib/init/template/helm-unified-runtime/index.js +9 -6
- package/lib/init/template/http/index.js +182 -0
- package/lib/init/template/kafka/files/mta.yaml.hbs +14 -0
- package/lib/init/template/kafka/files/package.json.hbs +22 -0
- package/lib/init/template/kafka/index.js +40 -0
- package/lib/init/template/lint/index.js +4 -4
- package/lib/init/template/mta/files/mta.yaml.hbs +4 -0
- package/lib/init/template/multitenancy/files/values.yaml.hbs +2 -2
- package/lib/util/cf.js +6 -2
- package/npm-shrinkwrap.json +300 -276
- package/package.json +1 -1
package/lib/build/util.js
CHANGED
|
@@ -118,6 +118,7 @@ function resolveRequiredSapModels(modelPaths) {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
async function getDefaultModelOptions(ws = false) {
|
|
121
|
+
// Note: requires.toggles holds the actual kind representation and not the value 'true'
|
|
121
122
|
const wildcards = cds.env.requires.toggles && cds.env.features.folders ? ['*', cds.env.features.folders] : '*'
|
|
122
123
|
let paths = _filterModelPaths(cds.resolve(wildcards, false))
|
|
123
124
|
|
|
@@ -165,17 +166,6 @@ function getI18nDefaultFolder() {
|
|
|
165
166
|
return cds.env.i18n.folders[0] ?? 'i18n'
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
function isClassicMtx() {
|
|
169
|
-
function _hasMtxDependency() {
|
|
170
|
-
try {
|
|
171
|
-
return !!require(path.join(cds.root, 'package.json'))?.dependencies?.['@sap/cds-mtx']
|
|
172
|
-
} catch (e) {
|
|
173
|
-
return false
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return /true/i.test(process.env.OLD_MTX) || _hasMtxDependency()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
169
|
async function pathExists(path) {
|
|
180
170
|
return fs.promises.access(path).then(() => true).catch(() => false);
|
|
181
171
|
}
|
|
@@ -378,7 +368,6 @@ module.exports = {
|
|
|
378
368
|
getDefaultModelOptions,
|
|
379
369
|
flatten,
|
|
380
370
|
getI18nDefaultFolder,
|
|
381
|
-
isClassicMtx,
|
|
382
371
|
normalizePath,
|
|
383
372
|
pathExists,
|
|
384
373
|
getWorkspaces,
|
|
@@ -3,7 +3,8 @@ const cds = require('../../cds')
|
|
|
3
3
|
|
|
4
4
|
module.exports = function processor(csn, options = {}) {
|
|
5
5
|
const edmOptions = Object.assign({
|
|
6
|
-
odataOpenapiHints: true, // hint to compiler
|
|
6
|
+
odataOpenapiHints: true, // hint to cds-compiler
|
|
7
|
+
edm4OpenAPI: true, // downgrades certain OData errors to warnings in cds-compiler
|
|
7
8
|
to: 'openapi' // hint to cds.compile.to.edm (usually set by CLI, but also do this in programmatic usages)
|
|
8
9
|
}, options)
|
|
9
10
|
|
|
@@ -57,7 +57,7 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
|
|
|
57
57
|
|
|
58
58
|
const fromFile = vcapFile && exists(vcapFile) ? await read(vcapFile) : {};
|
|
59
59
|
const fromEnv = this.getFromEnv('VCAP_SERVICES', 'SERVICE_REPLACEMENTS');
|
|
60
|
-
let vcapEnv = { ...
|
|
60
|
+
let vcapEnv = { ...fromEnv, ...fromFile };
|
|
61
61
|
if (process.env.TARGET_CONTAINER) {
|
|
62
62
|
vcapEnv.TARGET_CONTAINER = process.env.TARGET_CONTAINER;
|
|
63
63
|
}
|
|
@@ -82,30 +82,32 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
const hasVCAPEnv = Object.keys(vcapEnv).length > 0;
|
|
85
|
+
let serviceKeyName
|
|
85
86
|
if (!serviceName && hasVCAPEnv) {
|
|
86
87
|
await fs.mkdir(dest, { recursive: true });
|
|
87
|
-
}
|
|
88
|
-
|
|
88
|
+
} else {
|
|
89
|
+
const { cfServiceInstanceName, cfServiceInstanceKeyName, serviceKey } =
|
|
89
90
|
await this._getOrCreateCFService(projectPath, dest, serviceName, tunnelAddress);
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
vcapEnv.VCAP_SERVICES
|
|
94
|
-
|
|
92
|
+
serviceName ??= cfServiceInstanceName;
|
|
93
|
+
serviceKeyName ??= cfServiceInstanceKeyName
|
|
94
|
+
if (!vcapEnv.VCAP_SERVICES || serviceName) {
|
|
95
|
+
vcapEnv.VCAP_SERVICES = this._getVCAPServicesEntry(cfServiceInstanceName, serviceKey);
|
|
96
|
+
}
|
|
95
97
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
if (storeCredentials) {
|
|
99
|
+
await this._addInstanceToDefaultEnvJson([dest, projectPath], cfServiceInstanceName, serviceKey);
|
|
100
|
+
}
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
console.log(`${bold('Starting deployment to SAP HANA ...')}`);
|
|
101
|
-
|
|
102
104
|
DEBUG?.({ dest, vcapEnv, hdiOptions })
|
|
103
105
|
await hdi.deploy(dest, vcapEnv, hdiOptions);
|
|
104
106
|
|
|
105
107
|
if (!hasVCAPEnv) {
|
|
106
108
|
const bindOptions = {
|
|
107
109
|
...options,
|
|
108
|
-
to: `${serviceName}:${
|
|
110
|
+
to: `${serviceName}:${serviceKeyName}`,
|
|
109
111
|
for: options.for,
|
|
110
112
|
kind: task.for
|
|
111
113
|
}
|
|
@@ -227,12 +229,12 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
|
|
|
227
229
|
|
|
228
230
|
_getVCAPServicesEntry(serviceInstanceName, serviceKey) {
|
|
229
231
|
return {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
232
|
+
hana: [
|
|
233
|
+
{
|
|
234
|
+
name: serviceInstanceName,
|
|
235
|
+
tags: ['hana'],
|
|
236
|
+
credentials: serviceKey
|
|
237
|
+
}
|
|
236
238
|
]
|
|
237
239
|
};
|
|
238
240
|
}
|
package/lib/import/common.js
CHANGED
|
@@ -16,7 +16,7 @@ let optionsMapping = {
|
|
|
16
16
|
'no-save': 'no_save'
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
let apiOptions = ['includeNamespaces', 'keepNamespace'];
|
|
19
|
+
let apiOptions = ['includeNamespaces', 'keepNamespace', 'beta'];
|
|
20
20
|
let commonOptions = ['no_copy', 'no_save', 'out', 'dry', 'as', 'from', 'force', 'config'];
|
|
21
21
|
|
|
22
22
|
async function generateEDMX2JSON(edmx) {
|
package/lib/import/importapi.js
CHANGED
|
@@ -64,7 +64,7 @@ async function cds_import_from_edmx(filepath, options = { keepNamespace: false }
|
|
|
64
64
|
filepath = await common.isValidInputFile(path.resolve(process.cwd(), filepath));
|
|
65
65
|
const src = await common.getContentFromFile(filepath);
|
|
66
66
|
// takes the api specific options and reads it from env
|
|
67
|
-
let odataOptions = { include_namespaces: options.includeNamespaces, keep_namespace: options.keepNamespace };
|
|
67
|
+
let odataOptions = { include_namespaces: options.includeNamespaces, keep_namespace: options.keepNamespace, beta: options.beta};
|
|
68
68
|
if (cds.env.import) {
|
|
69
69
|
common.readEnvVariables(odataOptions, false);
|
|
70
70
|
}
|
|
@@ -82,7 +82,7 @@ const known_vocabularies = {
|
|
|
82
82
|
'com.sap.vocabularies.UI.v1': 'UI',
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
function _initialize(parserContext
|
|
85
|
+
function _initialize(parserContext) {
|
|
86
86
|
parserContext.unboundedActions = {};
|
|
87
87
|
parserContext.unboundedFunctions = {};
|
|
88
88
|
parserContext.entityTypes = [];
|
|
@@ -103,7 +103,8 @@ function _initialize(parserContext, mockServerUc) {
|
|
|
103
103
|
parserContext.entityToBoundedActions = {};
|
|
104
104
|
parserContext.entityToBoundedFunctions = {};
|
|
105
105
|
parserContext.entityContainerAnnotations = {};
|
|
106
|
-
parserContext.mockServerUc =
|
|
106
|
+
parserContext.mockServerUc = true;
|
|
107
|
+
parserContext.beta = false;
|
|
107
108
|
}
|
|
108
109
|
function _isJson(edmx) {
|
|
109
110
|
let isJson = false;
|
|
@@ -290,7 +291,7 @@ function _replaceSpecialCharacters(text) {
|
|
|
290
291
|
return text.replace(/(?:\\[rn]|[\r\n]+)+/gm, "\n").replace(/\s+/g, ' ').replace(/"/g, """).trim();
|
|
291
292
|
}
|
|
292
293
|
|
|
293
|
-
function _resolveCoreTerm(annotationTerm, annotationTermObject, csnDefsTargetObject) {
|
|
294
|
+
function _resolveCoreTerm(annotationTerm, annotationTermObject, csnDefsTargetObject, parserContext) {
|
|
294
295
|
if (annotationTerm === "@Core.Description" || annotationTerm === "@Core.LongDescription") {
|
|
295
296
|
// we don't capture `null` value for doc
|
|
296
297
|
if (annotationTermObject === null) return;
|
|
@@ -313,9 +314,10 @@ function _resolveCoreTerm(annotationTerm, annotationTermObject, csnDefsTargetObj
|
|
|
313
314
|
if (annotationTermObject === null) annotationTermObject = true;
|
|
314
315
|
|
|
315
316
|
if (annotationTerm === "@Core.OptionalParameter") {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
if (parserContext.beta) {
|
|
318
|
+
_updateElementObjectForDefaultValue(csnDefsTargetObject, annotationTermObject.DefaultValue);
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
319
321
|
_captureAnnotationInCSN(annotationTerm, annotationTermObject, csnDefsTargetObject);
|
|
320
322
|
}
|
|
321
323
|
}
|
|
@@ -403,13 +405,13 @@ function _parseValidationTerm(annotationTerm, annotationTermObject, csnDefsTarge
|
|
|
403
405
|
_captureAnnotationInCSN(annotationTerm, annotationTermObject, csnDefsTargetObject);
|
|
404
406
|
}
|
|
405
407
|
|
|
406
|
-
function _parseAnnotationTerms(annotationTerm, annotationTermObject, csnDefsTargetObject) {
|
|
408
|
+
function _parseAnnotationTerms(annotationTerm, annotationTermObject, csnDefsTargetObject, parserContext) {
|
|
407
409
|
const term = annotationTerm.split('.');
|
|
408
410
|
const vocabAlias = term[0];
|
|
409
411
|
|
|
410
412
|
switch (vocabAlias) {
|
|
411
413
|
case "@Core":
|
|
412
|
-
_resolveCoreTerm(annotationTerm, annotationTermObject, csnDefsTargetObject);
|
|
414
|
+
_resolveCoreTerm(annotationTerm, annotationTermObject, csnDefsTargetObject, parserContext);
|
|
413
415
|
break;
|
|
414
416
|
case "@Capabilities":
|
|
415
417
|
_parseCapabilitiesTerm(annotationTerm, annotationTermObject, csnDefsTargetObject);
|
|
@@ -458,7 +460,7 @@ function _captureAnnotationWithinElement(sourceObject, targetObject, parserConte
|
|
|
458
460
|
Object.keys(sourceObject).forEach(key => {
|
|
459
461
|
if (key.startsWith('@')) {
|
|
460
462
|
element = _resolveAnotationTerm(JSON.stringify(key), parserContext);
|
|
461
|
-
_parseAnnotationTerms(element, sourceObject[key], targetObject);
|
|
463
|
+
_parseAnnotationTerms(element, sourceObject[key], targetObject, parserContext);
|
|
462
464
|
}
|
|
463
465
|
});
|
|
464
466
|
}
|
|
@@ -1210,7 +1212,7 @@ function _parseAnnotations(schemaAnnotations, csnDefs, parserContext) {
|
|
|
1210
1212
|
let annotationTerms = schemaAnnotations[annotationTargetPath];
|
|
1211
1213
|
Object.keys(annotationTerms).forEach(annotationTerm => {
|
|
1212
1214
|
let annotationTermObject = schemaAnnotations[annotationTargetPath][annotationTerm];
|
|
1213
|
-
_parseAnnotationTerms(annotationTerm, annotationTermObject, csnDefsTargetObject);
|
|
1215
|
+
_parseAnnotationTerms(annotationTerm, annotationTermObject, csnDefsTargetObject, parserContext);
|
|
1214
1216
|
});
|
|
1215
1217
|
}
|
|
1216
1218
|
});
|
|
@@ -1684,7 +1686,12 @@ async function getEdmxv4CSN(edmx, ignorePersistenceSkip, mockServerUc, importerC
|
|
|
1684
1686
|
let name_space = [];
|
|
1685
1687
|
|
|
1686
1688
|
const parserContext = {};
|
|
1687
|
-
_initialize(parserContext
|
|
1689
|
+
_initialize(parserContext);
|
|
1690
|
+
parserContext.mockServerUc = mockServerUc;
|
|
1691
|
+
|
|
1692
|
+
if (importerContext.beta) {
|
|
1693
|
+
parserContext.beta = importerContext.beta
|
|
1694
|
+
}
|
|
1688
1695
|
|
|
1689
1696
|
if (importerContext.include_all_namespaces) {
|
|
1690
1697
|
name_space.push(true);
|
package/lib/index.js
CHANGED
|
@@ -46,9 +46,9 @@ class CdsDkAdd {
|
|
|
46
46
|
class CdsDkBuild {
|
|
47
47
|
get build() { return super.build = require('./build') }
|
|
48
48
|
}
|
|
49
|
-
if (process.argv[2] in {
|
|
49
|
+
if (process.argv[2] in { add:1, init:1, help:1 }) {
|
|
50
50
|
cds.extend (cds.constructor) .with (CdsDkAdd)
|
|
51
|
-
} else if (process.argv[2] in {
|
|
51
|
+
} else if (process.argv[2] in { build:1, deploy:1, push:1 }) {
|
|
52
52
|
cds.extend (cds.constructor) .with (CdsDkBuild)
|
|
53
53
|
}
|
|
54
54
|
|
package/lib/init/constants.js
CHANGED
|
@@ -4,7 +4,7 @@ module.exports = {
|
|
|
4
4
|
COMMAND_INIT: 'init',
|
|
5
5
|
COMMAND_ADD: 'add',
|
|
6
6
|
|
|
7
|
-
MAVEN_ARCHETYPE_VERSION: '2.7.
|
|
7
|
+
MAVEN_ARCHETYPE_VERSION: '2.7.1',
|
|
8
8
|
|
|
9
9
|
OPTIONS: Object.freeze({
|
|
10
10
|
JAVA: 'java',
|
|
@@ -35,6 +35,7 @@ module.exports = {
|
|
|
35
35
|
ENTERPRISE_MESSAGING: 'enterprise-messaging',
|
|
36
36
|
ENTERPRISE_MESSAGING_SHARED: 'enterprise-messaging-shared',
|
|
37
37
|
REDIS_MESSAGING: 'redis-messaging',
|
|
38
|
+
KAFKA: 'kafka',
|
|
38
39
|
APPROUTER: 'approuter',
|
|
39
40
|
DESTINATION: 'destination',
|
|
40
41
|
DATA: 'data',
|
package/lib/init/index.js
CHANGED
|
@@ -100,11 +100,11 @@ module.exports = class CDSGenerator {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
* @param {string} facets, comma separated list of
|
|
103
|
+
* @param {string} facets, comma separated list of facets
|
|
104
104
|
* @param {any} options, additional options
|
|
105
105
|
*/
|
|
106
|
-
async
|
|
107
|
-
if (!facets) throw 'You must specify a facet to add to the project.'
|
|
106
|
+
async add(facets) {
|
|
107
|
+
if (!facets?.length) throw 'You must specify a facet to add to the project.'
|
|
108
108
|
|
|
109
109
|
this._initialize(null);
|
|
110
110
|
this._greetings();
|
|
@@ -113,7 +113,7 @@ module.exports = class CDSGenerator {
|
|
|
113
113
|
throw `The current folder doesn't seem to contain a project. None of the following files found: ${PROJECT_FILES.join(', ')}.`
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
await this._process();
|
|
116
|
+
await this._process(facets);
|
|
117
117
|
await this.stepEnd();
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -170,11 +170,11 @@ module.exports = class CDSGenerator {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
async _process() {
|
|
173
|
+
async _process(facets) {
|
|
174
174
|
DEBUG?.(`Project path: ${cds.root}`);
|
|
175
175
|
|
|
176
176
|
await this._validateOptions();
|
|
177
|
-
await this._fillTemplateList();
|
|
177
|
+
await this._fillTemplateList(facets);
|
|
178
178
|
|
|
179
179
|
for (const template of this.templateList) {
|
|
180
180
|
console.log(`Adding feature '${template.name}'...`);
|
|
@@ -216,11 +216,11 @@ module.exports = class CDSGenerator {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
async _fillTemplateList() {
|
|
219
|
+
async _fillTemplateList(facets) {
|
|
220
220
|
const templates = new Map
|
|
221
|
-
const { command, options
|
|
221
|
+
const { command, options } = cds.cli
|
|
222
222
|
|
|
223
|
-
const plugins = command === COMMAND_INIT ? options.add : new Set(
|
|
223
|
+
const plugins = command === COMMAND_INIT ? options.add : new Set(facets)
|
|
224
224
|
|
|
225
225
|
for (let plugin of plugins) {
|
|
226
226
|
// Compat
|
|
@@ -299,20 +299,6 @@ module.exports = class CDSGenerator {
|
|
|
299
299
|
if (cds.cli.command === COMMAND_INIT && !options.add.has(JAVA)) {
|
|
300
300
|
options.add.add(NODEJS);
|
|
301
301
|
}
|
|
302
|
-
|
|
303
|
-
this._checkAdditionalOptions();
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
_checkAdditionalOptions() {
|
|
307
|
-
const { options } = cds.cli
|
|
308
|
-
for (const [key] of Object.entries(options)) {
|
|
309
|
-
const keySplit = key.split(/:/)
|
|
310
|
-
if (keySplit.length === 2) {
|
|
311
|
-
if (!options.add.has(keySplit[0])) {
|
|
312
|
-
console.log(`ignoring option ${key} since ${keySplit[0]} is not part of specified feature list: ${Array.from(options.add).join(', ')}`)
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
302
|
}
|
|
317
303
|
|
|
318
304
|
async _validateOptions() {
|
package/lib/init/mvn.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
const { URLS, MAVEN_ARCHETYPE_VERSION, OPTIONS: { JAVA_MVN, JAVA_PACKAGE,
|
|
2
|
+
const { URLS, MAVEN_ARCHETYPE_VERSION, OPTIONS: { JAVA_MVN, JAVA_PACKAGE, HANA }, REGEX_JAVA_PACKAGE } = require('./constants');
|
|
3
3
|
|
|
4
4
|
const cp = require('child_process');
|
|
5
5
|
const util = require('util');
|
|
@@ -143,10 +143,6 @@ class MvnArchetypeUtil {
|
|
|
143
143
|
params.set(`-DtargetPlatform`, `cloudfoundry`);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
const hasSamples = !!(options.add && options.add.has(SAMPLES));
|
|
147
|
-
params.set(`-DincludeModel`, hasSamples);
|
|
148
|
-
params.set(`-DincludeIntegrationTest`, hasSamples);
|
|
149
|
-
|
|
150
146
|
if (options[JAVA_MVN]) {
|
|
151
147
|
this._scanMvnParams(options[JAVA_MVN], params);
|
|
152
148
|
}
|
package/lib/init/plugin.js
CHANGED
|
@@ -10,6 +10,14 @@ module.exports = class Plugin {
|
|
|
10
10
|
this.name = this.constructor.name.replace(/template/i, '').replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Provides command-line options for the plugin.
|
|
15
|
+
* @returns {Array.<{option: string, flag: string, shortcut?: string, help: string}>}
|
|
16
|
+
*/
|
|
17
|
+
options() {
|
|
18
|
+
return []
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
/**
|
|
14
22
|
* Gets the required templates.
|
|
15
23
|
* @returns {string[]} An array of strings representing required plugins.
|
|
@@ -32,6 +32,11 @@ const enterpriseMessaging = {
|
|
|
32
32
|
where: { type: 'org.cloudfoundry.managed-service', 'parameters.service': 'enterprise-messaging' }
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
const kafkaMessaging = {
|
|
36
|
+
in: 'resources',
|
|
37
|
+
where: { type: 'org.cloudfoundry.managed-service', 'parameters.service': 'kafka' }
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
const applicationLogging = {
|
|
36
41
|
in: 'resources',
|
|
37
42
|
where: { type: 'org.cloudfoundry.managed-service', 'parameters.service': 'application-logs' }
|
|
@@ -144,6 +149,7 @@ module.exports = {
|
|
|
144
149
|
destination,
|
|
145
150
|
connectivity,
|
|
146
151
|
enterpriseMessaging,
|
|
152
|
+
kafkaMessaging,
|
|
147
153
|
hdbDeployer,
|
|
148
154
|
hdiContainer,
|
|
149
155
|
notificationTypesDeployer,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// const cds = require('../../../cds')
|
|
2
|
+
|
|
3
|
+
module.exports = async (data={}, csn, { headerOnly=false, queries=false, separator=',' }={}) => {
|
|
4
|
+
if (!queries) { // remove all projection-like entities
|
|
5
|
+
Object.keys(data)
|
|
6
|
+
.map(name => csn.definitions[name])
|
|
7
|
+
.filter (entity => entity.query)
|
|
8
|
+
.forEach(entity => { delete data[entity.name] })
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// We might need multiple passes if data for associations/compositions is created on the fly.
|
|
12
|
+
// So loop as long as there is some non-string data left.
|
|
13
|
+
while (Object.values(data).some(d => typeof d === 'object')) {
|
|
14
|
+
Object.entries(data)
|
|
15
|
+
.filter(([_, value]) => typeof value === 'object')
|
|
16
|
+
.map(([name]) => csn.definitions[name])
|
|
17
|
+
.forEach(entity => {
|
|
18
|
+
const entityData = data[entity.name]
|
|
19
|
+
const header = []
|
|
20
|
+
const records = []
|
|
21
|
+
for (let i = 0; i < entityData.length; i++) {
|
|
22
|
+
let record = []
|
|
23
|
+
for (const element of Object.values(entity.elements).sort(keyFirstSorter)) {
|
|
24
|
+
const name = element.name
|
|
25
|
+
let value = entityData[i][name]
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
continue
|
|
28
|
+
if (element._type === 'cds.Composition') {
|
|
29
|
+
data[element.target] = value // Add object for a new entity. Next pass will process it.
|
|
30
|
+
}
|
|
31
|
+
else if (element._type === 'cds.Association') {
|
|
32
|
+
if (i === 0) {
|
|
33
|
+
header.push(...Object.keys(value).map(foreignKey => name + '_' + foreignKey))
|
|
34
|
+
}
|
|
35
|
+
record.push(...Object.values(value))
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (i === 0) header.push(name)
|
|
39
|
+
if (typeof value === 'string' && (value.includes('"') || value.includes(separator)))
|
|
40
|
+
value = `"${value.replace(/"/g, '""')}"` // escape double quotes, then quote the value
|
|
41
|
+
record.push(value)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
records.push(record.join(separator))
|
|
45
|
+
}
|
|
46
|
+
let res = header.join(separator)
|
|
47
|
+
if (!headerOnly)
|
|
48
|
+
res += '\n' + records.join('\n')
|
|
49
|
+
|
|
50
|
+
data[entity.name] = res
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
return data
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function keyFirstSorter(e1, e2) {
|
|
57
|
+
if (e1.key && !e2.key) return -1
|
|
58
|
+
if (!e1.key && e2.key) return 1
|
|
59
|
+
return 0 // preserve original order otherwise
|
|
60
|
+
}
|