@sap/cds-dk 8.9.5 → 9.0.5
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 +101 -2012
- package/LICENSE +15 -21
- package/bin/bind.js +1 -1
- package/bin/build.js +35 -37
- package/bin/cds.js +13 -30
- package/bin/compile/index.js +2 -2
- package/bin/debug.js +27 -7
- package/bin/deploy/index.js +6 -23
- package/bin/deploy/to-hana.js +4 -2
- package/bin/help.js +5 -3
- package/bin/init.js +1 -1
- package/bin/up.js +45 -12
- package/bin/watch.js +45 -63
- package/lib/bind/cf.js +2 -1
- package/lib/bind/k8s.js +2 -2
- package/lib/bind/plugin.js +1 -1
- package/lib/bind/shared.js +16 -25
- package/lib/build/buildTaskEngine.js +26 -10
- package/lib/build/buildTaskFactory.js +3 -2
- package/lib/build/buildTaskProvider.js +18 -7
- package/lib/build/buildTaskProviderFactory.js +35 -13
- package/lib/build/constants.js +4 -0
- package/lib/build/index.js +1 -1
- package/lib/build/plugin.js +89 -54
- package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +3 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +4 -2
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/api-rule.yaml +4 -2
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +18 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/service-binding.yaml +0 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +34 -2
- package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +9 -2
- package/lib/build/plugins/helm/index.js +2 -1
- package/lib/build/plugins.js +24 -10
- package/lib/build/provider/edmxBuildPlugin.js +1 -11
- package/lib/build/provider/fiori/index.js +4 -4
- package/lib/build/provider/hana/index.js +12 -5
- package/lib/build/provider/hana/template/package.json +1 -1
- package/lib/build/provider/internalBuildPlugin.js +1 -1
- package/lib/build/provider/internalBuildTaskProvider.js +3 -24
- package/lib/build/provider/java/index.js +1 -1
- package/lib/build/provider/mtx-extension/index.js +15 -8
- package/lib/build/provider/nodejs/index.js +28 -6
- package/lib/build/util.js +186 -125
- package/lib/deploy/index.js +5 -0
- package/lib/deploy/to-hana/hana.js +27 -33
- package/lib/deploy/to-hana/hdiDeployUtil.js +2 -2
- package/lib/import/odata/v2parser.js +34 -3
- package/lib/import/openapi/importOpenAPI.js +4 -0
- package/lib/index.js +2 -11
- package/lib/init/constants.js +1 -2
- package/lib/init/merge.js +101 -77
- package/lib/init/mvn.js +3 -3
- package/lib/init/projectReader.js +1 -1
- package/lib/init/template/ams/files/mta.yaml.hbs +6 -1
- package/lib/init/template/ams/files/package.json.hbs +1 -1
- package/lib/init/template/approuter/files/mta.yaml.hbs +5 -0
- package/lib/init/template/cf-manifest/files/manifest.yml.hbs +1 -1
- package/lib/init/template/cloud-logging/files/package.json.hbs +3 -3
- package/lib/init/template/data/as-json.js +3 -3
- package/lib/init/template/dynatrace/files/mta.yaml.hbs +1 -1
- package/lib/init/template/dynatrace/files/package.json.hbs +2 -2
- package/lib/init/template/dynatrace/index.js +2 -1
- package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +6 -0
- package/lib/init/template/enterprise-messaging/index.js +5 -1
- package/lib/init/template/extensibility/files/package.json.hbs +1 -1
- package/lib/init/template/hana/files/db/package.json +1 -1
- package/lib/init/template/hana/files/package.json.hbs +2 -4
- package/lib/init/template/hana/index.js +2 -2
- package/lib/init/template/handler/index.js +16 -12
- package/lib/init/template/helm/index.js +13 -22
- package/lib/init/template/helm-unified-runtime/index.js +2 -1
- package/lib/init/template/html5-repo/files/values.yaml.hbs +12 -1
- package/lib/init/template/html5-repo/index.js +10 -5
- package/lib/init/template/http/index.js +1 -1
- package/lib/init/template/ias/files/mta.yaml.hbs +1 -1
- package/lib/init/template/ias/files/sidecar.package.json.hbs +0 -7
- package/lib/init/template/ias/index.js +5 -4
- package/lib/init/template/lint/files/package.json +6 -0
- package/lib/init/template/lint/index.js +61 -204
- package/lib/init/template/mta/files/package.json +1 -1
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +2 -2
- package/lib/init/template/multitenancy/files/package.json.hbs +1 -1
- package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -4
- package/lib/init/template/multitenancy/index.js +3 -0
- package/lib/init/template/nodejs/files/package.json.hbs +6 -3
- package/lib/init/template/postgres/files/package.json.hbs +1 -1
- package/lib/init/template/redis/files/package.json.hbs +1 -1
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +6 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +1 -0
- package/lib/init/template/sample/files/app/browse/fiori-service.cds +3 -2
- package/lib/init/template/sample/files/app/common.cds +0 -11
- package/lib/init/template/sqlite/files/package.json +1 -1
- package/lib/init/template/toggles/files/package.json.hbs +1 -1
- package/lib/init/template/typescript/files/package.json +2 -4
- package/lib/init/template/workzone-standard/index.js +2 -0
- package/lib/init/template/xsuaa/index.js +2 -6
- package/lib/lint/Linter.js +203 -331
- package/lib/lint/generators.js +52 -46
- package/lib/lint/io.js +77 -289
- package/lib/util/fs.js +2 -1
- package/lib/util/git.js +1 -1
- package/lib/util/glob.js +77 -0
- package/lib/watch/livereload-server.js +3 -4
- package/lib/watch/node-watch.js +3 -4
- package/lib/watch/watched.js +1 -1
- package/npm-shrinkwrap.json +200 -858
- package/package.json +6 -8
- package/readme.md +1 -1
- package/lib/lint/checks.js +0 -135
|
@@ -709,11 +709,42 @@ function _getServiceComplexTypes(parserContext) {
|
|
|
709
709
|
complexTypeKey = complexTypesKeys[i];
|
|
710
710
|
complexType = parserContext.allComplexTypes[complexTypeKey].Property;
|
|
711
711
|
isOpenType = parserContext.allComplexTypes[complexTypeKey].open;
|
|
712
|
-
|
|
712
|
+
|
|
713
|
+
//S4 might have actions or functions which return a complex type named like the action or function. In this case the complex type must be renamed as else a compile error happens as the result type cannot be found / is a function.
|
|
714
|
+
if (parserContext.allFunctionImports.some(fi => fi[0] === complexTypeKey)) {
|
|
715
|
+
const originalName = complexTypeKey;
|
|
716
|
+
const functionImport = parserContext.allFunctionImports.find(fi => fi[0] === complexTypeKey);
|
|
717
|
+
complexTypeKey = functionImport[0] + 'ReturnType';
|
|
718
|
+
let i = 1;
|
|
719
|
+
while (
|
|
720
|
+
parserContext.allFunctionImports.some(fi => fi[0] === complexTypeKey) ||
|
|
721
|
+
parserContext.allEntitySetMapMC[complexTypeKey] ||
|
|
722
|
+
parserContext.allEntitySetMap[_extractEntityFromNamespace(complexTypeKey)] ||
|
|
723
|
+
parserContext.allEntities.includes(_extractEntityFromNamespace(complexTypeKey))
|
|
724
|
+
) {
|
|
725
|
+
if (i > 1) {
|
|
726
|
+
complexTypeKey = complexTypeKey.slice(0, complexTypeKey.length-1)
|
|
727
|
+
}
|
|
728
|
+
complexTypeKey += i;
|
|
729
|
+
i++;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
//Rename complexType in parserContext for downstream FunctionImport logic
|
|
733
|
+
parserContext.allComplexTypes[complexTypeKey] = parserContext.allComplexTypes[originalName];
|
|
734
|
+
parserContext.allComplexTypes[complexTypeKey]['_attributes'].Name = complexTypeKey
|
|
735
|
+
delete parserContext.allComplexTypes[originalName]
|
|
736
|
+
//Correct Return Type of affected FunctionImports
|
|
737
|
+
const functionImportsWithWrongReturnType = parserContext.allFunctionImports.filter(fi => fi[2] === originalName || fi[2] === `Collection(${originalName})`);
|
|
738
|
+
for (const functionImport of functionImportsWithWrongReturnType) {
|
|
739
|
+
functionImport[2] = functionImport[2].replace(originalName, complexTypeKey);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
complexTypeCSN += _getServiceComplexType(complexTypeKey, complexType, parserContext, isOpenType);
|
|
713
744
|
if (i !== complexTypesKeys.length - 1) {
|
|
714
|
-
complexTypeCSN
|
|
745
|
+
complexTypeCSN += ",\n";
|
|
715
746
|
} else {
|
|
716
|
-
complexTypeCSN
|
|
747
|
+
complexTypeCSN += "\n";
|
|
717
748
|
}
|
|
718
749
|
}
|
|
719
750
|
return complexTypeCSN;
|
|
@@ -685,6 +685,10 @@ function structElements(context, type, schema) {
|
|
|
685
685
|
//TODO: check if property "name" already exists and has identical cdsType, warn otherwise
|
|
686
686
|
type.elements[name] = cdsType(context, propSchema);
|
|
687
687
|
if (name !== prop) type.elements[name]["@openapi.name"] = prop;
|
|
688
|
+
// Add @mandatory if the property is in the required array
|
|
689
|
+
if (schema.required && schema.required.includes(prop)) {
|
|
690
|
+
type.elements[name]["@mandatory"] = true;
|
|
691
|
+
}
|
|
688
692
|
}
|
|
689
693
|
}
|
|
690
694
|
|
package/lib/index.js
CHANGED
|
@@ -35,10 +35,11 @@ class CdsDk {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const REQUIRED_CDS_MAJOR =
|
|
38
|
+
const REQUIRED_CDS_MAJOR = 8, REQUIRED_CDS_MINOR = 3
|
|
39
39
|
const [major, minor] = cds.version.split('.').map(Number)
|
|
40
40
|
if (major < REQUIRED_CDS_MAJOR || major === REQUIRED_CDS_MAJOR && minor < REQUIRED_CDS_MINOR) {
|
|
41
41
|
const [dkVersion] = require('../package.json').version.split('.')
|
|
42
|
+
|
|
42
43
|
console.error(`
|
|
43
44
|
This application uses '@sap/cds' version ${major}.${minor}, which is not compatible with the installed '@sap/cds-dk' version ${dkVersion}.
|
|
44
45
|
You can either:
|
|
@@ -48,16 +49,6 @@ if (major < REQUIRED_CDS_MAJOR || major === REQUIRED_CDS_MAJOR && minor < REQUIR
|
|
|
48
49
|
process.exit(1)
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
const EXCLUDED_CDS_MAJOR = 9
|
|
52
|
-
if (major >= EXCLUDED_CDS_MAJOR) {
|
|
53
|
-
const [dkVersion] = require('../package.json').version.split('.')
|
|
54
|
-
console.error(`
|
|
55
|
-
This application uses '@sap/cds' version ${major}, which is not compatible with the installed '@sap/cds-dk' version ${dkVersion}.
|
|
56
|
-
Update '@sap/cds-dk' to the latest version.
|
|
57
|
-
`)
|
|
58
|
-
process.exit(1)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
52
|
cds.extend (cds.constructor) .with (CdsDk)
|
|
62
53
|
|
|
63
54
|
class CdsDkAdd {
|
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: '
|
|
8
|
+
MAVEN_ARCHETYPE_VERSION: '4.0.2',
|
|
9
9
|
|
|
10
10
|
OPTIONS: Object.freeze({
|
|
11
11
|
COMPLETION: 'completion',
|
|
@@ -61,7 +61,6 @@ module.exports = {
|
|
|
61
61
|
DATA: 'data',
|
|
62
62
|
HTTP: 'http',
|
|
63
63
|
LINT: 'lint',
|
|
64
|
-
LINT_GLOBAL: 'lint:global',
|
|
65
64
|
LINT_DEV: 'lint:dev',
|
|
66
65
|
PIPELINE: 'pipeline',
|
|
67
66
|
}),
|
package/lib/init/merge.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const { EOL } = require('node:os')
|
|
2
2
|
const { inspect } = require('node:util')
|
|
3
3
|
const cds = require('../cds')
|
|
4
|
-
const
|
|
4
|
+
const YAML = require('yaml')
|
|
5
|
+
const { copy, read, write, exists, path: {resolve, join} } = cds.utils
|
|
5
6
|
const { readYAML, writeYAML, readJSON } = require('../util/fs')
|
|
6
7
|
const { detectIndent } = require('./indent')
|
|
7
8
|
const { colors } = require('../util/term')
|
|
@@ -50,43 +51,7 @@ module.exports.mergeGitignore = async function(into, from) {
|
|
|
50
51
|
const enhanced = target.concat(source.filter(line => !target.includes(line)))
|
|
51
52
|
await write(into, enhanced.join(EOL))
|
|
52
53
|
return enhanced
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @typedef {Object} MatchedNode
|
|
57
|
-
* @property {string | MatchedNode} in - key path or matched node to start search from
|
|
58
|
-
* @property {Object} where - list of constraints
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @typedef {Object} Overwrites
|
|
63
|
-
* @property {(string | MatchedNode)[]} item - path to item to be overwritten
|
|
64
|
-
* @property {string} withValue - replacement string
|
|
65
|
-
*/
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @typedef {Object} Deletion
|
|
69
|
-
* @property {MatchedNode} item - matched node to delete
|
|
70
|
-
* @property {MatchedNode} [key] - key path to property to delete in node (optional)
|
|
71
|
-
* @property {Object[]} [relationships] - list of relationships to delete
|
|
72
|
-
* @property {string} relationships[].removeProperty - key path to to-be-removed property
|
|
73
|
-
* @property {string[]} relationships[].allWithin - key path to relationship
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @typedef {Object} Relationship
|
|
78
|
-
* @property {(string | MatchedNode)[]} insert - source path to matched node
|
|
79
|
-
* @property {(string | MatchedNode)[]} into - target path for inserted relationship
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @typedef {Object} MergingSemantics
|
|
84
|
-
* @property {boolean} [forceOverwrite] - overwrite values for existing keys
|
|
85
|
-
* @property {MatchedNode[]} [additions] - matched nodes to be added from source template
|
|
86
|
-
* @property {Overwrites[]} [overwrites] - matched keys to be overwritten with given string
|
|
87
|
-
* @property {Deletion[]} [deletions] - matched nodes to be deleted
|
|
88
|
-
* @property {Relationship[]} [relationships] - relationships to be inserted
|
|
89
|
-
*/
|
|
54
|
+
}
|
|
90
55
|
|
|
91
56
|
/**
|
|
92
57
|
* @param {string | JSON} into - file path or JSON to merge into
|
|
@@ -121,8 +86,8 @@ async function _mergeJSON(into, from, project, semantics) {
|
|
|
121
86
|
}
|
|
122
87
|
|
|
123
88
|
/**
|
|
124
|
-
* @param {string | YAML.Document} into - file path or YAML to merge into
|
|
125
|
-
* @param {string | YAML.Document} from - file path or YAML to merge from
|
|
89
|
+
* @param {string | YAML.Document | object} into - file path or YAML to merge into
|
|
90
|
+
* @param {string | YAML.Document | object} from - file path or YAML to merge from
|
|
126
91
|
* @param {Object} [project] - project descriptor used for Mustache replacements
|
|
127
92
|
* @param {MergingSemantics} [semantics] - merging algorithm semantics
|
|
128
93
|
* @returns {Promise<YAML.Document>} - merged YAML
|
|
@@ -169,11 +134,14 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
169
134
|
|
|
170
135
|
const _validateWhere = (node, dict, index) => {
|
|
171
136
|
const _addToMap = entries => entries?.filter(entry => {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
137
|
+
if (typeof entry.in === 'string') return true
|
|
138
|
+
if (typeof entry === 'string' && !entry.where) return false // no random access caching needed for pure key paths
|
|
139
|
+
if (Array.isArray(entry)) entry = entry[0]
|
|
140
|
+
const neededParent = dict.get(entry.in[0])?.node
|
|
141
|
+
return collectionStack.includes(neededParent) // lookbehind in parent collection stack
|
|
142
|
+
// REVISIT: Only look behind until sequence is reached?
|
|
176
143
|
}).forEach(item => {
|
|
144
|
+
if (Array.isArray(item)) item = item[0]
|
|
177
145
|
const json = JSON.parse(String(node))
|
|
178
146
|
const whereFulfilled = Object.entries(item.where).every(([key, value]) =>
|
|
179
147
|
_getProperty(json, key) === value
|
|
@@ -186,7 +154,7 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
186
154
|
if (additions) _addToMap(additions)
|
|
187
155
|
if (deletions) _addToMap(deletions.map(deletion => deletion.item))
|
|
188
156
|
if (relationships) _addToMap(relationships?.map(({into: [entry]}) => entry).filter(e => e))
|
|
189
|
-
if (overwrites) _addToMap(overwrites.map(overwrite => overwrite.item
|
|
157
|
+
if (overwrites) _addToMap(overwrites.map(overwrite => overwrite.item))
|
|
190
158
|
}
|
|
191
159
|
|
|
192
160
|
function _traverseYAMLNode(node, index, actions, templateNode) {
|
|
@@ -284,11 +252,23 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
284
252
|
overwrites?.forEach(({ item, withValue }) => {
|
|
285
253
|
const keyPath = Array.isArray(item) && typeof item[0] === 'string' ? item[0] : typeof item === 'string' ? item : item[1]
|
|
286
254
|
const inEntry = Array.isArray(item) && typeof item[0] === 'object' ? item[0] : typeof item === 'object' ? item : item[1]
|
|
287
|
-
|
|
255
|
+
let node
|
|
256
|
+
if (inEntry && entryMap.get(inEntry)) {
|
|
257
|
+
node = entryMap.get(inEntry).node // starting from item found in nested array cache
|
|
258
|
+
} else {
|
|
259
|
+
node = collectionStack[collectionStack.length - 1] // starting from root
|
|
260
|
+
}
|
|
288
261
|
const keys = keyPath.split('.')
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
262
|
+
for (const key of keys.slice(0, -1)) {
|
|
263
|
+
if (!node?.get(key) && typeof inEntry === 'string') return // node doesn't exist, will be added by template
|
|
264
|
+
node = node?.get(key) ?? node
|
|
265
|
+
}
|
|
266
|
+
const tail = keys.pop()
|
|
267
|
+
if (!node.get(tail)) {
|
|
268
|
+
node.add({ key: tail, value: withValue })
|
|
269
|
+
} else {
|
|
270
|
+
node.set(tail, withValue)
|
|
271
|
+
}
|
|
292
272
|
})
|
|
293
273
|
|
|
294
274
|
// 4. Delete entries from the project (e.g. separate deployer module when adding mtx)
|
|
@@ -335,7 +315,7 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
335
315
|
})
|
|
336
316
|
.filter(item => !entryMap.get(item))
|
|
337
317
|
.forEach(item => {
|
|
338
|
-
if (!templateEntryMap.get(item)) throw 'Error: did not find entry in template for ' + inspect(item, { colors, depth:11 }) + ' in ' + from
|
|
318
|
+
if (!templateEntryMap.get(item)) throw 'Error: did not find entry in template for ' + inspect(item, { colors, depth:11 }) + ' in \n' + from
|
|
339
319
|
const templateNode = templateEntryMap.get(item).node
|
|
340
320
|
item.at !== undefined ? targetNode.items.splice(item.at, 0, templateNode) : targetNode.add(templateNode)
|
|
341
321
|
})
|
|
@@ -352,36 +332,42 @@ async function _mergeYAML(into, from, project, semantics = {}) {
|
|
|
352
332
|
// 7. Create missing relationships
|
|
353
333
|
_traverseYAMLNode(target.contents, null, {
|
|
354
334
|
mergeCollection: (targetNode, templateNode) => {
|
|
355
|
-
|
|
335
|
+
if (!YAML.isSeq(templateNode)) return
|
|
356
336
|
const targetJSON = YAML.parse(String(targetNode))
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
337
|
+
for (const { insert, into } of semantics.relationships ?? []) {
|
|
338
|
+
const [first, ...rest] = into
|
|
339
|
+
const seqPath = rest.find(x => typeof x === 'string') || ''
|
|
340
|
+
const keyPath = rest.length > 1 ? rest.at(-1) : null
|
|
341
|
+
const base = entryMap.get(first)
|
|
342
|
+
if (!base) continue
|
|
343
|
+
const seqNode = seqPath ? _getYAMLProperty(base.node, seqPath) : base.node
|
|
344
|
+
if (seqNode !== targetNode) continue
|
|
345
|
+
const inserts = Array.isArray(insert) ? insert : [insert]
|
|
346
|
+
for (const ins of inserts) {
|
|
347
|
+
const insEntry = entryMap.get(ins)
|
|
348
|
+
if (!insEntry) continue
|
|
349
|
+
const srcNode = insEntry.node, srcJson = insEntry.json
|
|
350
|
+
let key = keyPath
|
|
351
|
+
if (!key && srcNode.get && srcNode.get('name')) key = 'name'
|
|
352
|
+
let cand, duplicate
|
|
353
|
+
if (key) {
|
|
354
|
+
const val = _getProperty(srcJson, key)
|
|
355
|
+
cand = templateNode.items.find(i => YAML.isMap(i) && i.get(key) === val) || { [key]: val }
|
|
356
|
+
duplicate = targetJSON.some(t => t?.[key] === val)
|
|
357
|
+
} else {
|
|
358
|
+
cand = templateNode.items.find(i => JSON.stringify(YAML.parse(String(i))) === JSON.stringify(YAML.parse(String(srcNode)))) || srcNode
|
|
359
|
+
const srcObj = YAML.parse(String(cand))
|
|
360
|
+
duplicate = targetJSON.some(t => JSON.stringify(t) === JSON.stringify(srcObj))
|
|
361
|
+
}
|
|
362
|
+
if (!duplicate) {
|
|
363
|
+
const clone = YAML.parse(YAML.stringify(cand))
|
|
364
|
+
targetNode.add(clone)
|
|
365
|
+
targetJSON.push(clone)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
381
368
|
}
|
|
382
|
-
}
|
|
383
369
|
}
|
|
384
|
-
|
|
370
|
+
}, source.contents)
|
|
385
371
|
|
|
386
372
|
typeof into === 'string' && await writeYAML(into, target)
|
|
387
373
|
return target
|
|
@@ -456,3 +442,41 @@ module.exports.merge = (...src) => {
|
|
|
456
442
|
}
|
|
457
443
|
}
|
|
458
444
|
}
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @typedef {Object} MatchedNode
|
|
449
|
+
* @property {string | MatchedNode} in - key path or matched node to start search from
|
|
450
|
+
* @property {Object} where - list of constraints
|
|
451
|
+
*/
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* @typedef {Object} Overwrites
|
|
455
|
+
* @property {(string | MatchedNode)[]} item - path to item to be overwritten
|
|
456
|
+
* @property {string} withValue - replacement string
|
|
457
|
+
*/
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* @typedef {Object} Deletion
|
|
461
|
+
* @property {MatchedNode} item - matched node to delete
|
|
462
|
+
* @property {MatchedNode} [key] - key path to property to delete in node (optional)
|
|
463
|
+
* @property {Object[]} [relationships] - list of relationships to delete
|
|
464
|
+
* @property {string} relationships[].removeProperty - key path to to-be-removed property
|
|
465
|
+
* @property {string[]} relationships[].allWithin - key path to relationship
|
|
466
|
+
*/
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* @typedef {Object} Relationship
|
|
470
|
+
* @property {(string | MatchedNode)[]} insert - source path to matched node
|
|
471
|
+
* @property {(string | MatchedNode)[]} into - target path for inserted relationship
|
|
472
|
+
*/
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* @typedef {Object} MergingSemantics
|
|
476
|
+
* @property {boolean} [forceOverwrite] - overwrite values for existing keys
|
|
477
|
+
* @property {MatchedNode[]} [additions] - matched nodes to be added from source template
|
|
478
|
+
* @property {Overwrites[]} [overwrites] - matched keys to be overwritten with given string
|
|
479
|
+
* @property {Deletion[]} [deletions] - matched nodes to be deleted
|
|
480
|
+
* @property {Relationship[]} [relationships] - relationships to be inserted
|
|
481
|
+
*/
|
|
482
|
+
|
package/lib/init/mvn.js
CHANGED
|
@@ -156,15 +156,15 @@ function _scan(mvnParams) {
|
|
|
156
156
|
// a=[x,y,z] => a:x,y,z
|
|
157
157
|
const quoteRegex = /([\w\-.]+)=([\w\-.]+|\[([\w.\-,]+)\])/g
|
|
158
158
|
return [...mvnParams.matchAll(quoteRegex)].map(([,key,value,listValues]) => {
|
|
159
|
-
key = key.startsWith('-
|
|
159
|
+
key = key.startsWith('-') ? key : `-${key}`
|
|
160
160
|
return [key, listValues || value]
|
|
161
161
|
})
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
function _finalize(params) {
|
|
165
165
|
params.set(`-Dstyle.color`, `always`)
|
|
166
|
-
if (LOG._debug) params.set('-X')
|
|
167
|
-
if (LOG._debug) params.set('-e')
|
|
166
|
+
if (LOG._debug && !params.has('-X')) params.set('-X')
|
|
167
|
+
if (LOG._debug && !params.has('-e')) params.set('-e')
|
|
168
168
|
if (process.env.CI) params.set('--batch-mode')
|
|
169
169
|
const final = Array.from(params, ([arg, val]) => val !== null && val !== undefined ? `${arg}=${val}` : arg)
|
|
170
170
|
DEBUG?.(term.highlight('mvn ' + final.join(' ')))
|
|
@@ -194,7 +194,7 @@ module.exports = new class ProjectReader {
|
|
|
194
194
|
hasUI5: _ui5,
|
|
195
195
|
hasMTXRoute: () => _inProd('extensibility') || (_inProd('multitenancy') && !_isJava()),
|
|
196
196
|
hasMTXRouteJava: () => (_inProd('helm-unified-runtime') || _inProd('helm')) && _isJava() && _inProd('multitenancy'),
|
|
197
|
-
imageRegistry: () => exists('chart/values.yaml') ? cds.load.yaml(join(cds.root, 'chart/values.yaml')).global?.image?.registry ?? '<your-container-registry>' : '<your-container-registry>',
|
|
197
|
+
imageRegistry: () => exists('chart/values.yaml') ? cds.load.yaml(join(cds.root, 'chart/values.yaml')).global?.image?.registry ?? '<your-container-registry-server>' : '<your-container-registry-server>',
|
|
198
198
|
extendsApp: _extends,
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -10,7 +10,12 @@ modules:
|
|
|
10
10
|
- name: {{appName}}-ams-policies-deployer
|
|
11
11
|
type: javascript.nodejs
|
|
12
12
|
{{#isJava}}
|
|
13
|
-
path:
|
|
13
|
+
path: .
|
|
14
|
+
build-parameters:
|
|
15
|
+
builder: custom
|
|
16
|
+
commands:
|
|
17
|
+
- npx cds build --for ams
|
|
18
|
+
build-result: srv/src/gen/policies
|
|
14
19
|
{{/isJava}}
|
|
15
20
|
{{^isJava}}
|
|
16
21
|
path: gen/policies
|
|
@@ -72,6 +72,8 @@ modules:
|
|
|
72
72
|
resources:
|
|
73
73
|
- name: {{appName}}-auth
|
|
74
74
|
type: org.cloudfoundry.managed-service
|
|
75
|
+
requires:
|
|
76
|
+
- name: app-api
|
|
75
77
|
parameters:
|
|
76
78
|
service: xsuaa
|
|
77
79
|
service-plan: application
|
|
@@ -79,3 +81,6 @@ resources:
|
|
|
79
81
|
config:
|
|
80
82
|
xsappname: {{appName}}-${org}-${space}
|
|
81
83
|
tenant-mode: {{#hasMultitenancy}}shared{{/hasMultitenancy}}{{^hasMultitenancy}}dedicated{{/hasMultitenancy}}
|
|
84
|
+
oauth2-configuration:
|
|
85
|
+
redirect-uris:
|
|
86
|
+
- https://~{app-api/app-uri}/**
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@cap-js/telemetry": ">=0",
|
|
4
4
|
"@grpc/grpc-js": "^1",
|
|
5
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "
|
|
6
|
-
"@opentelemetry/exporter-metrics-otlp-grpc": "
|
|
7
|
-
"@opentelemetry/host-metrics": "
|
|
5
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "<0.200",
|
|
6
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "<0.200",
|
|
7
|
+
"@opentelemetry/host-metrics": "<0.200"
|
|
8
8
|
},
|
|
9
9
|
"cds": {
|
|
10
10
|
"requires": {
|
|
@@ -228,10 +228,10 @@ function dataForField(element, artifact, csn, record, data, parent, depth, refer
|
|
|
228
228
|
return randomIntInRange(range)
|
|
229
229
|
}
|
|
230
230
|
case 'cds.hana.REAL':
|
|
231
|
-
case 'cds.Decimal': {
|
|
232
|
-
const prec = element.precision ? Math.min(Math.pow(10, element.precision), Number.MAX_SAFE_INTEGER) : 100
|
|
233
|
-
const range = { from: 0, to: prec }
|
|
231
|
+
case 'cds.Decimal': { // Decimal(9,5), Decimal(9), Decimal(precision:5)
|
|
234
232
|
const scale = element.scale ?? (element.precision ? 0 : 2) // scale is 0 if only precision is given
|
|
233
|
+
const prec = element.precision ? Math.min(Math.pow(10, element.precision-scale), Number.MAX_SAFE_INTEGER) : 100
|
|
234
|
+
const range = { from: 0, to: prec }
|
|
235
235
|
annotatedIntRange(element, range)
|
|
236
236
|
return +(randomDecimalInRange(range).toFixed(scale))
|
|
237
237
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@cap-js/telemetry": ">=0",
|
|
4
|
-
"@opentelemetry/exporter-metrics-otlp-proto": "
|
|
5
|
-
"@opentelemetry/host-metrics": "
|
|
4
|
+
"@opentelemetry/exporter-metrics-otlp-proto": "<0.200"{{#hasHelm}},
|
|
5
|
+
"@opentelemetry/host-metrics": "<0.200"
|
|
6
6
|
{{/hasHelm}}
|
|
7
7
|
},
|
|
8
8
|
"cds": {
|
|
@@ -24,7 +24,7 @@ module.exports = class extends require('../../plugin') {
|
|
|
24
24
|
|
|
25
25
|
async combine() {
|
|
26
26
|
const project = readProject()
|
|
27
|
-
const { hasMta, hasHelm, hasHelmUnifiedRuntime, isJava, hasMultitenancy, srvPath } = project
|
|
27
|
+
const { appName, hasMta, hasHelm, hasHelmUnifiedRuntime, isJava, hasMultitenancy, srvPath } = project
|
|
28
28
|
|
|
29
29
|
if (hasMta) {
|
|
30
30
|
const dynatrace = {
|
|
@@ -48,6 +48,7 @@ module.exports = class extends require('../../plugin') {
|
|
|
48
48
|
into: [mtxSidecar, 'requires', 'name']
|
|
49
49
|
})
|
|
50
50
|
}
|
|
51
|
+
project.uppercaseStrippedAppName = appName.replace(/-/g, '').toUpperCase().slice(0, 16),
|
|
51
52
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
52
53
|
with: project, additions, relationships
|
|
53
54
|
})
|
|
@@ -2,7 +2,7 @@ const cds = require('../../../cds')
|
|
|
2
2
|
const { read, yaml: YAML } = cds.utils
|
|
3
3
|
const { readProject } = require('../../projectReader')
|
|
4
4
|
const { merge } = require('../../merge')
|
|
5
|
-
const { srv4, enterpriseMessaging } = require('../../registries/mta')
|
|
5
|
+
const { srv4, enterpriseMessaging, xsuaa } = require('../../registries/mta')
|
|
6
6
|
|
|
7
7
|
module.exports = class EnterpriseMessagingTemplate extends require('../../plugin') {
|
|
8
8
|
|
|
@@ -58,6 +58,10 @@ module.exports = class EnterpriseMessagingTemplate extends require('../../plugin
|
|
|
58
58
|
|
|
59
59
|
if (hasXsuaa) {
|
|
60
60
|
if (hasMta) {
|
|
61
|
+
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
62
|
+
project,
|
|
63
|
+
additions: [xsuaa]
|
|
64
|
+
})
|
|
61
65
|
project['em-service-name'] = YAML.parse(await read('mta.yaml'))?.resources?.find(r => r?.parameters?.service === 'enterprise-messaging')?.name
|
|
62
66
|
} else {
|
|
63
67
|
project['em-service-name'] = `${appName}-messaging`
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"node": "^22.0.0"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"start": "node node_modules/@sap/hdi-deploy/deploy.js --use-hdb",
|
|
11
|
+
"start": "node node_modules/@sap/hdi-deploy/deploy.js --use-hdb --parameter com.sap.hana.di.table/try_fast_table_migration=true",
|
|
12
12
|
"build": "npm i && npx cds build .. --for hana --production"
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -13,8 +13,8 @@ module.exports = class HanaTemplate extends require('../../plugin') {
|
|
|
13
13
|
return 'database support for SAP HANA'
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
static hasInProduction(
|
|
17
|
-
return
|
|
16
|
+
static hasInProduction() {
|
|
17
|
+
return readProject().dependencies?.['@cap-js/hana']
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
async run() {
|
|
@@ -145,7 +145,7 @@ async function createExtCodeHandler(service, proj, out, force) {
|
|
|
145
145
|
// package.json
|
|
146
146
|
const pkgJson = await read('package.json')
|
|
147
147
|
const pkgJsonDelta = require('./files/extension/package.json')
|
|
148
|
-
|
|
148
|
+
cds.utils.merge ? cds.utils.merge(pkgJson, pkgJsonDelta) : merge(pkgJson, pkgJsonDelta)
|
|
149
149
|
await write('package.json', pkgJson, { spaces: 2 })
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -161,15 +161,19 @@ async function loadModel() {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
164
|
+
// TODO remove w/ cds 10, copied from cds-utils.js
|
|
165
|
+
/**
|
|
166
|
+
* Polyfill for cds.utils.merge
|
|
167
|
+
* Simple helper to deep-merge two or more objects.
|
|
168
|
+
* Entries from `xs` overwrite entries in `o`.
|
|
169
|
+
* @example cds.utils.merge({foo:1},{bar:2},{baz:3})
|
|
170
|
+
* @returns `o` with entries from `xs` merged in.
|
|
171
|
+
*/
|
|
172
|
+
function merge (o,...xs) {
|
|
173
|
+
let v; for (let x of xs) for (let k in x)
|
|
174
|
+
if (k === '__proto__' || k === 'constructor') continue //> avoid prototype pollution
|
|
175
|
+
else o[k] = is_object(v=x[k]) ? merge(o[k]??={},v) : v
|
|
176
|
+
return o
|
|
175
177
|
}
|
|
178
|
+
const is_object = x => typeof x === 'object' && x !== null && !is_array(x)
|
|
179
|
+
const is_array = Array.isArray
|