@sap/cds-dk 10.0.6 → 10.0.7
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 +13 -0
- package/lib/import/asyncapi/parserContext.js +136 -54
- package/lib/init/template/nodejs/index.js +4 -2
- package/node_modules/@cap-js/openapi/lib/compile/csdl.js +3 -3
- package/node_modules/@cap-js/openapi/lib/compile/csdl2openapi.js +111 -103
- package/node_modules/@cap-js/openapi/lib/compile/diagram.js +4 -4
- package/node_modules/@cap-js/openapi/lib/compile/types.d.ts +3 -1
- package/node_modules/@cap-js/openapi/package.json +3 -3
- package/node_modules/@sap/cds/CHANGELOG.md +7 -0
- package/node_modules/@sap/cds/lib/compile/for/nodejs.js +1 -0
- package/node_modules/@sap/cds/libx/_runtime/messaging/common-utils/authorizedRequest.js +3 -2
- package/node_modules/@sap/cds/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/CHANGELOG.md +36 -0
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx-migrate.js +32 -48
- package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +1 -0
- package/node_modules/@sap/cds-mtxs/cds-plugin.js +18 -0
- package/node_modules/@sap/cds-mtxs/lib/migration/migration.js +3 -408
- package/node_modules/@sap/cds-mtxs/package.json +1 -1
- package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +5 -6
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/annotations.js +5 -2
- package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/index.js +6 -5
- package/node_modules/@sap/cds-mtxs/srv/extensibility-service.cds +0 -11
- package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +12 -22
- package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +30 -24
- package/node_modules/@sap/cds-mtxs/srv/model-provider.js +2 -2
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +5 -2
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi.js +5 -3
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/srv-mgr.js +3 -2
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana/tms.js +17 -0
- package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +14 -13
- package/node_modules/sax/lib/sax.js +27 -9
- package/node_modules/sax/package.json +1 -1
- package/node_modules/ws/package.json +1 -1
- package/package.json +4 -4
- package/lib/init/template/nodejs/files/.gitignore.hbs +0 -34
- package/node_modules/@sap/cds-mtxs/lib/migration/extension-project-builder.js +0 -129
- package/node_modules/@sap/cds-mtxs/lib/migration/extension-project.js +0 -89
- package/node_modules/@sap/cds-mtxs/lib/migration/mtx-adapter.js +0 -230
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
8
8
|
|
|
9
|
+
## Version 10.0.7 - 2026-08-07
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Bundle `@sap/cds-mtxs` 4 again, instead of 3.
|
|
14
|
+
- `cds import --from asyncapi` now correctly imports types referenced via `$ref` in AsyncAPI schemas, including `allOf` composition, and no longer loses types from earlier events when a service has multiple events.
|
|
15
|
+
- `cds add html5-repo`, `cds add workzone`, and `cds add portal` no longer emit an HTML5 application content deployer module into `mta.yaml` when the project has no UI apps, avoiding the `could not find the ".../gen/app" path` build failure.
|
|
16
|
+
- `cds init --nodejs` creates the ESLint and VS Code config files again
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- `cds init --nodejs` creates a cleaned-up .gitignore file
|
|
21
|
+
|
|
9
22
|
## Version 10.0.6 - 2026-07-24
|
|
10
23
|
|
|
11
24
|
### Added
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
const { getRegExpGroups } = require('./utils');
|
|
2
2
|
const messages = require("../message").getMessages();
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {{ type?: string|string[], format?: string, properties?: Record<string, AsyncApiSchema>, items?: AsyncApiSchema, allOf?: AsyncApiSchema[], '$ref'?: string, required?: string[], additionalProperties?: boolean|AsyncApiSchema, enum?: Array<*>, default?: *, nullable?: boolean, [key: string]: * }} AsyncApiSchema
|
|
6
|
+
* @typedef {{ components: { messages: Record<string, AsyncApiMessage>, schemas: Record<string, AsyncApiSchema> }, info?: object, [key: string]: * }} AsyncApiDocument
|
|
7
|
+
* @typedef {{ name: string, payload?: AsyncApiSchema, [key: string]: * }} AsyncApiMessage
|
|
8
|
+
* @typedef {{ type?: string|{'ref':string[]}, kind?: string, elements?: Record<string, CsnElement>, items?: CsnElement, '@cds.external'?: string, '@mandatory'?: boolean, precision?: number, scale?: number, default?: *, enum?: object, [key: string]: * }} CsnElement
|
|
9
|
+
* @typedef {Record<string, *>} Annotations
|
|
10
|
+
* @typedef {Record<string, CsnElement | null>} CsnTypeMap
|
|
11
|
+
*/
|
|
12
|
+
|
|
4
13
|
module.exports = class ParserContext {
|
|
5
14
|
/**
|
|
6
|
-
* @
|
|
15
|
+
* @param {AsyncApiDocument} content
|
|
7
16
|
*/
|
|
8
17
|
constructor(content) {
|
|
9
18
|
this.services = this.getServicesFromContent(content);
|
|
10
19
|
}
|
|
11
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} eventName
|
|
23
|
+
*/
|
|
12
24
|
getTopicName(eventName) {
|
|
13
25
|
return eventName.startsWith('ce/') ? eventName.substring(3) : eventName;
|
|
14
26
|
}
|
|
15
27
|
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} messageRefString
|
|
30
|
+
*/
|
|
16
31
|
getEventName(messageRefString) {
|
|
17
32
|
const lastSlashIndex = messageRefString.lastIndexOf('/');
|
|
18
33
|
return lastSlashIndex == -1 ? '' : messageRefString.substring(lastSlashIndex + 1);
|
|
@@ -20,9 +35,10 @@ module.exports = class ParserContext {
|
|
|
20
35
|
|
|
21
36
|
/**
|
|
22
37
|
* Returns services from the asyncapi json object along with the events and annotations.
|
|
23
|
-
* @
|
|
38
|
+
* @param {AsyncApiDocument} content - root AsyncAPI document
|
|
24
39
|
*/
|
|
25
40
|
getServicesFromContent(content) {
|
|
41
|
+
/** @type {Record<string, *>} */
|
|
26
42
|
const services = {};
|
|
27
43
|
const serviceAnnotations = this.getServiceAnnotations(content);
|
|
28
44
|
|
|
@@ -49,15 +65,17 @@ module.exports = class ParserContext {
|
|
|
49
65
|
|
|
50
66
|
// add topic annotation
|
|
51
67
|
eventAnnotations['@topic'] = this.getTopicName(eventName);
|
|
68
|
+
/** @type {Record<string, CsnElement>} */
|
|
52
69
|
let properties = {};
|
|
70
|
+
/** @type {CsnTypeMap} */
|
|
53
71
|
let types = {};
|
|
54
72
|
|
|
55
73
|
if (value.payload) {
|
|
56
74
|
// gets the schema being referred to in the event
|
|
57
75
|
const eventSchema = this.resolveRef(content, value.payload);
|
|
58
|
-
[properties, types] = this.getPropertiesAndTypes(event, eventSchema);
|
|
76
|
+
[properties, types] = this.getPropertiesAndTypes(event, eventSchema, content);
|
|
59
77
|
}
|
|
60
|
-
services[service].types = types;
|
|
78
|
+
services[service].types = { ...services[service].types, ...types };
|
|
61
79
|
services[service].events[event] = { 'kind': 'event', '@cds.external': 'true', ...eventAnnotations, elements: properties };
|
|
62
80
|
});
|
|
63
81
|
|
|
@@ -66,7 +84,7 @@ module.exports = class ParserContext {
|
|
|
66
84
|
|
|
67
85
|
/**
|
|
68
86
|
* Returns annotations of a particular service.
|
|
69
|
-
* @
|
|
87
|
+
* @param {AsyncApiDocument} content - root AsyncAPI document
|
|
70
88
|
*/
|
|
71
89
|
getServiceAnnotations(content) {
|
|
72
90
|
const serviceAnnotationsMapping = {
|
|
@@ -84,9 +102,10 @@ module.exports = class ParserContext {
|
|
|
84
102
|
|
|
85
103
|
if (content.info) {
|
|
86
104
|
for (const [key, value] of Object.entries(infoAnnotationsMapping)) {
|
|
87
|
-
|
|
105
|
+
/** @type {Record<string, *>} */ const info = content.info;
|
|
106
|
+
if (info[key] && !(info[key] instanceof Object)) {
|
|
88
107
|
// info values will always be in string format
|
|
89
|
-
annotations['@AsyncAPI.' + value] =
|
|
108
|
+
annotations['@AsyncAPI.' + value] = info[key];
|
|
90
109
|
}
|
|
91
110
|
}
|
|
92
111
|
}
|
|
@@ -95,8 +114,8 @@ module.exports = class ParserContext {
|
|
|
95
114
|
}
|
|
96
115
|
|
|
97
116
|
/**
|
|
98
|
-
* Returns annotations of a particular event.
|
|
99
|
-
* @
|
|
117
|
+
* Returns annotations of a particular event.
|
|
118
|
+
* @param {AsyncApiMessage} content - message object from components.messages
|
|
100
119
|
*/
|
|
101
120
|
getEventAnnotations(content) {
|
|
102
121
|
const eventLevelAnnotationsMapping = {
|
|
@@ -114,9 +133,8 @@ module.exports = class ParserContext {
|
|
|
114
133
|
}
|
|
115
134
|
|
|
116
135
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* @returns true/false depending on the annotation value.
|
|
136
|
+
* @param {string} annotation - annotation name (without @AsyncAPI. prefix)
|
|
137
|
+
* @param {*} value
|
|
120
138
|
*/
|
|
121
139
|
isValidAnnotationValue(annotation, value) {
|
|
122
140
|
const objectTypeAnnotations = ['StateInfo', 'EventSourceParams', 'EventCharacteristics', 'EventStateInfo'];
|
|
@@ -134,11 +152,12 @@ module.exports = class ParserContext {
|
|
|
134
152
|
}
|
|
135
153
|
|
|
136
154
|
/**
|
|
137
|
-
* Returns annotations for an event/service.
|
|
138
|
-
*
|
|
139
|
-
* @
|
|
155
|
+
* Returns annotations for an event/service.
|
|
156
|
+
* @param {object} content - event or service object
|
|
157
|
+
* @param {Record<string, string>} annotationsMapping - map of AsyncAPI extension key to CDS annotation suffix
|
|
140
158
|
*/
|
|
141
159
|
getAnnotations(content, annotationsMapping) {
|
|
160
|
+
/** @type {Annotations} */
|
|
142
161
|
const annotations = {};
|
|
143
162
|
|
|
144
163
|
for (const [key, value] of Object.entries(content)) {
|
|
@@ -160,11 +179,33 @@ module.exports = class ParserContext {
|
|
|
160
179
|
}
|
|
161
180
|
|
|
162
181
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* @
|
|
182
|
+
* Merges allOf entries into a single schema object with combined properties.
|
|
183
|
+
* Resolves any $ref entries within the allOf array using the provided document.
|
|
184
|
+
* @param {AsyncApiSchema} schema - AsyncAPI schema object, possibly containing allOf
|
|
185
|
+
* @param {AsyncApiDocument} docContent - root AsyncAPI document, used to resolve $ref entries
|
|
186
|
+
*/
|
|
187
|
+
flattenAllOf(schema, docContent) {
|
|
188
|
+
if (!schema.allOf) return schema;
|
|
189
|
+
/** @type {AsyncApiSchema} */
|
|
190
|
+
const merged = { type: 'object', properties: {} };
|
|
191
|
+
const required = [];
|
|
192
|
+
for (const entry of schema.allOf) {
|
|
193
|
+
const resolved = entry['$ref'] ? this.resolveRef(docContent, entry) : entry;
|
|
194
|
+
const flat = this.flattenAllOf(resolved, docContent);
|
|
195
|
+
Object.assign(merged.properties ?? {}, flat.properties || {});
|
|
196
|
+
if (flat.required) required.push(...flat.required);
|
|
197
|
+
}
|
|
198
|
+
if (required.length) merged.required = required;
|
|
199
|
+
return merged;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Returns the referred schema.
|
|
204
|
+
* @param {AsyncApiDocument} content - root AsyncAPI document
|
|
205
|
+
* @param {AsyncApiSchema | {'$ref': string}} payloadObject - either a $ref object or an inline schema
|
|
166
206
|
*/
|
|
167
207
|
resolveRef(content, payloadObject) {
|
|
208
|
+
/** @type {AsyncApiSchema} */
|
|
168
209
|
let schema = {};
|
|
169
210
|
|
|
170
211
|
if (payloadObject['$ref']) {
|
|
@@ -190,40 +231,46 @@ module.exports = class ParserContext {
|
|
|
190
231
|
|
|
191
232
|
/**
|
|
192
233
|
* Returns the properties and types generated, related to an event.
|
|
193
|
-
* @
|
|
234
|
+
* @param {string} eventName
|
|
235
|
+
* @param {AsyncApiSchema} content - resolved AsyncAPI schema object for the event payload
|
|
236
|
+
* @param {AsyncApiDocument} docContent - root AsyncAPI document, used to resolve $ref entries
|
|
237
|
+
* @returns {[Record<string, CsnElement>, CsnTypeMap]}
|
|
194
238
|
*/
|
|
195
|
-
getPropertiesAndTypes(eventName, content) {
|
|
239
|
+
getPropertiesAndTypes(eventName, content, docContent) {
|
|
240
|
+
/** @type {Record<string, CsnElement>} */
|
|
196
241
|
const properties = {};
|
|
197
|
-
|
|
242
|
+
/** @type {CsnTypeMap} */
|
|
243
|
+
const types = {};
|
|
198
244
|
|
|
199
245
|
if (content.properties) {
|
|
200
246
|
for (const [key, value] of Object.entries(content.properties)) {
|
|
201
|
-
// will contain type objects generated for a property
|
|
202
|
-
let referredTypes = {};
|
|
203
247
|
let isRequired = false;
|
|
204
248
|
if (content['required']?.includes(key)) isRequired = true;
|
|
205
|
-
|
|
206
|
-
// collecting all the types
|
|
207
|
-
types = { ...types, ...referredTypes };
|
|
249
|
+
properties[key] = this.parseProperty(eventName, key, value, isRequired, docContent, types);
|
|
208
250
|
}
|
|
209
251
|
}
|
|
210
252
|
return [properties, types];
|
|
211
253
|
}
|
|
212
254
|
|
|
213
255
|
/**
|
|
214
|
-
* Returns the processed
|
|
215
|
-
* @
|
|
256
|
+
* Returns the processed CSN element object for a property.
|
|
257
|
+
* @param {string} eventName
|
|
258
|
+
* @param {string} propertyName
|
|
259
|
+
* @param {AsyncApiSchema} propertyContent - AsyncAPI schema for this property
|
|
260
|
+
* @param {boolean} isRequired
|
|
261
|
+
* @param {AsyncApiDocument} docContent - root AsyncAPI document, used to resolve $ref entries
|
|
262
|
+
* @param {CsnTypeMap} types - accumulator for generated CDS type definitions
|
|
216
263
|
*/
|
|
217
|
-
parseProperty(eventName, propertyName, propertyContent, isRequired) {
|
|
264
|
+
parseProperty(eventName, propertyName, propertyContent, isRequired, docContent, types) {
|
|
218
265
|
let property = {};
|
|
219
266
|
let propertyAttributes = {};
|
|
220
|
-
let types = {};
|
|
221
267
|
|
|
222
268
|
if (isRequired === true) {
|
|
223
269
|
property['@mandatory'] = true;
|
|
224
270
|
}
|
|
225
271
|
|
|
226
272
|
let type = this.getTypeFromArray(propertyContent.type);
|
|
273
|
+
if (!type && propertyContent.allOf) type = 'object';
|
|
227
274
|
|
|
228
275
|
// case where type is defined
|
|
229
276
|
if (type && (type === 'object' || type === 'array')) {
|
|
@@ -231,48 +278,55 @@ module.exports = class ParserContext {
|
|
|
231
278
|
propertyName = propertyName[0].toUpperCase() + propertyName.substring(1);
|
|
232
279
|
let typeName = eventName + "." + propertyName;
|
|
233
280
|
// generate object for the introduced type
|
|
234
|
-
const elements = this.getTypeElements(propertyContent);
|
|
281
|
+
const elements = this.getTypeElements(propertyContent, docContent, types);
|
|
235
282
|
types[typeName] = { 'kind': 'type', '@cds.external': 'true', ...elements };
|
|
236
283
|
// referring to the generated type from the property
|
|
237
284
|
propertyAttributes = { 'type': typeName };
|
|
238
285
|
} else {
|
|
239
|
-
propertyAttributes = this.getPropertyObject(propertyContent);
|
|
286
|
+
propertyAttributes = this.getPropertyObject(propertyContent, docContent, types);
|
|
240
287
|
}
|
|
241
288
|
property = { ...property, ...propertyAttributes };
|
|
242
289
|
|
|
243
|
-
return
|
|
290
|
+
return property;
|
|
244
291
|
}
|
|
245
292
|
|
|
246
293
|
/**
|
|
247
|
-
* Returns
|
|
248
|
-
* @
|
|
294
|
+
* Returns the CSN structure for a complex (object/array) schema element.
|
|
295
|
+
* @param {AsyncApiSchema} propertyContent - AsyncAPI schema for this property
|
|
296
|
+
* @param {AsyncApiDocument} docContent - root AsyncAPI document, used to resolve $ref entries
|
|
297
|
+
* @param {CsnTypeMap} types - accumulator for generated CDS type definitions
|
|
298
|
+
* @returns {CsnElement}
|
|
249
299
|
*/
|
|
250
|
-
getTypeElements(propertyContent) {
|
|
300
|
+
getTypeElements(propertyContent, docContent, types) {
|
|
301
|
+
/** @type {CsnElement} */
|
|
251
302
|
let properties = {};
|
|
252
|
-
|
|
303
|
+
const schema = propertyContent.allOf ? this.flattenAllOf(propertyContent, docContent) : propertyContent;
|
|
304
|
+
let type = this.getTypeFromArray(schema.type);
|
|
253
305
|
|
|
254
306
|
// for nested object
|
|
255
307
|
if (type === 'object') {
|
|
256
|
-
|
|
257
|
-
|
|
308
|
+
if (!schema.properties) return {};
|
|
309
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
310
|
+
properties[key] = this.getTypeElements(value, docContent, types);
|
|
258
311
|
}
|
|
259
312
|
}
|
|
260
313
|
// for nested array
|
|
261
314
|
else if (type === 'array') {
|
|
262
|
-
|
|
315
|
+
if (!schema.items || (!schema.items.type && !schema.items['$ref'] && !schema.items.allOf)) return {};
|
|
316
|
+
properties.items = this.getTypeElements(schema.items, docContent, types);
|
|
263
317
|
return properties;
|
|
264
318
|
}
|
|
265
319
|
// base data type mapping
|
|
266
320
|
else {
|
|
267
|
-
return this.getPropertyObject(
|
|
321
|
+
return this.getPropertyObject(schema, docContent, types);
|
|
268
322
|
}
|
|
269
323
|
|
|
270
324
|
return { elements: properties };
|
|
271
325
|
}
|
|
272
326
|
|
|
273
327
|
/**
|
|
274
|
-
*
|
|
275
|
-
* @
|
|
328
|
+
* Unwraps nullable array type representations to a single type string.
|
|
329
|
+
* @param {string | string[] | undefined} typeValue
|
|
276
330
|
*/
|
|
277
331
|
getTypeFromArray(typeValue) {
|
|
278
332
|
let type;
|
|
@@ -288,15 +342,41 @@ module.exports = class ParserContext {
|
|
|
288
342
|
}
|
|
289
343
|
|
|
290
344
|
/**
|
|
291
|
-
* Returns
|
|
292
|
-
* @
|
|
345
|
+
* Returns the CSN element object for a scalar or $ref property.
|
|
346
|
+
* @param {AsyncApiSchema} propertyContent - AsyncAPI schema for this property
|
|
347
|
+
* @param {AsyncApiDocument} docContent - root AsyncAPI document, used to resolve $ref entries
|
|
348
|
+
* @param {CsnTypeMap} types - accumulator for generated CDS type definitions
|
|
293
349
|
*/
|
|
294
|
-
getPropertyObject(propertyContent) {
|
|
350
|
+
getPropertyObject(propertyContent, docContent, types) {
|
|
351
|
+
/** @type {CsnElement} */
|
|
295
352
|
const property = {};
|
|
296
353
|
if ('$ref' in propertyContent) {
|
|
297
|
-
const refPathParts = propertyContent['$ref'].split('/');
|
|
298
|
-
const
|
|
299
|
-
|
|
354
|
+
const refPathParts = (propertyContent['$ref'] ?? '').split('/');
|
|
355
|
+
const schemaName = refPathParts[3] ?? '';
|
|
356
|
+
const isWholeSchemaRef = () => refPathParts.length === 4 && refPathParts[1] === 'components' && refPathParts[2] === 'schemas';
|
|
357
|
+
|
|
358
|
+
if (isWholeSchemaRef()) {
|
|
359
|
+
// $ref to a whole top-level schema — resolve it and emit as a CDS type
|
|
360
|
+
if (!types[schemaName]) {
|
|
361
|
+
types[schemaName] = null; // placeholder to guard against circular refs
|
|
362
|
+
const resolvedSchema = this.resolveRef(docContent, propertyContent);
|
|
363
|
+
const flatSchema = resolvedSchema.allOf ? this.flattenAllOf(resolvedSchema, docContent) : resolvedSchema;
|
|
364
|
+
const elements = this.getTypeElements(flatSchema, docContent, types);
|
|
365
|
+
// only emit a named type if it has structure; otherwise fall back to LargeString
|
|
366
|
+
if (Object.keys(elements).length > 0) {
|
|
367
|
+
types[schemaName] = { 'kind': 'type', '@cds.external': 'true', ...elements };
|
|
368
|
+
} else {
|
|
369
|
+
delete types[schemaName];
|
|
370
|
+
property['type'] = 'cds.LargeString';
|
|
371
|
+
return property;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
property['type'] = schemaName;
|
|
375
|
+
} else {
|
|
376
|
+
// $ref to a specific property within a schema (e.g. /properties/propName)
|
|
377
|
+
const propertyName = refPathParts[refPathParts.length - 1];
|
|
378
|
+
property['type'] = { 'ref': [schemaName, propertyName] };
|
|
379
|
+
}
|
|
300
380
|
return property;
|
|
301
381
|
}
|
|
302
382
|
const inputType = this.getTypeFromArray(propertyContent.type);
|
|
@@ -322,24 +402,26 @@ module.exports = class ParserContext {
|
|
|
322
402
|
}
|
|
323
403
|
|
|
324
404
|
/**
|
|
325
|
-
*
|
|
326
|
-
* @returns the property object of enums.
|
|
405
|
+
* @param {Array<*>} enumArray
|
|
327
406
|
*/
|
|
328
407
|
getEnumObject(enumArray) {
|
|
408
|
+
/** @type {Record<string, {}>} */
|
|
329
409
|
const enumProperty = {};
|
|
330
410
|
|
|
331
411
|
enumArray.forEach(val => {
|
|
332
|
-
enumProperty[val] = {};
|
|
412
|
+
enumProperty[String(val)] = {};
|
|
333
413
|
});
|
|
334
414
|
|
|
335
415
|
return enumProperty;
|
|
336
416
|
}
|
|
337
417
|
|
|
338
418
|
/**
|
|
339
|
-
*
|
|
340
|
-
* @
|
|
419
|
+
* @param {string | undefined} type - AsyncAPI primitive type
|
|
420
|
+
* @param {string | null} format - AsyncAPI format string
|
|
341
421
|
*/
|
|
342
422
|
getDataType(type, format = null) {
|
|
423
|
+
if (!type) throw new Error(messages.UNRESOLVED_TYPE + `'${type}'`);
|
|
424
|
+
/** @type {Record<string, string>} */
|
|
343
425
|
const asyncapiToCdsMapping = {
|
|
344
426
|
'number': 'cds.Double',
|
|
345
427
|
'boolean': 'cds.Boolean',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
|
-
const { exists, mkdirp, path } = cds.utils
|
|
2
|
+
const { fs: { promises: { cp } }, exists, mkdirp, path } = cds.utils
|
|
3
3
|
const { OPTIONS: { NODEJS, JAVA } } = require('../../constants')
|
|
4
4
|
const term = require('../../../util/term')
|
|
5
5
|
const { merge } = require('../../merge')
|
|
@@ -24,10 +24,12 @@ module.exports = class NodejsTemplate extends require('../../plugin') {
|
|
|
24
24
|
|
|
25
25
|
async run() {
|
|
26
26
|
const { db, srv, app } = cds.env.folders
|
|
27
|
-
if (cds.cli.command === 'init'
|
|
27
|
+
if (cds.cli.command === 'init' || cds.cli.options.force) {
|
|
28
28
|
await renderAndCopy(path.join(__dirname, 'files'), cds.root, { projectName: path.basename(cds.root) })
|
|
29
29
|
} else {
|
|
30
30
|
await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: { projectName: path.basename(cds.root) }})
|
|
31
|
+
await cp(path.join(__dirname, 'files/eslint.config.mjs'), 'eslint.config.mjs', { force: false })
|
|
32
|
+
await cp(path.join(__dirname, 'files/.vscode'), '.vscode', { recursive: true, force: false })
|
|
31
33
|
}
|
|
32
34
|
await Promise.all([db, srv, app].map(p => mkdirp(p)))
|
|
33
35
|
}
|
|
@@ -14,7 +14,7 @@ const CDS_TERMS = Object.freeze({
|
|
|
14
14
|
Core: ['AcceptableMediaTypes', 'Computed', 'ComputedDefaultValue', 'DefaultNamespace', 'Description', 'Example', 'Immutable', 'LongDescription',
|
|
15
15
|
'MediaType', 'OptionalParameter', 'Permissions', 'SchemaVersion'],
|
|
16
16
|
JSON: ['Schema'],
|
|
17
|
-
Validation: ['AllowedValues', 'Exclusive', 'Maximum', 'Minimum', 'Pattern']
|
|
17
|
+
Validation: ['AllowedValues', 'Exclusive', 'Maximum', 'MaxItems', 'Minimum', 'MinItems', 'Pattern']
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -168,7 +168,7 @@ class CSDLMeta {
|
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
170
|
* Construct map of qualified term names
|
|
171
|
-
* @param {
|
|
171
|
+
* @param {*} alias Map of namespace or alias to alias
|
|
172
172
|
*/
|
|
173
173
|
#getVocabularies(alias) {
|
|
174
174
|
Object.keys(CDS_TERMS).forEach(vocab => {
|
|
@@ -187,7 +187,7 @@ class CSDLMeta {
|
|
|
187
187
|
/**
|
|
188
188
|
* Find model element by qualified name
|
|
189
189
|
* @param {string} qname Qualified name of model element
|
|
190
|
-
* @return {
|
|
190
|
+
* @return {*} Model element
|
|
191
191
|
*/
|
|
192
192
|
modelElement(qname) {
|
|
193
193
|
const q = nameParts(qname);
|