Fix unable to save blueprints in cds-ui 02/143502/2
authorFiete Ostkamp <fiete.ostkamp@telekom.de>
Thu, 5 Mar 2026 10:09:55 +0000 (11:09 +0100)
committerFiete Ostkamp <fiete.ostkamp@telekom.de>
Thu, 5 Mar 2026 11:59:24 +0000 (12:59 +0100)
- remove trailing slashes in cds-ui backend to avoid cds-blueprints
  -processor returning 404

Issue-ID: CCSDK-4165
Change-Id: I493024f924c9797957d142420119e2777d38524c
Signed-off-by: Fiete Ostkamp <fiete.ostkamp@telekom.de>
cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts
cds-ui/e2e-playwright/mock-processor/server.js
cds-ui/server/src/controllers/blueprint-rest.controller.ts
cds-ui/server/src/datasources/blueprint.datasource-template.ts

index 1d23405..70c28a6 100644 (file)
@@ -140,8 +140,9 @@ export class PackageCreationComponent extends ComponentCanDeactivate implements
                             this.router.navigate(['/packages/package/' + id]);
                         }
                     }, error => {
-                        // this.toastService.error('Error occure during editng process ' + error.message);
+                        this.toastService.error('Error occurred during save: ' + error.message);
                         console.log('Error -' + error.message);
+                        this.ngxService.stop();
                     }, () => {
                         this.ngxService.stop();
                     });
index dd6bcd3..3def580 100644 (file)
@@ -158,8 +158,8 @@ const server = http.createServer(async (req, res) => {
     return res.end(buf);
   }
 
-  // GET /api/v1/blueprint-model/   (list all)
-  if (method === 'GET' && pathname === `${BASE}/blueprint-model/`) {
+  // GET /api/v1/blueprint-model   (list all)
+  if (method === 'GET' && (pathname === `${BASE}/blueprint-model/` || pathname === `${BASE}/blueprint-model`)) {
     return json(res, blueprints);
   }
 
@@ -176,8 +176,8 @@ const server = http.createServer(async (req, res) => {
     return json(res, { message: 'deleted', id: m[1] });
   }
 
-  // POST /api/v1/blueprint-model/enrich/   – returns enriched CBA zip
-  if (method === 'POST' && pathname === `${BASE}/blueprint-model/enrich/`) {
+  // POST /api/v1/blueprint-model/enrich   – returns enriched CBA zip
+  if (method === 'POST' && (pathname === `${BASE}/blueprint-model/enrich` || pathname === `${BASE}/blueprint-model/enrich/`)) {
     await readBody(req); // drain multipart body
     const buf = minimalZip();
     res.writeHead(200, {
@@ -190,10 +190,12 @@ const server = http.createServer(async (req, res) => {
 
   // POST upload stubs – drain multipart body, echo back first fixture blueprint
   if (method === 'POST' && (
+    pathname === `${BASE}/blueprint-model` ||
     pathname === `${BASE}/blueprint-model/` ||
+    pathname === `${BASE}/blueprint-model/publish` ||
     pathname === `${BASE}/blueprint-model/publish/` ||
-    pathname === `${BASE}/blueprint-model/enrichandpublish/` ||
-    pathname === `${BASE}/blueprint-model/publish`   // deploy (no trailing slash)
+    pathname === `${BASE}/blueprint-model/enrichandpublish` ||
+    pathname === `${BASE}/blueprint-model/enrichandpublish/`
   )) {
     await readBody(req);
     return json(res, blueprints[0]);
index a8b989f..8530a23 100644 (file)
@@ -161,12 +161,13 @@ export class BlueprintRestController {
   ): Promise<Response> {
     return new Promise((resolve, reject) => {
       this.getFileFromMultiPartForm(request).then(file => {
-        // if (appConfig.action.deployBlueprint.grpcEnabled)
         if (appConfig.action.grpcEnabled)
           return this.uploadFileToBlueprintProcessorGrpc(file, 'DRAFT', response);
         else
-          return this.uploadFileToBlueprintController(file, '/blueprint-model/', response);
-      }, err => {
+          return this.uploadFileToBlueprintController(file, '/blueprint-model', response);
+      }).then(resp => {
+        resolve(resp);
+      }).catch(err => {
         reject(err);
       });
     });
@@ -201,12 +202,13 @@ export class BlueprintRestController {
   ): Promise<Response> {
     return new Promise((resolve, reject) => {
       this.getFileFromMultiPartForm(request).then(file => {
-        // if (appConfig.action.deployBlueprint.grpcEnabled)
         if (appConfig.action.grpcEnabled)
           return this.uploadFileToBlueprintProcessorGrpc(file, 'PUBLISH', response);
         else
-          return this.uploadFileToBlueprintController(file, '/blueprint-model/publish/', response);
-      }, err => {
+          return this.uploadFileToBlueprintController(file, '/blueprint-model/publish', response);
+      }).then(resp => {
+        resolve(resp);
+      }).catch(err => {
         reject(err);
       });
     });
@@ -244,7 +246,7 @@ export class BlueprintRestController {
         if (appConfig.action.grpcEnabled)
           return this.uploadFileToBlueprintProcessorGrpc(file, 'ENRICH', response);
         else
-          return this.uploadFileToBlueprintController(file, '/blueprint-model/enrich/', response);
+          return this.uploadFileToBlueprintController(file, '/blueprint-model/enrich', response);
         //   this.uploadFileToBlueprintController(file, "/blueprint-model/enrich/", response).then(resp => {
         //     resolve(resp);
         //   }, err => {
@@ -252,6 +254,10 @@ export class BlueprintRestController {
         //   });
         // }, err => {
         //   reject(err);
+      }).then(resp => {
+        resolve(resp);
+      }).catch(err => {
+        reject(err);
       });
     });
   }
@@ -277,7 +283,11 @@ export class BlueprintRestController {
         if (appConfig.action.grpcEnabled)
           return this.uploadFileToBlueprintProcessorGrpc(file, 'ENRICH', response);
         else
-          return this.uploadFileToBlueprintController(file, '/blueprint-model/enrichandpublish/', response);
+          return this.uploadFileToBlueprintController(file, '/blueprint-model/enrichandpublish', response);
+      }).then(resp => {
+        resolve(resp);
+      }).catch(err => {
+        reject(err);
       });
     });
   }
@@ -329,12 +339,13 @@ export class BlueprintRestController {
   ): Promise<Response> {
     return new Promise((resolve, reject) => {
       this.getFileFromMultiPartForm(request).then(file => {
-        // if (appConfig.action.deployBlueprint.grpcEnabled)
         if (appConfig.action.grpcEnabled)
           return this.uploadFileToBlueprintProcessorGrpc(file, 'PUBLISH', response);
         else
           return this.uploadFileToBlueprintProcessor(file, '/blueprint-model/publish', response);
-      }, err => {
+      }).then(resp => {
+        resolve(resp);
+      }).catch(err => {
         reject(err);
       });
     });
index dc1cd37..2dec3f1 100644 (file)
@@ -9,7 +9,7 @@ export default {
     "operations": [{
         "template": {
             "method": "GET",
-            "url": processorApiConfig.http.url + "/blueprint-model/",
+            "url": processorApiConfig.http.url + "/blueprint-model",
             "headers": {
                 "accepts": "application/json",
                 "content-type": "application/json",