From 7cd35b2ed0db5158de954cc18f16db6a9f2fee63 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Jul 2026 18:16:16 +0000 Subject: [PATCH] fix: ship html5-module build scaffolding for app/z2ui5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The published app's mta.yaml declares the html5 module `abap2UI5` (path app/z2ui5) with build commands `npm install && npm run build:cf`, but app/z2ui5 shipped only a webapp/ folder — no package.json and no build:cf script. Every `mbt build` (the cap2UI5 deploy-check gate) died with `npm error Missing script: "build:cf"`, so the app was not CF-deployable. Add the missing scaffolding as siblings of webapp/ in src/app/z2ui5/ (assemble copies src/ verbatim and overlays only app/z2ui5/webapp, so these survive): - package.json — @ui5/cli devDep + `build:cf` (ui5 build → dist, then copies xs-app.json into dist so the HTML5-repo content is complete) - ui5.yaml — UI5 tooling config (type: application; the UI5 runtime is loaded at request time from the `ui5` destination, so the build only bundles the app's own Component-preload) - xs-app.json — managed-approuter routing: /resources + /test-resources to the ui5 destination, everything else to the html5-apps-repo runtime Verified end-to-end against the real core mirror: assemble keeps the scaffolding beside the overlaid webapp, and `npm install && npm run build:cf` produces a complete dist/ (Component-preload.js, manifest.json, index.html, xs-app.json). Add a regression test asserting the scaffolding survives the webapp overlay. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Hv64RwyNgeCDHqvUDrst7u --- src/app/z2ui5/package.json | 12 ++++++++++++ src/app/z2ui5/ui5.yaml | 8 ++++++++ src/app/z2ui5/xs-app.json | 24 ++++++++++++++++++++++++ test/assemble-cap.test.js | 23 +++++++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 src/app/z2ui5/package.json create mode 100644 src/app/z2ui5/ui5.yaml create mode 100644 src/app/z2ui5/xs-app.json diff --git a/src/app/z2ui5/package.json b/src/app/z2ui5/package.json new file mode 100644 index 0000000..5ca9b6d --- /dev/null +++ b/src/app/z2ui5/package.json @@ -0,0 +1,12 @@ +{ + "name": "z2ui5", + "version": "1.0.0", + "private": true, + "description": "abap2UI5 UI5 frontend — html5 module built and deployed to the SAP BTP HTML5 application repository by the mta.yaml `abap2UI5` module", + "scripts": { + "build:cf": "ui5 build --clean-dest --dest dist && node -e \"require('fs').copyFileSync('xs-app.json','dist/xs-app.json')\"" + }, + "devDependencies": { + "@ui5/cli": "^4.0.0" + } +} diff --git a/src/app/z2ui5/ui5.yaml b/src/app/z2ui5/ui5.yaml new file mode 100644 index 0000000..939779f --- /dev/null +++ b/src/app/z2ui5/ui5.yaml @@ -0,0 +1,8 @@ +specVersion: "3.0" +metadata: + name: z2ui5 +type: application +# The UI5 runtime is loaded at request time from the `ui5` destination +# (https://ui5.sap.com, see mta.yaml + xs-app.json), so the build only +# bundles the app's own code (Component-preload) — no framework libraries +# are resolved or self-contained here. diff --git a/src/app/z2ui5/xs-app.json b/src/app/z2ui5/xs-app.json new file mode 100644 index 0000000..3bdf638 --- /dev/null +++ b/src/app/z2ui5/xs-app.json @@ -0,0 +1,24 @@ +{ + "welcomeFile": "/index.html", + "authenticationMethod": "route", + "routes": [ + { + "source": "^/resources/(.*)$", + "target": "/resources/$1", + "destination": "ui5", + "authenticationType": "none" + }, + { + "source": "^/test-resources/(.*)$", + "target": "/test-resources/$1", + "destination": "ui5", + "authenticationType": "none" + }, + { + "source": "^(.*)$", + "target": "$1", + "service": "html5-apps-repo-rt", + "authenticationType": "xsuaa" + } + ] +} diff --git a/test/assemble-cap.test.js b/test/assemble-cap.test.js index 6cd8aea..97a7339 100644 --- a/test/assemble-cap.test.js +++ b/test/assemble-cap.test.js @@ -144,6 +144,29 @@ describe("assemble-cap happy path", () => { expect(lock.packages["node_modules/express"].version).toBe("5.0.0"); }); + test("html5 module scaffolding in src/app/z2ui5 survives the webapp overlay", () => { + root = makeFixture(); + // the deployable html5 module (mta.yaml `abap2UI5`, path app/z2ui5) + // ships its build scaffolding as a sibling of webapp/. The overlay must + // replace only app/z2ui5/webapp, never the scaffolding next to it. + writeJson(path.join(root, "src", "app", "z2ui5", "package.json"), { + name: "z2ui5", + scripts: { "build:cf": "ui5 build --clean-dest --dest dist" }, + }); + write(path.join(root, "src", "app", "z2ui5", "ui5.yaml"), "type: application\n"); + write(path.join(root, "src", "app", "z2ui5", "xs-app.json"), "{}\n"); + + expect(runAssemble(root).status).toBe(0); + + const z2ui5 = path.join(root, "run", "output", "cap2UI5", "app", "z2ui5"); + // scaffolding preserved verbatim … + expect(readJson(path.join(z2ui5, "package.json")).scripts["build:cf"]).toBeDefined(); + expect(fs.existsSync(path.join(z2ui5, "ui5.yaml"))).toBe(true); + expect(fs.existsSync(path.join(z2ui5, "xs-app.json"))).toBe(true); + // … and the webapp is still overlaid from the core right beside it + expect(fs.existsSync(path.join(z2ui5, "webapp", "Component.js"))).toBe(true); + }); + test("is idempotent — a second run succeeds and produces the same lock", () => { root = makeFixture(); expect(runAssemble(root).status).toBe(0);