@sap-ux/odata-service-writer 0.24.2 → 0.25.1
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/dist/data/defaults.js +1 -1
- package/dist/index.js +1 -1
- package/dist/updates.d.ts +1 -2
- package/dist/updates.js +166 -13
- package/package.json +2 -2
- package/templates/extend/manifest.json +0 -98
package/dist/data/defaults.js
CHANGED
|
@@ -113,7 +113,7 @@ async function enhanceData(basePath, service, fs) {
|
|
|
113
113
|
// set service type to EDMX if not defined
|
|
114
114
|
service.type = service.type ?? types_1.ServiceType.EDMX;
|
|
115
115
|
/**
|
|
116
|
-
* In the manifest
|
|
116
|
+
* In the manifest annotation names are used to add annotations to the manifest.json.
|
|
117
117
|
* For CAP projects, annotations are added to the annotations.cds file instead of the manifest.json.
|
|
118
118
|
* If the service type is EDMX, this function sets the default annotation names to be included in the manifest.json.
|
|
119
119
|
*/
|
package/dist/index.js
CHANGED
|
@@ -219,7 +219,7 @@ async function generate(basePath, service, fs) {
|
|
|
219
219
|
// Prepare template folder for manifest and xml updates
|
|
220
220
|
const templateRoot = (0, path_1.join)(__dirname, '../templates');
|
|
221
221
|
// Update manifest.json
|
|
222
|
-
await (0, updates_1.updateManifest)(basePath, service, fs
|
|
222
|
+
await (0, updates_1.updateManifest)(basePath, service, fs);
|
|
223
223
|
// Dont extend backend and mockserver middlewares if service type is CDS
|
|
224
224
|
if (isServiceTypeEdmx) {
|
|
225
225
|
await writeEDMXServiceFiles(fs, basePath, paths, templateRoot, service);
|
package/dist/updates.d.ts
CHANGED
|
@@ -6,9 +6,8 @@ import type { OdataService, CdsAnnotationsInfo, EdmxAnnotationsInfo } from './ty
|
|
|
6
6
|
* @param basePath - the root path of an existing UI5 application
|
|
7
7
|
* @param service - the OData service instance
|
|
8
8
|
* @param fs - the memfs editor instance
|
|
9
|
-
* @param templateRoot - root folder contain the ejs templates
|
|
10
9
|
*/
|
|
11
|
-
export declare function updateManifest(basePath: string, service: OdataService, fs: Editor
|
|
10
|
+
export declare function updateManifest(basePath: string, service: OdataService, fs: Editor): Promise<void>;
|
|
12
11
|
/**
|
|
13
12
|
* Writes annotation XML files for EDMX service annotations.
|
|
14
13
|
*
|
package/dist/updates.js
CHANGED
|
@@ -7,19 +7,175 @@ exports.updateManifest = updateManifest;
|
|
|
7
7
|
exports.writeAnnotationXmlFiles = writeAnnotationXmlFiles;
|
|
8
8
|
exports.updateCdsFilesWithAnnotations = updateCdsFilesWithAnnotations;
|
|
9
9
|
exports.updatePackageJson = updatePackageJson;
|
|
10
|
-
const ejs_1 = require("ejs");
|
|
11
10
|
const path_1 = require("path");
|
|
12
11
|
const i18n_1 = require("./i18n");
|
|
13
12
|
const semver_1 = __importDefault(require("semver"));
|
|
14
13
|
const prettify_xml_1 = __importDefault(require("prettify-xml"));
|
|
15
14
|
const project_access_1 = require("@sap-ux/project-access");
|
|
15
|
+
/**
|
|
16
|
+
* Enhances manifest.json models with given service data.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} serviceName - name of the OData service instance
|
|
19
|
+
* @param {string} serviceVersion - version of the OData service instance
|
|
20
|
+
* @param {string} serviceModel - model of the OData service instance
|
|
21
|
+
* @param {boolean} includeSynchronizationMode - whether to include synchronizationMode for model settings
|
|
22
|
+
* @param {Manifest} manifest - the manifest.json of the application
|
|
23
|
+
*/
|
|
24
|
+
function enhanceManifestModels(serviceName, serviceVersion, serviceModel, includeSynchronizationMode, manifest) {
|
|
25
|
+
const models = manifest?.['sap.ui5']?.models ?? {};
|
|
26
|
+
let modelSettings = {};
|
|
27
|
+
if (serviceVersion === '4') {
|
|
28
|
+
if (includeSynchronizationMode) {
|
|
29
|
+
modelSettings['synchronizationMode'] = 'None';
|
|
30
|
+
}
|
|
31
|
+
modelSettings['operationMode'] = 'Server';
|
|
32
|
+
modelSettings['autoExpandSelect'] = true;
|
|
33
|
+
modelSettings['earlyRequests'] = true;
|
|
34
|
+
}
|
|
35
|
+
if (models[serviceModel]?.settings) {
|
|
36
|
+
// Merge settings for existing model
|
|
37
|
+
modelSettings = {
|
|
38
|
+
...models[serviceModel].settings,
|
|
39
|
+
...modelSettings
|
|
40
|
+
};
|
|
41
|
+
models[serviceModel] = {
|
|
42
|
+
...models[serviceModel],
|
|
43
|
+
dataSource: serviceName,
|
|
44
|
+
preload: true,
|
|
45
|
+
settings: modelSettings
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
models[serviceModel] = {
|
|
50
|
+
dataSource: serviceName,
|
|
51
|
+
preload: true,
|
|
52
|
+
settings: modelSettings
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (manifest['sap.ui5']) {
|
|
56
|
+
manifest['sap.ui5'] = {
|
|
57
|
+
...manifest['sap.ui5'],
|
|
58
|
+
models
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
Object.assign(manifest, { 'sap.ui5': { models: { ...models } } });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Enhances manifest.json dataSources with given service data.
|
|
67
|
+
*
|
|
68
|
+
* @param {string} serviceName - name of the OData service instance
|
|
69
|
+
* @param {string} servicePath - path of the OData service instance
|
|
70
|
+
* @param {string} serviceVersion - version of the OData service instance
|
|
71
|
+
* @param {Manifest} manifest - the manifest.json of the application
|
|
72
|
+
* @param {string} serviceMetadata - metdata of the OData service instance
|
|
73
|
+
* @param {EdmxAnnotationsInfo | EdmxAnnotationsInfo[]} serviceRemoteAnnotations - remote annotations of the OData service instance
|
|
74
|
+
* @param {string | string[]} serviceLocalAnnotations - local annotations of the OData service instance
|
|
75
|
+
*/
|
|
76
|
+
function enhanceManifestDatasources(serviceName, servicePath, serviceVersion, manifest, serviceMetadata, serviceRemoteAnnotations, serviceLocalAnnotations) {
|
|
77
|
+
const dataSources = manifest?.['sap.app'].dataSources ?? {};
|
|
78
|
+
// Service annotation names to be stored in service settings of dataSource
|
|
79
|
+
const annotations = [];
|
|
80
|
+
// Annotation dataSources used by service - remote and local annotations are handled differently
|
|
81
|
+
const annotationDataSources = {};
|
|
82
|
+
// Handle remote annotations used by service
|
|
83
|
+
if (Array.isArray(serviceRemoteAnnotations)) {
|
|
84
|
+
serviceRemoteAnnotations.forEach((remoteAnnotation) => {
|
|
85
|
+
if (remoteAnnotation.name) {
|
|
86
|
+
annotations.push(remoteAnnotation.name);
|
|
87
|
+
annotationDataSources[remoteAnnotation.name] = {
|
|
88
|
+
uri: `/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='${encodeURIComponent(remoteAnnotation.technicalName)}',Version='0001')/$value/`,
|
|
89
|
+
type: 'ODataAnnotation',
|
|
90
|
+
settings: {
|
|
91
|
+
localUri: `localService/${serviceName}/${remoteAnnotation.technicalName}.xml`
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else if (serviceRemoteAnnotations?.name) {
|
|
98
|
+
annotations.push(serviceRemoteAnnotations.name);
|
|
99
|
+
annotationDataSources[serviceRemoteAnnotations.name] = {
|
|
100
|
+
uri: `/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='${encodeURIComponent(serviceRemoteAnnotations.technicalName)}',Version='0001')/$value/`,
|
|
101
|
+
type: 'ODataAnnotation',
|
|
102
|
+
settings: {
|
|
103
|
+
localUri: `localService/${serviceName}/${serviceRemoteAnnotations.technicalName}.xml`
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Handle local annotations used by service
|
|
108
|
+
if (Array.isArray(serviceLocalAnnotations)) {
|
|
109
|
+
serviceLocalAnnotations.forEach((localAnnotation) => {
|
|
110
|
+
annotations.push(localAnnotation);
|
|
111
|
+
annotationDataSources[localAnnotation] = {
|
|
112
|
+
type: 'ODataAnnotation',
|
|
113
|
+
uri: `annotations/${localAnnotation}.xml`,
|
|
114
|
+
settings: {
|
|
115
|
+
localUri: `annotations/${localAnnotation}.xml`
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else if (serviceLocalAnnotations) {
|
|
121
|
+
annotations.push(serviceLocalAnnotations);
|
|
122
|
+
annotationDataSources[serviceLocalAnnotations] = {
|
|
123
|
+
type: 'ODataAnnotation',
|
|
124
|
+
uri: `annotations/${serviceLocalAnnotations}.xml`,
|
|
125
|
+
settings: {
|
|
126
|
+
localUri: `annotations/${serviceLocalAnnotations}.xml`
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const settings = {
|
|
131
|
+
annotations
|
|
132
|
+
};
|
|
133
|
+
if (serviceMetadata) {
|
|
134
|
+
settings['localUri'] = `localService/${serviceName}/metadata.xml`;
|
|
135
|
+
}
|
|
136
|
+
if (serviceVersion === '4') {
|
|
137
|
+
settings['odataVersion'] = '4.0';
|
|
138
|
+
}
|
|
139
|
+
else if (serviceVersion === '2') {
|
|
140
|
+
settings['odataVersion'] = '2.0';
|
|
141
|
+
}
|
|
142
|
+
// Create or update service dataSource in manifest.json for service
|
|
143
|
+
dataSources[serviceName] = {
|
|
144
|
+
uri: servicePath,
|
|
145
|
+
type: 'OData',
|
|
146
|
+
settings
|
|
147
|
+
};
|
|
148
|
+
// Create or update service annotation dataSources in manifest.json for service
|
|
149
|
+
for (const name in annotationDataSources) {
|
|
150
|
+
const annotationDataSource = annotationDataSources[name];
|
|
151
|
+
dataSources[name] = annotationDataSource;
|
|
152
|
+
}
|
|
153
|
+
// Update manifest.json dataSources
|
|
154
|
+
manifest['sap.app'].dataSources = dataSources;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Enhances (creates or updates existing) manifest.json with service data.
|
|
158
|
+
*
|
|
159
|
+
* @param {OdataService} service - the OData service instance
|
|
160
|
+
* @param {Manifest} manifest - the manifest.json of the application
|
|
161
|
+
*/
|
|
162
|
+
function enhanceManifest(service, manifest) {
|
|
163
|
+
const minimumUi5Version = (0, project_access_1.getMinimumUI5Version)(manifest);
|
|
164
|
+
// Enhance model settings for service
|
|
165
|
+
const serviceSettings = Object.assign(service, getModelSettings(minimumUi5Version));
|
|
166
|
+
if (serviceSettings.name && serviceSettings.path && serviceSettings.model !== undefined) {
|
|
167
|
+
enhanceManifestDatasources(serviceSettings.name, serviceSettings.path, serviceSettings.version, manifest, serviceSettings.metadata, serviceSettings.annotations, serviceSettings.localAnnotationsName);
|
|
168
|
+
// Add or update existing service model settings for manifest.json
|
|
169
|
+
enhanceManifestModels(serviceSettings.name, serviceSettings.version, serviceSettings.model, serviceSettings.includeSynchronizationMode, manifest);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
16
172
|
/**
|
|
17
173
|
* Modifies service in manifest.json and service files in a way that is supported by multiple services.
|
|
18
174
|
* If service files are defined in 'localService' folder then those files are moved to respective service folder and service configuration URI are modified in manifest.json.
|
|
19
175
|
*
|
|
20
176
|
* @param {string} webappPath - the webapp path of an existing UI5 application
|
|
21
177
|
* @param {string} dataSourceKey - dataSource key in manifest.json
|
|
22
|
-
* @param {
|
|
178
|
+
* @param {ManifestNamespace.DataSource} dataSource - dataSource configuration from manifest.json
|
|
23
179
|
* @param {Editor} fs - the memfs editor instance
|
|
24
180
|
*/
|
|
25
181
|
function updateExistingService(webappPath, dataSourceKey, dataSource, fs) {
|
|
@@ -47,6 +203,7 @@ function updateExistingService(webappPath, dataSourceKey, dataSource, fs) {
|
|
|
47
203
|
* @param {string} webappPath - the webapp path of an existing UI5 application
|
|
48
204
|
* @param {Manifest} manifest - the manifest.json of the application
|
|
49
205
|
* @param {Editor} fs - the memfs editor instance
|
|
206
|
+
* @returns modified manifest object.
|
|
50
207
|
*/
|
|
51
208
|
async function updateExistingServices(webappPath, manifest, fs) {
|
|
52
209
|
const dataSources = manifest?.['sap.app']?.dataSources;
|
|
@@ -63,7 +220,7 @@ async function updateExistingServices(webappPath, manifest, fs) {
|
|
|
63
220
|
}
|
|
64
221
|
}
|
|
65
222
|
}
|
|
66
|
-
|
|
223
|
+
return manifest;
|
|
67
224
|
}
|
|
68
225
|
/**
|
|
69
226
|
* Internal function that updates the manifest.json based on the given service configuration.
|
|
@@ -71,27 +228,23 @@ async function updateExistingServices(webappPath, manifest, fs) {
|
|
|
71
228
|
* @param basePath - the root path of an existing UI5 application
|
|
72
229
|
* @param service - the OData service instance
|
|
73
230
|
* @param fs - the memfs editor instance
|
|
74
|
-
* @param templateRoot - root folder contain the ejs templates
|
|
75
231
|
*/
|
|
76
|
-
async function updateManifest(basePath, service, fs
|
|
232
|
+
async function updateManifest(basePath, service, fs) {
|
|
77
233
|
const webappPath = await (0, project_access_1.getWebappPath)(basePath, fs);
|
|
78
234
|
const manifestPath = (0, path_1.join)(webappPath, 'manifest.json');
|
|
79
235
|
// Get component app id
|
|
80
236
|
const manifest = fs.readJSON(manifestPath);
|
|
81
237
|
const appProp = 'sap.app';
|
|
82
238
|
const appid = manifest?.[appProp]?.id;
|
|
83
|
-
// Check and update existing services
|
|
84
|
-
await updateExistingServices(webappPath, manifest, fs);
|
|
85
|
-
const modifiedManifest = fs.readJSON(manifestPath);
|
|
86
239
|
// Throw if required property is not found manifest.json
|
|
87
240
|
if (!appid) {
|
|
88
241
|
throw new Error((0, i18n_1.t)('error.requiredProjectPropertyNotFound', { property: `'${appProp}'.id`, path: manifestPath }));
|
|
89
242
|
}
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
fs.
|
|
243
|
+
// Check and update existing services
|
|
244
|
+
const modifiedManifest = await updateExistingServices(webappPath, manifest, fs);
|
|
245
|
+
// Add or update manifest.json with service
|
|
246
|
+
enhanceManifest(service, modifiedManifest);
|
|
247
|
+
fs.writeJSON(manifestPath, modifiedManifest);
|
|
95
248
|
}
|
|
96
249
|
/**
|
|
97
250
|
* Updates the cds index or service file with the provided annotations.
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"bugs": {
|
|
10
10
|
"url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aodata-service-writer"
|
|
11
11
|
},
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.25.1",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"files": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@types/semver": "7.5.2",
|
|
39
39
|
"fs-extra": "10.0.0",
|
|
40
40
|
"lodash": "4.17.21",
|
|
41
|
-
"@sap-ux/project-access": "1.28.
|
|
41
|
+
"@sap-ux/project-access": "1.28.10"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=18.x"
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sap.app": {
|
|
3
|
-
"dataSources": {
|
|
4
|
-
"<%=name%>": {
|
|
5
|
-
"uri": "<%=path%>",
|
|
6
|
-
"type": "OData",
|
|
7
|
-
"settings": {
|
|
8
|
-
"annotations": [
|
|
9
|
-
<% if (locals.annotations && typeof annotations !== 'undefined') { %>
|
|
10
|
-
<% if (annotations.length) { %>
|
|
11
|
-
<% annotations.forEach(function(annotation, index) { %>
|
|
12
|
-
<% if (annotation.technicalName) { %>
|
|
13
|
-
"<%= annotation.name %>"<% if (index < annotations.length - 1 || locals.localAnnotationsName && (!locals.localAnnotationsName.length || locals.localAnnotationsName.length > 0)) { %>,<% } %>
|
|
14
|
-
<% } %>
|
|
15
|
-
<% }); %>
|
|
16
|
-
<% } else if (annotations.technicalName) { %>
|
|
17
|
-
"<%= annotations.name %>"<% if (locals.localAnnotationsName && (!locals.localAnnotationsName.length || locals.localAnnotationsName.length > 0)) {%>,<%}%><% } %>
|
|
18
|
-
<% } %>
|
|
19
|
-
<% if (locals.localAnnotationsName && typeof localAnnotationsName !== 'undefined') { %>
|
|
20
|
-
<% if (Array.isArray(localAnnotationsName)) { %>
|
|
21
|
-
<% localAnnotationsName.forEach(function(localAnnotation, index) { %>
|
|
22
|
-
"<%- localAnnotation %>"<% if (index < localAnnotationsName.length - 1){ %>,<% } %>
|
|
23
|
-
<% }); %>
|
|
24
|
-
<% } else if (localAnnotationsName) { %>
|
|
25
|
-
"<%- localAnnotationsName %>"
|
|
26
|
-
<% } %>
|
|
27
|
-
<% } %>
|
|
28
|
-
]
|
|
29
|
-
<% if (locals.metadata) { %>,
|
|
30
|
-
"localUri": "localService/<%- name %>/metadata.xml" <% } %><%if (version === '4') {%>,
|
|
31
|
-
"odataVersion": "4.0"<% } %><%if (version === '2') {%>,
|
|
32
|
-
"odataVersion": "2.0"<% } %>
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
<% if (locals.annotations && typeof annotations !== 'undefined') { %>
|
|
36
|
-
<% if (annotations.length && annotations.length > 0) { %>
|
|
37
|
-
<% annotations.forEach(function(annotation, index) { %>
|
|
38
|
-
<% if (annotation.technicalName) { %>,
|
|
39
|
-
"<%= annotation.name %>": {
|
|
40
|
-
"uri": "/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='<%- encodeURIComponent(annotation.technicalName) %>',Version='0001')/$value/",
|
|
41
|
-
"type": "ODataAnnotation",
|
|
42
|
-
"settings": {
|
|
43
|
-
"localUri": "localService/<%- name %>/<%- annotation.technicalName %>.xml"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
<% } %>
|
|
47
|
-
<% }); %>
|
|
48
|
-
<% } else if (annotations.technicalName) { %>,
|
|
49
|
-
"<%= annotations.name %>": {
|
|
50
|
-
"uri": "/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='<%- encodeURIComponent(annotations.technicalName) %>',Version='0001')/$value/",
|
|
51
|
-
"type": "ODataAnnotation",
|
|
52
|
-
"settings": {
|
|
53
|
-
"localUri": "localService/<%- name %>/<%- annotations.technicalName %>.xml"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
<% } %>
|
|
57
|
-
<% } %>
|
|
58
|
-
<% if (locals.localAnnotationsName && typeof localAnnotationsName !== 'undefined') { %>,
|
|
59
|
-
<% if (locals.localAnnotationsName && typeof localAnnotationsName !== 'undefined') { %>
|
|
60
|
-
<% if (Array.isArray(localAnnotationsName)) { %>
|
|
61
|
-
<% localAnnotationsName.forEach(function(localAnnotation, index) { %>
|
|
62
|
-
"<%- localAnnotation %>": {
|
|
63
|
-
"type": "ODataAnnotation",
|
|
64
|
-
"uri": "annotations/<%- localAnnotation %>.xml",
|
|
65
|
-
"settings": {
|
|
66
|
-
"localUri": "annotations/<%- localAnnotation %>.xml"
|
|
67
|
-
}
|
|
68
|
-
}<% if (index < localAnnotationsName.length - 1){ %>,<% } %>
|
|
69
|
-
<% }); %>
|
|
70
|
-
<% } else if (localAnnotationsName) { %>
|
|
71
|
-
"<%- localAnnotationsName %>": {
|
|
72
|
-
"type": "ODataAnnotation",
|
|
73
|
-
"uri": "annotations/<%- localAnnotationsName %>.xml",
|
|
74
|
-
"settings": {
|
|
75
|
-
"localUri": "annotations/<%- localAnnotationsName %>.xml"
|
|
76
|
-
}
|
|
77
|
-
} <% } %>
|
|
78
|
-
<% } %>
|
|
79
|
-
<% } %>
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
"sap.ui5": {
|
|
83
|
-
"models": {
|
|
84
|
-
"<%=model%>": {
|
|
85
|
-
"dataSource": "<%=name%>",
|
|
86
|
-
"preload": true,
|
|
87
|
-
"settings": {<%if (version === '4') {%>
|
|
88
|
-
<% if (locals.includeSynchronizationMode) { %>
|
|
89
|
-
"synchronizationMode": "None",
|
|
90
|
-
<% } %>
|
|
91
|
-
"operationMode": "Server",
|
|
92
|
-
"autoExpandSelect": true,
|
|
93
|
-
"earlyRequests": true<% } %>
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|