@sap/cds-dk 6.2.3 → 6.3.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/CHANGELOG.md +27 -0
- package/bin/bind.js +4 -4
- package/bin/deploy/to-h2.js +4 -0
- package/bin/deploy/to-sqlite.js +6 -4
- package/bin/help.js +1 -1
- package/bin/login.js +1 -0
- package/bin/push.js +29 -7
- package/lib/bind/userCdsrcJsonStorageProvider.js +4 -4
- package/lib/client/activate.js +1 -1
- package/lib/client/base_command.js +10 -10
- package/lib/client/helper/dependency_helper.js +10 -1
- package/lib/client/helper/logging.js +6 -2
- package/lib/client/pull.js +6 -6
- package/lib/client/push.js +33 -14
- package/lib/client/settings_manager.js +52 -21
- package/lib/compile/openapi/csdl2openapi.js +1 -1
- package/lib/compile/to-xsuaa.js +1 -1
- package/lib/import/odata/v2parser.js +37 -1
- package/lib/import/odata/v4parser.js +101 -23
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +23 -45
- package/lib/init/template/approuter/index.js +44 -48
- package/lib/init/template/auditlog/index.js +14 -10
- package/lib/init/template/cf-manifest/index.js +9 -11
- package/lib/init/template/connectivity/index.js +10 -10
- package/lib/init/template/data/index.js +20 -19
- package/lib/init/template/destinations/index.js +14 -9
- package/lib/init/template/enterprise-messaging/index.js +14 -9
- package/lib/init/template/extensibility/index.js +14 -9
- package/lib/init/template/hana/index.js +51 -57
- package/lib/init/template/helm/index.js +27 -59
- package/lib/init/template/helm/subchart/templates/_helpers.tpl +38 -0
- package/lib/init/template/helm/subchart/templates/deployment.yaml +12 -12
- package/lib/init/template/helm/subchart/values.md +565 -194
- package/lib/init/template/helm/subchart/values.schema.json +163 -8
- package/lib/init/template/helm/subchart/values.yaml +17 -1
- package/lib/init/template/html5-repo/index.js +15 -11
- package/lib/init/template/java/index.js +15 -11
- package/lib/init/template/kibana-logging/index.js +30 -31
- package/lib/init/template/lint/index.js +17 -18
- package/lib/init/template/mta/index.js +18 -40
- package/lib/init/template/mtx/index.js +2 -3
- package/lib/init/template/multitenancy/index.js +27 -20
- package/lib/init/template/nodejs/index.js +18 -20
- package/lib/init/template/notebook/index.js +5 -434
- package/lib/init/template/pipeline/index.js +10 -10
- package/lib/init/template/samples/index.js +7 -16
- package/lib/init/template/templateBase.js +17 -18
- package/lib/init/template/toggles/files/cdsrc.json +5 -0
- package/lib/init/template/toggles/files/cdsrc.json.hbs +7 -0
- package/lib/init/template/toggles/index.js +12 -6
- package/lib/init/template/xsuaa/index.js +44 -41
- package/lib/init/types.d.ts +0 -59
- package/lib/init/util/commandUtil.js +6 -7
- package/lib/init/util/fsUtil.js +23 -109
- package/lib/init/util/merge.js +319 -0
- package/lib/init/util/mvnArchetypeUtil.js +6 -5
- package/lib/init/util/projectReader.js +125 -300
- package/lib/init/util/spinner.js +10 -8
- package/lib/init/util/templateUtil.js +25 -368
- package/lib/lint/Linter.js +2 -3
- package/lib/lint/checks.js +0 -1
- package/lib/lint/io.js +18 -34
- package/npm-shrinkwrap.json +102 -239
- package/package.json +3 -3
- package/lib/init/template/notebook/cap_magic.py +0 -118
- package/lib/init/template/notebook/files/{{{name}}}.ipynb.hbs +0 -90
- package/lib/init/template/notebook/files/{{{name}}}.json +0 -102
- package/lib/init/template/notebook/notebook.js +0 -394
- package/lib/init/util/logger.js +0 -42
|
@@ -1,375 +1,32 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const templatePath = this._getTemplatePath(template);
|
|
18
|
-
|
|
19
|
-
const files = await this.fsUtil.readdir(templatePath);
|
|
20
|
-
for (const file of files) {
|
|
21
|
-
const fileNew = Mustache.render(file, templateValues);
|
|
22
|
-
const src = path.join(templatePath, file);
|
|
23
|
-
const dest = path.join(destinationPath, fileNew);
|
|
24
|
-
|
|
25
|
-
const stat = await this.fsUtil.stat(src);
|
|
26
|
-
if (stat.isDirectory()) {
|
|
27
|
-
await this.copyFiles(path.join(template, file), dest, templateValues, overwrite);
|
|
28
|
-
} else if (this._isTemplateFile(file)) {
|
|
29
|
-
await this._writeTemplateFile(src, dest, templateValues, overwrite);
|
|
30
|
-
} else {
|
|
31
|
-
await this.fsUtil.copy(src, dest);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async sortDependencies(packageJSONPath) {
|
|
37
|
-
const json = await this.fsUtil.readJSON(packageJSONPath);
|
|
38
|
-
json.dependencies = Object.fromEntries(
|
|
39
|
-
Object.entries(json.dependencies).sort(([a],[b]) => a>b ? 1 : -1)
|
|
40
|
-
)
|
|
41
|
-
await this.fsUtil.writeJSON(packageJSONPath, json);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async _writeTemplateFile(src, destination, templateValues, overwrite = false) {
|
|
45
|
-
const destinationPath = destination.replace(TEMPLATE_EXTENSION_REGEX, '');
|
|
46
|
-
if (overwrite || !(await this.fsUtil.pathExists(destinationPath))) {
|
|
47
|
-
const content = await this._processTemplateFile(src, templateValues);
|
|
48
|
-
await this.fsUtil.writeFile(destinationPath, content);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async _processTemplateFile(src, templateValues) {
|
|
53
|
-
const content = await this.fsUtil.readFile(src);
|
|
54
|
-
return Mustache.render(content, templateValues);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
_getTemplatePath(templatePath) {
|
|
58
|
-
return path.join(this.templateRoot, templatePath);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
_isTemplateFile(filename) {
|
|
62
|
-
return path.extname(filename) === TEMPLATE_EXTENSION;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/*
|
|
66
|
-
Will do a syntactic merge when `semantics` is undefined.
|
|
67
|
-
Syntactic merges are sufficient in some cases,
|
|
68
|
-
e.g merging dependencies in a package.json, as they are
|
|
69
|
-
just maps where you can do a key-value replacement.
|
|
70
|
-
*/
|
|
71
|
-
_deepMerge(target, source) {
|
|
72
|
-
const unique = array => [...new Set(array.map(JSON.stringify))].map(JSON.parse)
|
|
73
|
-
if (this._isObject(target) && this._isObject(source)) {
|
|
74
|
-
for (const key in source) {
|
|
75
|
-
if (this._isObject(source[key])) {
|
|
76
|
-
if (!target[key]) Object.assign(target, { [key]: source[key] })
|
|
77
|
-
else this._deepMerge(target[key], source[key])
|
|
78
|
-
} else if (Array.isArray(source[key]) && Array.isArray(target[key])) {
|
|
79
|
-
target[key] = unique([...source[key], ...target[key]])
|
|
80
|
-
} else {
|
|
81
|
-
Object.assign(target, { [key]: target[key] || source[key] })
|
|
82
|
-
}
|
|
1
|
+
const Mustache = require('mustache')
|
|
2
|
+
const { copy, read, write, exists, readdir, path, isdir } = require('../../cds').utils
|
|
3
|
+
|
|
4
|
+
async function copyFiles(templatePath, destinationPath, templateValues, overwrite = false) {
|
|
5
|
+
for (const dirent of await readdir(templatePath)) {
|
|
6
|
+
const fileNew = Mustache.render(dirent, templateValues)
|
|
7
|
+
const src = path.join(templatePath, dirent);
|
|
8
|
+
const dest = path.join(destinationPath, fileNew);
|
|
9
|
+
|
|
10
|
+
if (isdir(src)) {
|
|
11
|
+
await copyFiles(path.join(templatePath, dirent), dest, templateValues, overwrite);
|
|
12
|
+
} else if (path.extname(dirent) === '.hbs') {
|
|
13
|
+
const destinationPath = dest.replace('.hbs', '');
|
|
14
|
+
if (overwrite || !exists(destinationPath)) {
|
|
15
|
+
const content = await render(src, templateValues);
|
|
16
|
+
await write(destinationPath, content, { spaces: 2 });
|
|
83
17
|
}
|
|
84
|
-
} else if (Array.isArray(target) && Array.isArray(source)) {
|
|
85
|
-
target = unique([...source, ...target])
|
|
86
|
-
}
|
|
87
|
-
return target || source
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async mergeJSON(targetPath, from, projectDescriptor, semantics) {
|
|
91
|
-
const source = typeof from === 'string' ? await this.fsUtil.readJSON(from, projectDescriptor) : from
|
|
92
|
-
|
|
93
|
-
if (! await this.fsUtil.pathExists(targetPath)) {
|
|
94
|
-
await this.fsUtil.writeJSON(targetPath, source)
|
|
95
|
-
} else if (semantics) {
|
|
96
|
-
const target = await this.fsUtil.readJSON(targetPath)
|
|
97
|
-
|
|
98
|
-
if (!target) return // Has no JSON file
|
|
99
|
-
|
|
100
|
-
const targetYAML = await YAML.parseDocument(YAML.stringify(target))
|
|
101
|
-
const sourceYAML = await YAML.parseDocument(YAML.stringify(source))
|
|
102
|
-
const resultYAML = await this.mergeYAML(targetYAML, sourceYAML, projectDescriptor, semantics)
|
|
103
|
-
const result = YAML.parse(YAML.stringify(resultYAML))
|
|
104
|
-
await this.fsUtil.writeJSON(targetPath, result)
|
|
105
18
|
} else {
|
|
106
|
-
|
|
107
|
-
const sourceFile = await this._processTemplateFile(from, projectDescriptor)
|
|
108
|
-
const source = JSON.parse(sourceFile)
|
|
109
|
-
const result = target && source ? this._deepMerge(target, source) : target || source
|
|
110
|
-
await this.fsUtil.writeJSON(targetPath, result)
|
|
19
|
+
await copy(src, dest);
|
|
111
20
|
}
|
|
112
21
|
}
|
|
22
|
+
}
|
|
113
23
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
new YAML.Document(into)
|
|
119
|
-
const source =
|
|
120
|
-
typeof from === 'string' ? await this.fsUtil.readYAML(from, projectDescriptor)
|
|
121
|
-
: from instanceof YAML.Document ? from :
|
|
122
|
-
new YAML.Document(from)
|
|
123
|
-
|
|
124
|
-
if (!target || !target.contents) {
|
|
125
|
-
if (typeof into === 'string' && typeof from === 'string') {
|
|
126
|
-
return projectDescriptor ? this.fsUtil.writeYAML(into, source) : fs.copy(from, into)
|
|
127
|
-
}
|
|
128
|
-
return /* has no YAML */
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const existenceMap = new Map()
|
|
132
|
-
const templateExistenceMap = new Map()
|
|
133
|
-
|
|
134
|
-
const { additions, overwrites, deletions, relationships } = semantics
|
|
135
|
-
additions?.forEach(existence => {
|
|
136
|
-
existenceMap.set(existence.ref, undefined)
|
|
137
|
-
templateExistenceMap.set(existence.ref, undefined)
|
|
138
|
-
})
|
|
139
|
-
deletions?.forEach(deletion => {
|
|
140
|
-
existenceMap.set(deletion.item.ref, undefined)
|
|
141
|
-
})
|
|
142
|
-
relationships?.forEach(relationship => {
|
|
143
|
-
const [existence] = relationship.into
|
|
144
|
-
const [insertExistence] = relationship.insert
|
|
145
|
-
const ref = insertExistence.ref + ' -> ' + existence.ref
|
|
146
|
-
existenceMap.set(ref, undefined)
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
let collectionStack = [target.contents]
|
|
150
|
-
|
|
151
|
-
const _getProperty = (object, keyPath) => keyPath.split('.').reduce((p, k) => p && p[k], object)
|
|
152
|
-
const _getYAMLProperty = (object, keyPath) => keyPath.split('.').reduce((p, k) => p && p.get(k), object)
|
|
153
|
-
|
|
154
|
-
const _validateWhere = (node, dict, index) => {
|
|
155
|
-
const _addToMap = existences => existences?.filter(existence => {
|
|
156
|
-
let where = existence.in
|
|
157
|
-
if (typeof where === 'string') return true // just a key path on the document root
|
|
158
|
-
else where = where[0] // a more complex list of constraints, a sequence/array is involved
|
|
159
|
-
const neededParent = dict.get(where.ref)?.node
|
|
160
|
-
return collectionStack.includes(neededParent) // lookbehind in parent collection stack
|
|
161
|
-
// REVISIT: Only look behind until sequence is reached?
|
|
162
|
-
}).forEach(({ where, ref }) => {
|
|
163
|
-
const json = JSON.parse(String(node))
|
|
164
|
-
const whereFulfilled = where.every(constraint =>
|
|
165
|
-
constraint.isEqualTo === _getProperty(json, constraint.property)
|
|
166
|
-
)
|
|
167
|
-
if (whereFulfilled) {
|
|
168
|
-
const [collection] = collectionStack
|
|
169
|
-
dict.set(ref, { json, node, index, collection })
|
|
170
|
-
}
|
|
171
|
-
})
|
|
172
|
-
if (additions) _addToMap(additions)
|
|
173
|
-
if (deletions) _addToMap(deletions.map(deletion => deletion.item))
|
|
174
|
-
if (relationships) _addToMap(relationships?.map(({into: [existence]}) => existence).filter(e => e))
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function _traverseYAMLNode(node, index, actions, templateNode) {
|
|
178
|
-
let shifted = false
|
|
179
|
-
if (YAML.isMap(node)) {
|
|
180
|
-
actions?.visitMap && actions.visitMap(node, index)
|
|
181
|
-
const [collection] = collectionStack
|
|
182
|
-
if (YAML.isSeq(collection)) {
|
|
183
|
-
collectionStack.unshift(node)
|
|
184
|
-
shifted = true
|
|
185
|
-
}
|
|
186
|
-
} else if (YAML.isPair(node) && node.value?.items) {
|
|
187
|
-
collectionStack.unshift(node.value)
|
|
188
|
-
} else if (YAML.isScalar(node) && semantics.forceOverwrite && templateNode) {
|
|
189
|
-
node.value = templateNode.value ?? templateNode.items?.[0]?.value?.value
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (node.items) {
|
|
193
|
-
if (YAML.isSeq(node) && templateNode?.items) {
|
|
194
|
-
actions?.mergeCollection && actions.mergeCollection(node, templateNode)
|
|
195
|
-
_traverseYAMLCollection(node, actions, templateNode)
|
|
196
|
-
} else {
|
|
197
|
-
_traverseYAMLCollection(node, actions, templateNode)
|
|
198
|
-
}
|
|
199
|
-
} else if (node.value?.items || node.value && semantics.forceOverwrite) {
|
|
200
|
-
_traverseYAMLNode(node.value, index, actions, templateNode && templateNode.value)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (node.value?.items || shifted) {
|
|
204
|
-
collectionStack.shift()
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
_traverseYAMLNode.bind(this)
|
|
208
|
-
|
|
209
|
-
function _traverseYAMLCollection (collection, actions, templateCollection) {
|
|
210
|
-
if (!collection) return
|
|
211
|
-
|
|
212
|
-
const keyToIndex = new Map, templateIndexToIndex = new Map
|
|
213
|
-
|
|
214
|
-
// Map collection items to their semantic counterpart(s)
|
|
215
|
-
collection.items.forEach((node, i) => {
|
|
216
|
-
if (node.key) keyToIndex.set(node.key.value, i)
|
|
217
|
-
const existence = [...existenceMap.entries()].find(([,value]) => value?.node === node)
|
|
218
|
-
if (existence) {
|
|
219
|
-
const [existenceKey] = existence
|
|
220
|
-
const templateExistence = existenceKey && templateExistenceMap.get(existenceKey)
|
|
221
|
-
const templateIndex = templateExistence?.index
|
|
222
|
-
if (templateIndex !== undefined) templateIndexToIndex.set(templateIndex, i)
|
|
223
|
-
}
|
|
224
|
-
if (!templateCollection) _traverseYAMLNode(node, i, actions)
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
if (!templateCollection) return
|
|
228
|
-
|
|
229
|
-
templateCollection.items.forEach((templateNode, templateIndex) => {
|
|
230
|
-
if (YAML.isScalar(templateNode)) {
|
|
231
|
-
if (!collection.items.map(item => item.value).includes(templateNode.value)) {
|
|
232
|
-
collection.add(templateNode)
|
|
233
|
-
}
|
|
234
|
-
} else if (YAML.isPair(templateNode)) {
|
|
235
|
-
const i = keyToIndex.get(templateNode.key.value)
|
|
236
|
-
const [collection] = collectionStack
|
|
237
|
-
const targetNode = collection.items && collection.items[i]
|
|
238
|
-
if (targetNode) {
|
|
239
|
-
_traverseYAMLNode(targetNode, templateIndex, actions, templateNode)
|
|
240
|
-
} else if (actions.mergePair) {
|
|
241
|
-
actions.mergePair(collection, templateNode)
|
|
242
|
-
}
|
|
243
|
-
} else if (YAML.isMap(templateNode)) {
|
|
244
|
-
const targetNode = collection.items[templateIndexToIndex.get(templateIndex)]
|
|
245
|
-
if (actions.mergeCollection) actions.mergeCollection(targetNode, templateNode)
|
|
246
|
-
if (targetNode) {
|
|
247
|
-
_traverseYAMLNode(targetNode, templateIndex, actions, templateNode)
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
})
|
|
251
|
-
}
|
|
252
|
-
_traverseYAMLCollection.bind(this)
|
|
253
|
-
|
|
254
|
-
// 1. Validate the existences in the template
|
|
255
|
-
_traverseYAMLNode(source.contents, null, {
|
|
256
|
-
visitMap: (node, index) => {
|
|
257
|
-
_validateWhere(node, templateExistenceMap, index)
|
|
258
|
-
}
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
// 2. Validate the existences in the project
|
|
262
|
-
_traverseYAMLNode(target.contents, null, {
|
|
263
|
-
visitMap: (node, index) => {
|
|
264
|
-
_validateWhere(node, existenceMap, index)
|
|
265
|
-
}
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
// 3. Apply overwrites to already found existences
|
|
269
|
-
overwrites?.forEach(({ item, withValue }) => {
|
|
270
|
-
const keyPath = Array.isArray(item) && typeof item[0] === 'string' ? item[0] : typeof item === 'string' ? item : item[1]
|
|
271
|
-
const inExistence = Array.isArray(item) && typeof item[0] === 'object' ? item[0] : typeof item === 'object' ? item : item[1]
|
|
272
|
-
const node = inExistence && existenceMap.get(inExistence.ref) ? existenceMap.get(inExistence.ref).node : collectionStack[collectionStack.length - 1]
|
|
273
|
-
const keys = keyPath.split('.')
|
|
274
|
-
if (!node.getIn(keys)) return
|
|
275
|
-
_getYAMLProperty(node, keys.slice(0, keys.length - 1).join('.'))
|
|
276
|
-
.set(keys[keys.length - 1], withValue)
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
// 4. Delete existences from the project (e.g. separate deployer module when adding mtx)
|
|
280
|
-
deletions?.forEach(({ item: { ref }, relationships }) => {
|
|
281
|
-
const existence = existenceMap.get(ref)
|
|
282
|
-
if (!existence) return
|
|
283
|
-
existence.collection.delete(existence.index)
|
|
284
|
-
|
|
285
|
-
relationships?.forEach(relationship => {
|
|
286
|
-
const [allWithinKeyPath, inKeyPath, into] = relationship.allWithin
|
|
287
|
-
const parent = _getYAMLProperty(target, allWithinKeyPath)
|
|
288
|
-
for (const child of parent.items) {
|
|
289
|
-
const grandchild = _getYAMLProperty(child, inKeyPath)
|
|
290
|
-
const i = grandchild?.items?.findIndex(node =>
|
|
291
|
-
node.get(into) === _getProperty(existence.json, relationship.removeProperty)
|
|
292
|
-
) ?? - 1
|
|
293
|
-
if (i > -1) grandchild.delete(i)
|
|
294
|
-
}
|
|
295
|
-
})
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
// 5. Create missing existences and pairs
|
|
299
|
-
_traverseYAMLNode(target.contents, null, {
|
|
300
|
-
mergePair: (collection, templateNode) => {
|
|
301
|
-
if (YAML.isMap(collection)) {
|
|
302
|
-
collection.add(templateNode)
|
|
303
|
-
}
|
|
304
|
-
},
|
|
305
|
-
mergeCollection: (targetNode, templateNode) => {
|
|
306
|
-
if (YAML.isSeq(templateNode)) {
|
|
307
|
-
let [,parent] = collectionStack
|
|
308
|
-
additions?.filter(addition => {
|
|
309
|
-
if (typeof addition.in === 'string' || Array.isArray(addition.in) && typeof addition.in[0] === 'string') return true
|
|
310
|
-
const inExistence = Array.isArray(addition.in) ? existenceMap.get(addition.in[0].ref) : existenceMap.get(addition.in.ref)
|
|
311
|
-
return inExistence?.node === parent
|
|
312
|
-
})
|
|
313
|
-
.filter(addition => {
|
|
314
|
-
const keyPath = typeof addition.in === 'string' ? addition.in : Array.isArray(addition.in) && typeof addition.in[0] === 'string' ? addition.in[0] : addition.in[1]
|
|
315
|
-
const keys = keyPath.split('.')
|
|
316
|
-
if (keys.length > collectionStack.length + 1) return
|
|
317
|
-
if (keys.length > 1) parent = collectionStack[keys.length]
|
|
318
|
-
return _getYAMLProperty(parent, keyPath) === targetNode
|
|
319
|
-
})
|
|
320
|
-
.filter(({ ref }) => {
|
|
321
|
-
return !existenceMap.get(ref)
|
|
322
|
-
})
|
|
323
|
-
.forEach(({ ref, at }) => {
|
|
324
|
-
const templateNode = templateExistenceMap.get(ref).node
|
|
325
|
-
at !== undefined ? targetNode.items.splice(at, 0, templateNode) : targetNode.add(templateNode)
|
|
326
|
-
})
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
}, source.contents)
|
|
330
|
-
|
|
331
|
-
// 6. Re-validate the existences in the project
|
|
332
|
-
_traverseYAMLNode(target.contents, null, {
|
|
333
|
-
visitMap: (node, index) => {
|
|
334
|
-
_validateWhere(node, existenceMap, index)
|
|
335
|
-
}
|
|
336
|
-
})
|
|
337
|
-
|
|
338
|
-
// 7. Create missing relationships
|
|
339
|
-
_traverseYAMLNode(target.contents, null, {
|
|
340
|
-
mergeCollection: (targetNode, templateNode) => {
|
|
341
|
-
if (YAML.isSeq(templateNode)) {
|
|
342
|
-
const targetJSON = YAML.parse(String(targetNode))
|
|
343
|
-
const relationship = semantics.relationships?.filter(r => r)
|
|
344
|
-
.find(relationship => {
|
|
345
|
-
const [existence, keyPath] = relationship.into
|
|
346
|
-
if (!existenceMap.get(existence.ref)) return false
|
|
347
|
-
const existingNode = _getYAMLProperty(existenceMap.get(existence.ref).node, keyPath)
|
|
348
|
-
return targetNode === existingNode
|
|
349
|
-
})
|
|
350
|
-
if (!relationship) return
|
|
351
|
-
|
|
352
|
-
const intoKey = relationship.into[relationship.into.length - 1]
|
|
353
|
-
const [existence, existenceKeyPath] = relationship.insert
|
|
354
|
-
const missingPairs = [existence]
|
|
355
|
-
.filter(({ref}) =>
|
|
356
|
-
!targetJSON.some(item =>
|
|
357
|
-
_getProperty(existenceMap.get(ref).json, existenceKeyPath) === item[intoKey]
|
|
358
|
-
)
|
|
359
|
-
)
|
|
360
|
-
.map(({ref}) => existenceMap.get(ref).node.get(intoKey))
|
|
361
|
-
missingPairs.forEach(pair => {
|
|
362
|
-
targetNode.add({ [intoKey]: pair })
|
|
363
|
-
})
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}, source.contents)
|
|
367
|
-
|
|
368
|
-
typeof into === 'string' && await this.fsUtil.writeYAML(into, target)
|
|
369
|
-
return target
|
|
370
|
-
}
|
|
24
|
+
async function render(src, templateValues) {
|
|
25
|
+
const content = await read(src, 'utf-8');
|
|
26
|
+
return Mustache.render(content, templateValues);
|
|
27
|
+
}
|
|
371
28
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
29
|
+
module.exports = {
|
|
30
|
+
render,
|
|
31
|
+
copyFiles
|
|
375
32
|
}
|
package/lib/lint/Linter.js
CHANGED
|
@@ -124,10 +124,9 @@ class Linter {
|
|
|
124
124
|
for (let i = 0; i < configFiles.length; i++) {
|
|
125
125
|
const configPath = path.join(configDir, configFiles[i]);
|
|
126
126
|
if (configFiles[i] !== "package.json" || (
|
|
127
|
-
configFiles[i]
|
|
127
|
+
configFiles[i] === "package.json" && require(configPath).eslintConfig
|
|
128
128
|
)) {
|
|
129
|
-
if (
|
|
130
|
-
|
|
129
|
+
if (exists(configPath) && await isfile(configPath)) {
|
|
131
130
|
return configPath;
|
|
132
131
|
}
|
|
133
132
|
}
|
package/lib/lint/checks.js
CHANGED
package/lib/lint/io.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
const fsp = require("fs").promises;
|
|
2
1
|
const path = require("path");
|
|
3
2
|
const yaml = require("@sap/cds-foss")("yaml");
|
|
4
3
|
const term = require("../util/term");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const JSONC = require(
|
|
4
|
+
const { read, write, exists } = require('../cds').utils;
|
|
5
|
+
const { readJSONC } = require("../init/util/fsUtil");
|
|
6
|
+
const JSONC = require('../util/jsonc');
|
|
8
7
|
|
|
9
8
|
module.exports = {
|
|
10
9
|
/**
|
|
@@ -14,8 +13,8 @@ module.exports = {
|
|
|
14
13
|
*/
|
|
15
14
|
async readEslintConfig(configPath) {
|
|
16
15
|
let config;
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const configFile = path.basename(configPath);
|
|
17
|
+
const configString = await read(configPath, "utf8");
|
|
19
18
|
switch (configFile) {
|
|
20
19
|
case ".eslintrc.js":
|
|
21
20
|
case ".eslintrc.cjs":
|
|
@@ -27,14 +26,14 @@ module.exports = {
|
|
|
27
26
|
break;
|
|
28
27
|
case ".eslintrc.yaml":
|
|
29
28
|
case ".eslintrc.yml":
|
|
30
|
-
config = yaml.parse(await
|
|
29
|
+
config = yaml.parse(await read(configPath, "utf8"));
|
|
31
30
|
break;
|
|
32
31
|
case ".eslintrc.json":
|
|
33
32
|
case ".eslintrc":
|
|
34
|
-
config = await
|
|
33
|
+
config = await readJSONC(configPath);
|
|
35
34
|
break;
|
|
36
35
|
case "package.json":
|
|
37
|
-
config = JSON.parse(await
|
|
36
|
+
config = JSON.parse(await read(configPath, "utf8"));
|
|
38
37
|
if ("eslintConfig" in config) {
|
|
39
38
|
config = config["eslintConfig"];
|
|
40
39
|
} else {
|
|
@@ -60,7 +59,7 @@ module.exports = {
|
|
|
60
59
|
let configContents = {};
|
|
61
60
|
const isFilePath = typeof configIn === "string";
|
|
62
61
|
if (isFilePath) {
|
|
63
|
-
if (
|
|
62
|
+
if (exists(configIn)) {
|
|
64
63
|
configContents = (await this.readEslintConfig(configIn)) || {};
|
|
65
64
|
}
|
|
66
65
|
} else {
|
|
@@ -103,7 +102,7 @@ module.exports = {
|
|
|
103
102
|
* Writes ESLint config contents to file
|
|
104
103
|
* @param {*} configContents config file contents
|
|
105
104
|
* @param {*} configPath config file path to write to
|
|
106
|
-
* @returns {void}
|
|
105
|
+
* @returns {Promise<void>}
|
|
107
106
|
*/
|
|
108
107
|
async writeEslintConfig(configPath, configContents, logger=console) {
|
|
109
108
|
const configType = "recommended";
|
|
@@ -139,15 +138,15 @@ module.exports = {
|
|
|
139
138
|
break;
|
|
140
139
|
case ".eslintrc.yaml":
|
|
141
140
|
case ".eslintrc.yml":
|
|
142
|
-
await
|
|
141
|
+
await write(configPath, yaml.stringify(configContents));
|
|
143
142
|
break;
|
|
144
143
|
case ".eslintrc.json":
|
|
145
144
|
case ".eslintrc":
|
|
146
|
-
await
|
|
145
|
+
await write(configPath, configContents, { spaces: 2 });
|
|
147
146
|
break;
|
|
148
147
|
case "package.json":
|
|
149
|
-
if (
|
|
150
|
-
contents = JSON.parse(await
|
|
148
|
+
if (exists(configPath)) {
|
|
149
|
+
contents = JSON.parse(await read(configPath, "utf8"));
|
|
151
150
|
} else {
|
|
152
151
|
contents = {};
|
|
153
152
|
}
|
|
@@ -156,12 +155,11 @@ module.exports = {
|
|
|
156
155
|
} else {
|
|
157
156
|
contents["eslintConfig"] = [...configContents, ...contents["eslintConfig"]];
|
|
158
157
|
}
|
|
159
|
-
await
|
|
158
|
+
await write(configPath, contents, { spaces: 2 });
|
|
160
159
|
break;
|
|
161
160
|
default:
|
|
162
161
|
break;
|
|
163
162
|
}
|
|
164
|
-
return;
|
|
165
163
|
},
|
|
166
164
|
|
|
167
165
|
/**
|
|
@@ -171,9 +169,9 @@ module.exports = {
|
|
|
171
169
|
*/
|
|
172
170
|
async readVscodeSettings(settingsPath) {
|
|
173
171
|
let settings;
|
|
174
|
-
if (
|
|
172
|
+
if (exists(settingsPath)) {
|
|
175
173
|
try {
|
|
176
|
-
settings = await
|
|
174
|
+
settings = await readJSONC(settingsPath);
|
|
177
175
|
} catch (err) {
|
|
178
176
|
settings = {};
|
|
179
177
|
}
|
|
@@ -230,21 +228,7 @@ module.exports = {
|
|
|
230
228
|
}
|
|
231
229
|
}
|
|
232
230
|
|
|
233
|
-
await
|
|
234
|
-
},
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Writes VS Code settings from file
|
|
238
|
-
* @param {*} settings settings file contents
|
|
239
|
-
* @param {*} settingsPath settings file path to write to
|
|
240
|
-
* @returns {void}
|
|
241
|
-
*/
|
|
242
|
-
async writeVscodeSettings(settingsPath, settings) {
|
|
243
|
-
if (!settings) {
|
|
244
|
-
await fsUtil.mkdirp(path.dirname(settingsPath));
|
|
245
|
-
}
|
|
246
|
-
await fsUtil.writeJSON(settingsPath, settings);
|
|
247
|
-
return;
|
|
231
|
+
await write(settingsPath, settings, { spaces: 2 });
|
|
248
232
|
},
|
|
249
233
|
|
|
250
234
|
/**
|