@sap-ux/odata-service-writer 0.24.1 → 0.25.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.
@@ -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 EJS template, annotation names are used to add annotations to the manifest.json.
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, templateRoot);
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/types.d.ts CHANGED
@@ -66,7 +66,7 @@ export interface OdataService {
66
66
  * Annotations can either be EDMX annotations or CDS annotations.
67
67
  */
68
68
  annotations?: EdmxAnnotationsInfo | EdmxAnnotationsInfo[] | CdsAnnotationsInfo | CdsAnnotationsInfo[];
69
- localAnnotationsName?: string;
69
+ localAnnotationsName?: string | string[];
70
70
  previewSettings?: Partial<ProxyBackend>;
71
71
  /**
72
72
  * Indicates whether certificate errors should be ignored.
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, templateRoot: string): Promise<void>;
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 {Manifest} dataSource - dataSource configuration from manifest.json
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) {
@@ -71,9 +227,8 @@ async function updateExistingServices(webappPath, manifest, fs) {
71
227
  * @param basePath - the root path of an existing UI5 application
72
228
  * @param service - the OData service instance
73
229
  * @param fs - the memfs editor instance
74
- * @param templateRoot - root folder contain the ejs templates
75
230
  */
76
- async function updateManifest(basePath, service, fs, templateRoot) {
231
+ async function updateManifest(basePath, service, fs) {
77
232
  const webappPath = await (0, project_access_1.getWebappPath)(basePath, fs);
78
233
  const manifestPath = (0, path_1.join)(webappPath, 'manifest.json');
79
234
  // Get component app id
@@ -87,11 +242,9 @@ async function updateManifest(basePath, service, fs, templateRoot) {
87
242
  if (!appid) {
88
243
  throw new Error((0, i18n_1.t)('error.requiredProjectPropertyNotFound', { property: `'${appProp}'.id`, path: manifestPath }));
89
244
  }
90
- const manifestJsonExt = fs.read((0, path_1.join)(templateRoot, 'extend', `manifest.json`));
91
- const manifestSettings = Object.assign(service, getModelSettings((0, project_access_1.getMinimumUI5Version)(modifiedManifest)));
92
- // If the service object includes ejs options, for example 'client' (see: https://ejs.co/#docs),
93
- // resulting in unexpected behaviour and problems when webpacking. Passing an empty options object prevents this.
94
- fs.extendJSON(manifestPath, JSON.parse((0, ejs_1.render)(manifestJsonExt, manifestSettings, {})));
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.24.1",
12
+ "version": "0.25.0",
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.8"
41
+ "@sap-ux/project-access": "1.28.9"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=18.x"
@@ -1,79 +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) { %>,<% } %>
14
- <% } %>
15
- <% }); %>
16
- <% } else if (annotations.technicalName) { %>
17
- "<%= annotations.name %>"
18
- <% } %>
19
- <% if (locals.localAnnotationsName) {%>,<%}%><% } %>
20
- <% if (locals.localAnnotationsName) { %>
21
- "<%- localAnnotationsName %>"
22
- <% } %>
23
- ]
24
- <% if (locals.metadata) { %>,
25
- "localUri": "localService/<%- name %>/metadata.xml" <% } %><%if (version === '4') {%>,
26
- "odataVersion": "4.0"<% } %><%if (version === '2') {%>,
27
- "odataVersion": "2.0"<% } %>
28
- }
29
- }
30
- <% if (locals.annotations && typeof annotations !== 'undefined') { %>
31
- <% if (annotations.length && annotations.length > 0) { %>
32
- <% annotations.forEach(function(annotation, index) { %>
33
- <% if (annotation.technicalName) { %>,
34
- "<%= annotation.name %>": {
35
- "uri": "/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='<%- encodeURIComponent(annotation.technicalName) %>',Version='0001')/$value/",
36
- "type": "ODataAnnotation",
37
- "settings": {
38
- "localUri": "localService/<%- name %>/<%- annotation.technicalName %>.xml"
39
- }
40
- }
41
- <% } %>
42
- <% }); %>
43
- <% } else if (annotations.technicalName) { %>,
44
- "<%= annotations.name %>": {
45
- "uri": "/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='<%- encodeURIComponent(annotations.technicalName) %>',Version='0001')/$value/",
46
- "type": "ODataAnnotation",
47
- "settings": {
48
- "localUri": "localService/<%- name %>/<%- annotations.technicalName %>.xml"
49
- }
50
- }
51
- <% } %>
52
- <% } %>
53
- <% if (locals.localAnnotationsName) { %>,
54
- "<%- localAnnotationsName %>": {
55
- "type": "ODataAnnotation",
56
- "uri": "annotations/<%- localAnnotationsName %>.xml",
57
- "settings": {
58
- "localUri": "annotations/<%- localAnnotationsName %>.xml"
59
- }
60
- } <% } %>
61
- }
62
- },
63
- "sap.ui5": {
64
- "models": {
65
- "<%=model%>": {
66
- "dataSource": "<%=name%>",
67
- "preload": true,
68
- "settings": {<%if (version === '4') {%>
69
- <% if (locals.includeSynchronizationMode) { %>
70
- "synchronizationMode": "None",
71
- <% } %>
72
- "operationMode": "Server",
73
- "autoExpandSelect": true,
74
- "earlyRequests": true<% } %>
75
- }
76
- }
77
- }
78
- }
79
- }