@sap-ux/odata-service-writer 1.0.16 → 1.0.18

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.
@@ -201,12 +201,28 @@ function removeUnusedAnnotations(fs, webappPath, dataSources, serviceName, creat
201
201
  * @param {string} webappPath - the webapp path of an existing UI5 application
202
202
  * @param dataSources - dataSources from manifest.json
203
203
  * @param serviceName - name of the OData service instance
204
- * @param {EdmxAnnotationsInfo | EdmxAnnotationsInfo[]} serviceRemoteAnnotations - remote annotations of the OData service instance
204
+ * @param {EdmxAnnotationsInfo | EdmxAnnotationsInfo[]} serviceRemoteAnnotations - remote annotations of the OData service instance; `undefined` preserves existing remote annotations (nothing pruned), an empty array prunes them
205
205
  * @param {boolean} cleanOldAnnotations - if true, checks and updates service annotations
206
206
  * @returns created annotation dataSources list for service.
207
207
  */
208
208
  function addRemoteAnnotationDataSources(fs, webappPath, dataSources, serviceName, serviceRemoteAnnotations, cleanOldAnnotations) {
209
209
  const createdAnnotations = [];
210
+ // `undefined` means the caller did not fetch annotations ("unknown"). Preserve the service's
211
+ // existing remote annotation references, dataSource entries and files - never treat unknown as
212
+ // "none". An explicit empty array is a caller-asserted "no annotations" and still prunes below.
213
+ if (serviceRemoteAnnotations === undefined) {
214
+ if (cleanOldAnnotations) {
215
+ const serviceAnnotations = dataSources?.[serviceName]?.settings?.annotations ?? [];
216
+ serviceAnnotations.forEach((name) => {
217
+ const dataSource = dataSources[name];
218
+ // Only re-collect remote annotations for the current service (uri differs from localUri).
219
+ if (dataSource?.type === 'ODataAnnotation' && dataSource.uri !== dataSource.settings?.localUri) {
220
+ createdAnnotations.push(name);
221
+ }
222
+ });
223
+ }
224
+ return createdAnnotations;
225
+ }
210
226
  if (Array.isArray(serviceRemoteAnnotations)) {
211
227
  serviceRemoteAnnotations.forEach((remoteAnnotation) => {
212
228
  if (remoteAnnotation.name) {
package/dist/update.d.ts CHANGED
@@ -20,7 +20,7 @@ export declare function addServicesData(basePath: string, paths: ProjectPaths, t
20
20
  * @param {ProjectPaths} paths - paths to the project files (package.json, ui5.yaml, ui5-local.yaml and ui5-mock.yaml)
21
21
  * @param {EdmxOdataService} service - the OData service instance
22
22
  * @param {Editor} fs - the memfs editor instance
23
- * @param {boolean} updateMiddlewares - whether the YAML files for the service (mock-server and fiori-tools-proxy middlewares) should be updated
23
+ * @param {boolean} updateMiddlewares - whether the backend proxy (fiori-tools-proxy) middleware in ui5*.yaml should be updated. The mockserver (sap-fe-mockserver) middleware is additionally regenerated whenever external (value-help) services are present, so the written external metadata stays resolvable.
24
24
  */
25
25
  export declare function updateServicesData(basePath: string, paths: ProjectPaths, service: EdmxOdataService, fs: Editor, updateMiddlewares: boolean): Promise<void>;
26
26
  //# sourceMappingURL=update.d.ts.map
package/dist/update.js CHANGED
@@ -146,20 +146,27 @@ export async function addServicesData(basePath, paths, templateRoot, service, fs
146
146
  * @param {ProjectPaths} paths - paths to the project files (package.json, ui5.yaml, ui5-local.yaml and ui5-mock.yaml)
147
147
  * @param {EdmxOdataService} service - the OData service instance
148
148
  * @param {Editor} fs - the memfs editor instance
149
- * @param {boolean} updateMiddlewares - whether the YAML files for the service (mock-server and fiori-tools-proxy middlewares) should be updated
149
+ * @param {boolean} updateMiddlewares - whether the backend proxy (fiori-tools-proxy) middleware in ui5*.yaml should be updated. The mockserver (sap-fe-mockserver) middleware is additionally regenerated whenever external (value-help) services are present, so the written external metadata stays resolvable.
150
150
  */
151
151
  export async function updateServicesData(basePath, paths, service, fs, updateMiddlewares) {
152
152
  let ui5Config;
153
153
  let ui5LocalConfig;
154
- if (updateMiddlewares) {
155
- if (paths.ui5Yaml) {
156
- ui5Config = await UI5Config.newInstance(fs.read(paths.ui5Yaml));
154
+ // The mockserver middleware is derived from the manifest and must stay consistent with the external
155
+ // (value-help) metadata files we write. Regenerate it whenever external services are present, even
156
+ // when the backend proxy middlewares are being preserved (updateMiddlewares === false).
157
+ const updateMockserver = updateMiddlewares || !!service.externalServices?.length;
158
+ if (updateMockserver && paths.ui5Yaml) {
159
+ ui5Config = await UI5Config.newInstance(fs.read(paths.ui5Yaml));
160
+ // Only re-point the backend proxy middleware when explicitly requested.
161
+ if (updateMiddlewares) {
157
162
  // Update ui5.yaml with backend middleware
158
163
  extendBackendMiddleware(fs, service, ui5Config, paths.ui5Yaml, true);
159
164
  }
165
+ }
166
+ if (updateMockserver && paths.ui5LocalYaml) {
167
+ ui5LocalConfig = await UI5Config.newInstance(fs.read(paths.ui5LocalYaml));
160
168
  // Update ui5-local.yaml with backend middleware
161
- if (paths.ui5LocalYaml) {
162
- ui5LocalConfig = await UI5Config.newInstance(fs.read(paths.ui5LocalYaml));
169
+ if (updateMiddlewares) {
163
170
  extendBackendMiddleware(fs, service, ui5LocalConfig, paths.ui5LocalYaml, true);
164
171
  }
165
172
  }
@@ -184,7 +191,7 @@ export async function updateServicesData(basePath, paths, service, fs, updateMid
184
191
  * @param {UI5Config | undefined} ui5Config - ui5.yaml configuration
185
192
  * @param {UI5Config | undefined} ui5LocalConfig - ui5-local.yaml configuration
186
193
  * @param {Editor} fs - the memfs editor instance
187
- * @param {boolean} updateMiddlewares - whether the YAML files for the service (mock-server and fiori-tools-proxy middlewares) should be updated
194
+ * @param {boolean} updateMiddlewares - whether the backend proxy (fiori-tools-proxy) middleware should be updated
188
195
  * @returns {Promise<string | undefined>} webapp path if metadata was written, undefined otherwise
189
196
  */
190
197
  async function updateMetadata(basePath, paths, service, ui5Config, ui5LocalConfig, fs, updateMiddlewares) {
@@ -192,8 +199,12 @@ async function updateMetadata(basePath, paths, service, ui5Config, ui5LocalConfi
192
199
  return undefined;
193
200
  }
194
201
  const webappPath = await getWebappPath(basePath, fs);
202
+ // The mockserver middleware is derived from the manifest and must stay consistent with the external
203
+ // (value-help) metadata files we write. Regenerate it whenever external services are present, even
204
+ // when the backend proxy middlewares are being preserved (updateMiddlewares === false).
205
+ const updateMockserver = updateMiddlewares || !!service.externalServices?.length;
195
206
  // Generate mockserver only when ui5-mock.yaml already exists
196
- if (paths.ui5MockYaml && paths.ui5Yaml && ui5Config && updateMiddlewares) {
207
+ if (paths.ui5MockYaml && paths.ui5Yaml && ui5Config && updateMockserver) {
197
208
  const config = {
198
209
  webappPath: webappPath,
199
210
  // Since ui5-mock.yaml already exists, set 'skip' to skip package.json file updates
@@ -214,8 +225,9 @@ async function updateMetadata(basePath, paths, service, ui5Config, ui5LocalConfi
214
225
  await generateMockserverConfig(basePath, config, fs);
215
226
  // Update ui5-local.yaml with mockserver middleware from updated ui5-mock.yaml
216
227
  await generateMockserverMiddlewareBasedOnUi5MockYaml(fs, paths.ui5Yaml, paths.ui5LocalYaml, ui5LocalConfig);
217
- // Update ui5-mock.yaml with backend middleware
218
- if (paths.ui5MockYaml) {
228
+ // Update ui5-mock.yaml with backend middleware only when the backend proxy is being (re)pointed;
229
+ // a metadata re-sync (updateMiddlewares === false) preserves the existing proxy configuration.
230
+ if (updateMiddlewares && paths.ui5MockYaml) {
219
231
  const ui5MockConfig = await UI5Config.newInstance(fs.read(paths.ui5MockYaml));
220
232
  extendBackendMiddleware(fs, service, ui5MockConfig, paths.ui5MockYaml, true);
221
233
  }
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "bugs": {
11
11
  "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aodata-service-writer"
12
12
  },
13
- "version": "1.0.16",
13
+ "version": "1.0.18",
14
14
  "license": "Apache-2.0",
15
15
  "main": "dist/index.js",
16
16
  "files": [
@@ -30,9 +30,9 @@
30
30
  "mem-fs-editor": "9.4.0",
31
31
  "semver": "7.8.5",
32
32
  "xml-formatter": "3.7.0",
33
- "@sap-ux/mockserver-config-writer": "1.0.14",
34
- "@sap-ux/project-access": "2.1.9",
35
- "@sap-ux/ui5-config": "1.0.6"
33
+ "@sap-ux/mockserver-config-writer": "1.0.15",
34
+ "@sap-ux/project-access": "2.1.10",
35
+ "@sap-ux/ui5-config": "1.0.7"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@jest/globals": "30.4.1",