From c464eeafddfeb52f2116c25c2cbe075af1c218b0 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 14:16:38 +0000 Subject: [PATCH 1/3] Migrate builder-cap2UI5 out of the cap2UI5 monorepo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the CAP app build project (src/ + assemble/publish scripts) from cap2UI5/cap2UI5:builder-cap2UI5/ into this standalone repository and adapt it to the split: - new scripts/mirror-core.js snapshots the published core package from cap2UI5/builder-abap2UI5-js into run/input/core (committed, with UPSTREAM_COMMIT — same convention as the other mirrors) - assemble-cap.js now vendors the mirrored core INTO the app (core/, linked as file:./core instead of file:../builder-abap2UI5-js/core), so the published app repo is fully self-contained; the core's lock entries are merged into the app lock under core/node_modules/ (npm manages the vendored package as part of the app tree) - publish-cap.js publishes into a checkout of cap2UI5/cap2UI5 (sibling directory or PUBLISH_TARGET), preserving that repo's .git/.github - workflows: update_cap (push/nightly/dispatch) mirrors the core, builds, runs the app's jest suite and publishes to cap2UI5/cap2UI5 via deploy key (secret ACTION_KEY_APP, skipped when unset); test runs the same assemble + jest gate on PRs; UPSTREAM_HEAD receives the triggers from builder-abap2UI5-js:trigger_cap - src/: dependency now file:../run/input/core, README/badges updated to the three-repo layout Verified locally: mirror_core (local checkout) → assemble → npm ci → npm test all green (2 suites, 11 tests); assemble output is deterministic. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01ScZqNHaaKSyyd5kYTAXyFR --- .github/workflows/test.yml | 31 + .github/workflows/update_cap.yml | 98 + .gitignore | 4 + README.md | 101 +- UPSTREAM_HEAD | 1 + package-lock.json | 16 + package.json | 18 + run/input/UPSTREAM_COMMIT | 1 + run/input/core/README.md | 52 + run/input/core/app/z2ui5/webapp/Component.js | 249 + run/input/core/app/z2ui5/webapp/Util.js | 35 + .../core/app/z2ui5/webapp/cc/CameraPicture.js | 221 + .../app/z2ui5/webapp/cc/CameraSelector.js | 36 + run/input/core/app/z2ui5/webapp/cc/Dirty.js | 55 + run/input/core/app/z2ui5/webapp/cc/Favicon.js | 28 + .../core/app/z2ui5/webapp/cc/FileUploader.js | 181 + run/input/core/app/z2ui5/webapp/cc/Focus.js | 67 + .../core/app/z2ui5/webapp/cc/Geolocation.js | 116 + run/input/core/app/z2ui5/webapp/cc/History.js | 31 + run/input/core/app/z2ui5/webapp/cc/Info.js | 119 + run/input/core/app/z2ui5/webapp/cc/LPTitle.js | 53 + .../core/app/z2ui5/webapp/cc/MultiInputExt.js | 72 + .../core/app/z2ui5/webapp/cc/Scrolling.js | 130 + .../app/z2ui5/webapp/cc/SmartMultiInputExt.js | 142 + run/input/core/app/z2ui5/webapp/cc/Storage.js | 92 + run/input/core/app/z2ui5/webapp/cc/Timer.js | 67 + run/input/core/app/z2ui5/webapp/cc/Title.js | 19 + run/input/core/app/z2ui5/webapp/cc/Tree.js | 72 + .../core/app/z2ui5/webapp/cc/UITableExt.js | 193 + .../core/app/z2ui5/webapp/cc/UploadSetExt.js | 104 + .../z2ui5/webapp/controller/App.controller.js | 50 + .../webapp/controller/View1.controller.js | 525 + .../core/app/z2ui5/webapp/core/AppState.js | 196 + .../z2ui5/webapp/core/DebugTool.fragment.xml | 103 + .../core/app/z2ui5/webapp/core/DebugTool.js | 318 + .../core/app/z2ui5/webapp/core/ErrorView.js | 176 + .../app/z2ui5/webapp/core/FrontendAction.js | 593 ++ run/input/core/app/z2ui5/webapp/core/Lib.js | 366 + .../core/app/z2ui5/webapp/core/Messages.js | 93 + .../core/app/z2ui5/webapp/core/Server.js | 544 ++ .../core/app/z2ui5/webapp/core/ViewSlots.js | 162 + run/input/core/app/z2ui5/webapp/css/style.css | 1 + run/input/core/app/z2ui5/webapp/index.html | 35 + run/input/core/app/z2ui5/webapp/manifest.json | 89 + .../core/app/z2ui5/webapp/model/models.js | 16 + .../core/app/z2ui5/webapp/view/App.view.xml | 5 + run/input/core/package-lock.json | 5631 +++++++++++ run/input/core/package.json | 50 + run/input/core/srv/app/samples/README.md | 119 + .../srv/app/samples/z2ui5_cl_demo_app_001.js | 30 + .../srv/app/samples/z2ui5_cl_demo_app_003.js | 24 + .../srv/app/samples/z2ui5_cl_demo_app_004.js | 83 + .../srv/app/samples/z2ui5_cl_demo_app_005.js | 28 + .../srv/app/samples/z2ui5_cl_demo_app_006.js | 92 + .../srv/app/samples/z2ui5_cl_demo_app_008.js | 99 + .../srv/app/samples/z2ui5_cl_demo_app_009.js | 152 + .../srv/app/samples/z2ui5_cl_demo_app_011.js | 76 + .../srv/app/samples/z2ui5_cl_demo_app_012.js | 120 + .../srv/app/samples/z2ui5_cl_demo_app_015.js | 27 + .../srv/app/samples/z2ui5_cl_demo_app_017.js | 131 + .../srv/app/samples/z2ui5_cl_demo_app_019.js | 84 + .../srv/app/samples/z2ui5_cl_demo_app_020.js | 38 + .../srv/app/samples/z2ui5_cl_demo_app_021.js | 30 + .../srv/app/samples/z2ui5_cl_demo_app_022.js | 22 + .../srv/app/samples/z2ui5_cl_demo_app_024.js | 77 + .../srv/app/samples/z2ui5_cl_demo_app_025.js | 90 + .../srv/app/samples/z2ui5_cl_demo_app_026.js | 70 + .../srv/app/samples/z2ui5_cl_demo_app_027.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_028.js | 52 + .../srv/app/samples/z2ui5_cl_demo_app_030.js | 65 + .../srv/app/samples/z2ui5_cl_demo_app_035.js | 188 + .../srv/app/samples/z2ui5_cl_demo_app_038.js | 65 + .../srv/app/samples/z2ui5_cl_demo_app_041.js | 33 + .../srv/app/samples/z2ui5_cl_demo_app_047.js | 61 + .../srv/app/samples/z2ui5_cl_demo_app_048.js | 34 + .../srv/app/samples/z2ui5_cl_demo_app_051.js | 28 + .../srv/app/samples/z2ui5_cl_demo_app_052.js | 78 + .../srv/app/samples/z2ui5_cl_demo_app_053.js | 67 + .../srv/app/samples/z2ui5_cl_demo_app_056.js | 114 + .../srv/app/samples/z2ui5_cl_demo_app_059.js | 57 + .../srv/app/samples/z2ui5_cl_demo_app_061.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_062.js | 26 + .../srv/app/samples/z2ui5_cl_demo_app_064.js | 76 + .../srv/app/samples/z2ui5_cl_demo_app_065.js | 46 + .../srv/app/samples/z2ui5_cl_demo_app_067.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_068.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_069.js | 69 + .../srv/app/samples/z2ui5_cl_demo_app_070.js | 207 + .../srv/app/samples/z2ui5_cl_demo_app_071.js | 35 + .../srv/app/samples/z2ui5_cl_demo_app_073.js | 27 + .../srv/app/samples/z2ui5_cl_demo_app_074.js | 94 + .../srv/app/samples/z2ui5_cl_demo_app_075.js | 65 + .../srv/app/samples/z2ui5_cl_demo_app_078.js | 52 + .../srv/app/samples/z2ui5_cl_demo_app_080.js | 52 + .../srv/app/samples/z2ui5_cl_demo_app_081.js | 100 + .../srv/app/samples/z2ui5_cl_demo_app_088.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_097.js | 93 + .../srv/app/samples/z2ui5_cl_demo_app_098.js | 96 + .../srv/app/samples/z2ui5_cl_demo_app_101.js | 54 + .../srv/app/samples/z2ui5_cl_demo_app_103.js | 50 + .../srv/app/samples/z2ui5_cl_demo_app_104.js | 97 + .../srv/app/samples/z2ui5_cl_demo_app_106.js | 28 + .../srv/app/samples/z2ui5_cl_demo_app_109.js | 88 + .../srv/app/samples/z2ui5_cl_demo_app_110.js | 72 + .../srv/app/samples/z2ui5_cl_demo_app_122.js | 107 + .../srv/app/samples/z2ui5_cl_demo_app_125.js | 26 + .../srv/app/samples/z2ui5_cl_demo_app_126.js | 104 + .../srv/app/samples/z2ui5_cl_demo_app_133.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_136.js | 94 + .../srv/app/samples/z2ui5_cl_demo_app_144.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_160.js | 172 + .../srv/app/samples/z2ui5_cl_demo_app_161.js | 62 + .../srv/app/samples/z2ui5_cl_demo_app_163.js | 46 + .../srv/app/samples/z2ui5_cl_demo_app_166.js | 44 + .../srv/app/samples/z2ui5_cl_demo_app_167.js | 43 + .../srv/app/samples/z2ui5_cl_demo_app_173.js | 56 + .../srv/app/samples/z2ui5_cl_demo_app_175.js | 26 + .../srv/app/samples/z2ui5_cl_demo_app_176.js | 43 + .../srv/app/samples/z2ui5_cl_demo_app_181.js | 69 + .../srv/app/samples/z2ui5_cl_demo_app_187.js | 35 + .../srv/app/samples/z2ui5_cl_demo_app_189.js | 49 + .../srv/app/samples/z2ui5_cl_demo_app_197.js | 91 + .../srv/app/samples/z2ui5_cl_demo_app_202.js | 45 + .../srv/app/samples/z2ui5_cl_demo_app_205.js | 81 + .../srv/app/samples/z2ui5_cl_demo_app_206.js | 28 + .../srv/app/samples/z2ui5_cl_demo_app_207.js | 71 + .../srv/app/samples/z2ui5_cl_demo_app_208.js | 59 + .../srv/app/samples/z2ui5_cl_demo_app_209.js | 69 + .../srv/app/samples/z2ui5_cl_demo_app_210.js | 30 + .../srv/app/samples/z2ui5_cl_demo_app_213.js | 22 + .../srv/app/samples/z2ui5_cl_demo_app_214.js | 28 + .../srv/app/samples/z2ui5_cl_demo_app_215.js | 23 + .../srv/app/samples/z2ui5_cl_demo_app_216.js | 29 + .../srv/app/samples/z2ui5_cl_demo_app_217.js | 25 + .../srv/app/samples/z2ui5_cl_demo_app_218.js | 23 + .../srv/app/samples/z2ui5_cl_demo_app_219.js | 51 + .../srv/app/samples/z2ui5_cl_demo_app_220.js | 42 + .../srv/app/samples/z2ui5_cl_demo_app_221.js | 32 + .../srv/app/samples/z2ui5_cl_demo_app_222.js | 32 + .../srv/app/samples/z2ui5_cl_demo_app_223.js | 32 + .../srv/app/samples/z2ui5_cl_demo_app_224.js | 32 + .../srv/app/samples/z2ui5_cl_demo_app_225.js | 75 + .../srv/app/samples/z2ui5_cl_demo_app_226.js | 103 + .../srv/app/samples/z2ui5_cl_demo_app_227.js | 40 + .../srv/app/samples/z2ui5_cl_demo_app_228.js | 29 + .../srv/app/samples/z2ui5_cl_demo_app_229.js | 25 + .../srv/app/samples/z2ui5_cl_demo_app_230.js | 26 + .../srv/app/samples/z2ui5_cl_demo_app_231.js | 80 + .../srv/app/samples/z2ui5_cl_demo_app_232.js | 26 + .../srv/app/samples/z2ui5_cl_demo_app_233.js | 25 + .../srv/app/samples/z2ui5_cl_demo_app_234.js | 25 + .../srv/app/samples/z2ui5_cl_demo_app_235.js | 104 + .../srv/app/samples/z2ui5_cl_demo_app_236.js | 31 + .../srv/app/samples/z2ui5_cl_demo_app_237.js | 62 + .../srv/app/samples/z2ui5_cl_demo_app_238.js | 51 + .../srv/app/samples/z2ui5_cl_demo_app_239.js | 76 + .../srv/app/samples/z2ui5_cl_demo_app_240.js | 119 + .../srv/app/samples/z2ui5_cl_demo_app_241.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_242.js | 44 + .../srv/app/samples/z2ui5_cl_demo_app_245.js | 81 + .../srv/app/samples/z2ui5_cl_demo_app_246.js | 50 + .../srv/app/samples/z2ui5_cl_demo_app_247.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_248.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_249.js | 63 + .../srv/app/samples/z2ui5_cl_demo_app_250.js | 92 + .../srv/app/samples/z2ui5_cl_demo_app_251.js | 48 + .../srv/app/samples/z2ui5_cl_demo_app_252.js | 83 + .../srv/app/samples/z2ui5_cl_demo_app_257.js | 80 + .../srv/app/samples/z2ui5_cl_demo_app_259.js | 115 + .../srv/app/samples/z2ui5_cl_demo_app_260.js | 120 + .../srv/app/samples/z2ui5_cl_demo_app_261.js | 49 + .../srv/app/samples/z2ui5_cl_demo_app_262.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_263.js | 48 + .../srv/app/samples/z2ui5_cl_demo_app_264.js | 56 + .../srv/app/samples/z2ui5_cl_demo_app_265.js | 42 + .../srv/app/samples/z2ui5_cl_demo_app_266.js | 101 + .../srv/app/samples/z2ui5_cl_demo_app_267.js | 53 + .../srv/app/samples/z2ui5_cl_demo_app_270.js | 15 + .../srv/app/samples/z2ui5_cl_demo_app_271.js | 52 + .../srv/app/samples/z2ui5_cl_demo_app_272.js | 49 + .../srv/app/samples/z2ui5_cl_demo_app_273.js | 156 + .../srv/app/samples/z2ui5_cl_demo_app_274.js | 67 + .../srv/app/samples/z2ui5_cl_demo_app_275.js | 49 + .../srv/app/samples/z2ui5_cl_demo_app_276.js | 56 + .../srv/app/samples/z2ui5_cl_demo_app_278.js | 65 + .../srv/app/samples/z2ui5_cl_demo_app_279.js | 76 + .../srv/app/samples/z2ui5_cl_demo_app_280.js | 92 + .../srv/app/samples/z2ui5_cl_demo_app_281.js | 107 + .../srv/app/samples/z2ui5_cl_demo_app_282.js | 114 + .../srv/app/samples/z2ui5_cl_demo_app_283.js | 61 + .../srv/app/samples/z2ui5_cl_demo_app_287.js | 46 + .../srv/app/samples/z2ui5_cl_demo_app_288.js | 91 + .../srv/app/samples/z2ui5_cl_demo_app_289.js | 66 + .../srv/app/samples/z2ui5_cl_demo_app_290.js | 103 + .../srv/app/samples/z2ui5_cl_demo_app_291.js | 55 + .../srv/app/samples/z2ui5_cl_demo_app_292.js | 67 + .../srv/app/samples/z2ui5_cl_demo_app_293.js | 59 + .../srv/app/samples/z2ui5_cl_demo_app_294.js | 61 + .../srv/app/samples/z2ui5_cl_demo_app_295.js | 54 + .../srv/app/samples/z2ui5_cl_demo_app_296.js | 57 + .../srv/app/samples/z2ui5_cl_demo_app_297.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_298.js | 88 + .../srv/app/samples/z2ui5_cl_demo_app_299.js | 59 + .../srv/app/samples/z2ui5_cl_demo_app_300.js | 191 + .../srv/app/samples/z2ui5_cl_demo_app_302.js | 66 + .../srv/app/samples/z2ui5_cl_demo_app_303.js | 243 + .../srv/app/samples/z2ui5_cl_demo_app_306.js | 118 + .../srv/app/samples/z2ui5_cl_demo_app_307.js | 83 + .../srv/app/samples/z2ui5_cl_demo_app_316.js | 51 + .../srv/app/samples/z2ui5_cl_demo_app_325.js | 56 + .../srv/app/samples/z2ui5_cl_demo_app_330.js | 220 + .../srv/app/samples/z2ui5_cl_demo_app_352.js | 39 + .../srv/app/samples/z2ui5_cl_demo_app_362.js | 85 + .../srv/app/samples/z2ui5_cl_demo_app_363.js | 83 + .../srv/app/samples/z2ui5_cl_demo_app_364.js | 63 + .../srv/app/samples/z2ui5_cl_demo_app_366.js | 66 + .../srv/app/samples/z2ui5_cl_demo_app_367.js | 48 + .../srv/app/samples/z2ui5_cl_demo_app_368.js | 99 + .../srv/app/samples/z2ui5_cl_demo_app_369.js | 62 + .../srv/app/samples/z2ui5_cl_demo_app_370.js | 58 + .../srv/app/samples/z2ui5_cl_demo_app_371.js | 48 + .../srv/app/samples/z2ui5_cl_demo_app_372.js | 62 + .../srv/app/samples/z2ui5_cl_demo_app_373.js | 63 + .../srv/app/samples/z2ui5_cl_demo_app_374.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_375.js | 51 + .../srv/app/samples/z2ui5_cl_demo_app_376.js | 60 + .../srv/app/samples/z2ui5_cl_demo_app_377.js | 55 + .../srv/app/samples/z2ui5_cl_demo_app_378.js | 63 + .../srv/app/samples/z2ui5_cl_demo_app_379.js | 55 + .../srv/app/samples/z2ui5_cl_demo_app_380.js | 48 + .../app/samples/z2ui5_cl_sample_app_001.js | 120 + .../app/samples/z2ui5_cl_sample_context.js | 1484 +++ .../srv/app/samples/z2ui5_cx_sample_error.js | 40 + run/input/core/srv/z2ui5/00/00/abap_rtti.js | 165 + .../srv/z2ui5/00/00/cl_abap_char_utilities.js | 17 + .../srv/z2ui5/00/00/cl_abap_classdescr.js | 7 + .../core/srv/z2ui5/00/00/cl_abap_datadescr.js | 10 + .../core/srv/z2ui5/00/00/cl_abap_elemdescr.js | 22 + .../core/srv/z2ui5/00/00/cl_abap_format.js | 16 + .../srv/z2ui5/00/00/cl_abap_objectdescr.js | 12 + .../core/srv/z2ui5/00/00/cl_abap_refdescr.js | 14 + .../srv/z2ui5/00/00/cl_abap_structdescr.js | 14 + .../srv/z2ui5/00/00/cl_abap_tabledescr.js | 18 + .../core/srv/z2ui5/00/00/cl_abap_tstmp.js | 25 + .../core/srv/z2ui5/00/00/cl_abap_typedescr.js | 25 + .../srv/z2ui5/00/00/cl_abap_unit_assert.js | 43 + .../00/00/cx_sy_dyn_call_illegal_class.js | 13 + .../core/srv/z2ui5/00/01/z2ui5_cl_ajson.js | 593 ++ .../z2ui5/00/01/z2ui5_cl_ajson_filter_lib.js | 22 + .../srv/z2ui5/00/01/z2ui5_cl_ajson_mapping.js | 60 + .../z2ui5/00/01/z2ui5_cl_ajson_refinitlib.js | 10 + .../z2ui5/00/01/z2ui5_cl_ajson_utilities.js | 231 + .../srv/z2ui5/00/01/z2ui5_cx_ajson_error.js | 67 + .../core/srv/z2ui5/00/01/z2ui5_if_ajson.js | 8 + .../srv/z2ui5/00/01/z2ui5_if_ajson_filter.js | 6 + .../z2ui5/00/01/z2ui5_if_ajson_iterator.js | 5 + .../srv/z2ui5/00/01/z2ui5_if_ajson_mapping.js | 5 + .../srv/z2ui5/00/01/z2ui5_if_ajson_refinit.js | 5 + .../srv/z2ui5/00/01/z2ui5_if_ajson_types.js | 6 + .../srv/z2ui5/00/02/z2ui5_cl_srt_aunit.js | 31 + .../z2ui5/00/02/z2ui5_cl_srt_classdescr.js | 14 + .../z2ui5/00/02/z2ui5_cl_srt_complexdescr.js | 6 + .../srv/z2ui5/00/02/z2ui5_cl_srt_datadescr.js | 6 + .../srv/z2ui5/00/02/z2ui5_cl_srt_elemdescr.js | 81 + .../srv/z2ui5/00/02/z2ui5_cl_srt_intfdescr.js | 12 + .../z2ui5/00/02/z2ui5_cl_srt_objectdescr.js | 24 + .../srv/z2ui5/00/02/z2ui5_cl_srt_refdescr.js | 28 + .../z2ui5/00/02/z2ui5_cl_srt_structdescr.js | 61 + .../z2ui5/00/02/z2ui5_cl_srt_tabledescr.js | 50 + .../srv/z2ui5/00/02/z2ui5_cl_srt_typedescr.js | 81 + .../core/srv/z2ui5/00/02/z2ui5_cx_srt.js | 15 + .../srv/z2ui5/00/03/01/z2ui5_cl_util_db.js | 76 + .../srv/z2ui5/00/03/01/z2ui5_cl_util_ext.js | 713 ++ .../srv/z2ui5/00/03/02/z2ui5_cl_util_api.js | 114 + .../srv/z2ui5/00/03/02/z2ui5_cl_util_api_c.js | 9 + .../srv/z2ui5/00/03/02/z2ui5_cl_util_api_s.js | 8 + .../srv/z2ui5/00/03/z2ui5_cl_a2ui5_context.js | 1580 +++ .../srv/z2ui5/00/03/z2ui5_cl_a2ui5_http.js | 227 + .../z2ui5/00/03/z2ui5_cl_a2ui5_json_fltr.js | 34 + .../core/srv/z2ui5/00/03/z2ui5_cl_util.js | 717 ++ .../srv/z2ui5/00/03/z2ui5_cl_util_http.js | 173 + .../z2ui5/00/03/z2ui5_cl_util_json_fltr.js | 34 + .../core/srv/z2ui5/00/03/z2ui5_cl_util_log.js | 84 + .../core/srv/z2ui5/00/03/z2ui5_cl_util_msg.js | 118 + .../srv/z2ui5/00/03/z2ui5_cl_util_range.js | 118 + .../core/srv/z2ui5/00/03/z2ui5_cl_util_xml.js | 173 + .../srv/z2ui5/00/03/z2ui5_cx_a2ui5_error.js | 40 + .../srv/z2ui5/00/03/z2ui5_cx_util_error.js | 80 + .../z2ui5/01/01/z2ui5_cl_core_srv_draft.js | 171 + .../srv/z2ui5/01/02/z2ui5_cl_core_action.js | 266 + .../core/srv/z2ui5/01/02/z2ui5_cl_core_app.js | 195 + .../srv/z2ui5/01/02/z2ui5_cl_core_client.js | 718 ++ .../srv/z2ui5/01/02/z2ui5_cl_core_handler.js | 409 + .../srv/z2ui5/01/02/z2ui5_cl_core_srv_bind.js | 447 + .../z2ui5/01/02/z2ui5_cl_core_srv_event.js | 117 + .../z2ui5/01/02/z2ui5_cl_core_srv_model.js | 567 ++ .../srv/z2ui5/01/02/z2ui5_if_core_types.js | 110 + .../srv/z2ui5/01/03/z2ui5_cl_app_app_js.js | 23 + .../srv/z2ui5/01/03/z2ui5_cl_app_app_xml.js | 23 + .../z2ui5/01/03/z2ui5_cl_app_appstate_js.js | 10 + .../01/03/z2ui5_cl_app_camerapicture_js.js | 10 + .../01/03/z2ui5_cl_app_cameraselector_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_component_js.js | 23 + .../z2ui5/01/03/z2ui5_cl_app_debugtool_js.js | 23 + .../z2ui5/01/03/z2ui5_cl_app_debugtool_xml.js | 23 + .../srv/z2ui5/01/03/z2ui5_cl_app_dirty_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_errorview_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_favicon_js.js | 10 + .../01/03/z2ui5_cl_app_fileuploader_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_focus_js.js | 10 + .../01/03/z2ui5_cl_app_frontendaction_js.js | 12 + .../01/03/z2ui5_cl_app_geolocation_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_history_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_index_html.js | 84 + .../srv/z2ui5/01/03/z2ui5_cl_app_info_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_lib_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_lptitle_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_manifest_json.js | 23 + .../z2ui5/01/03/z2ui5_cl_app_messages_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_models_js.js | 23 + .../01/03/z2ui5_cl_app_multiinputext_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_scrolling_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_server_js.js | 23 + .../01/03/z2ui5_cl_app_smartmultiinpu_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_storage_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_style_css.js | 23 + .../srv/z2ui5/01/03/z2ui5_cl_app_timer_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_title_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_tree_js.js | 10 + .../z2ui5/01/03/z2ui5_cl_app_uitableext_js.js | 10 + .../01/03/z2ui5_cl_app_uploadsetext_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_util_js.js | 10 + .../srv/z2ui5/01/03/z2ui5_cl_app_view1_js.js | 23 + .../srv/z2ui5/01/03/z2ui5_cl_app_view1_xml.js | 23 + .../z2ui5/01/03/z2ui5_cl_app_viewslots_js.js | 10 + .../srv/z2ui5/02/z2ui5_cl_app_hello_world.js | 25 + .../core/srv/z2ui5/02/z2ui5_cl_app_startup.js | 376 + run/input/core/srv/z2ui5/02/z2ui5_cl_exit.js | 142 + .../srv/z2ui5/02/z2ui5_cl_http_handler.js | 50 + .../core/srv/z2ui5/02/z2ui5_cl_xml_view.js | 8550 +++++++++++++++++ .../core/srv/z2ui5/02/z2ui5_cl_xml_view_cc.js | 286 + .../core/srv/z2ui5/02/z2ui5_if_action.js | 5 + run/input/core/srv/z2ui5/02/z2ui5_if_app.js | 29 + .../core/srv/z2ui5/02/z2ui5_if_client.js | 121 + run/input/core/srv/z2ui5/02/z2ui5_if_exit.js | 42 + run/input/core/srv/z2ui5/02/z2ui5_if_types.js | 83 + .../core/srv/z2ui5/99/01/z2ui5_cl_util_db.js | 81 + .../core/srv/z2ui5/99/01/z2ui5_cl_util_ext.js | 3316 +++++++ .../srv/z2ui5/99/01/z2ui5_cl_util_http.js | 229 + .../core/srv/z2ui5/99/01/z2ui5_cl_util_log.js | 105 + .../core/srv/z2ui5/99/01/z2ui5_cl_util_msg.js | 534 + .../srv/z2ui5/99/01/z2ui5_cl_util_range.js | 157 + .../core/srv/z2ui5/99/01/z2ui5_cl_util_xml.js | 175 + .../srv/z2ui5/99/01/z2ui5_cx_util_error.js | 39 + .../core/srv/z2ui5/99/02/z2ui5_cl_pop_data.js | 59 + .../z2ui5/99/02/z2ui5_cl_pop_demo_output.js | 99 + .../srv/z2ui5/99/02/z2ui5_cl_pop_error.js | 49 + .../srv/z2ui5/99/02/z2ui5_cl_pop_file_dl.js | 97 + .../srv/z2ui5/99/02/z2ui5_cl_pop_file_ul.js | 77 + .../srv/z2ui5/99/02/z2ui5_cl_pop_get_range.js | 180 + .../z2ui5/99/02/z2ui5_cl_pop_get_range_m.js | 114 + .../core/srv/z2ui5/99/02/z2ui5_cl_pop_html.js | 54 + .../z2ui5/99/02/z2ui5_cl_pop_image_editor.js | 82 + .../srv/z2ui5/99/02/z2ui5_cl_pop_input_val.js | 68 + .../srv/z2ui5/99/02/z2ui5_cl_pop_js_loader.js | 74 + .../srv/z2ui5/99/02/z2ui5_cl_pop_messages.js | 51 + .../core/srv/z2ui5/99/02/z2ui5_cl_pop_pdf.js | 70 + .../srv/z2ui5/99/02/z2ui5_cl_pop_table.js | 130 + .../srv/z2ui5/99/02/z2ui5_cl_pop_textedit.js | 65 + .../z2ui5/99/02/z2ui5_cl_pop_to_confirm.js | 77 + .../srv/z2ui5/99/02/z2ui5_cl_pop_to_inform.js | 53 + .../srv/z2ui5/99/02/z2ui5_cl_pop_to_select.js | 220 + .../z2ui5/99/02/z2ui5_pop_preferred_param.js | 46 + run/input/core/srv/z2ui5/engine.js | 124 + run/input/core/srv/z2ui5/register-apps.js | 20 + run/input/core/srv/z2ui5/z2ui5_asset.js | 41 + run/input/core/srv/z2ui5/z2ui5_port.js | 138 + scripts/assemble-cap.js | 126 + scripts/mirror-core.js | 58 + scripts/publish-cap.js | 66 + src/.gitignore | 26 + src/.nvmrc | 1 + src/LICENSE | 21 + src/README.md | 319 + src/_media/image-1.png | Bin 0 -> 148763 bytes src/_media/image.png | Bin 0 -> 402473 bytes src/app/index.html | 160 + src/db/schema.cds | 12 + src/mta.yaml | 125 + src/package-lock.json | 7603 +++++++++++++++ src/package.json | 57 + src/srv/app/README.md | 58 + src/srv/app/z2ui5_cl_app_read_odata.js | 32 + src/srv/external/northwind.csn | 1172 +++ src/srv/external/northwind.xml | 1 + src/srv/server.js | 76 + src/srv/z2ui5-service.cds | 28 + src/srv/z2ui5-service.js | 18 + src/test/starter.test.js | 59 + src/test/z2ui5_cl_xml_view.test.js | 84 + src/xs-security.json | 6 + 401 files changed, 61302 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/update_cap.yml create mode 100644 .gitignore create mode 100644 UPSTREAM_HEAD create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 run/input/UPSTREAM_COMMIT create mode 100644 run/input/core/README.md create mode 100644 run/input/core/app/z2ui5/webapp/Component.js create mode 100644 run/input/core/app/z2ui5/webapp/Util.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/CameraPicture.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/CameraSelector.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Dirty.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Favicon.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/FileUploader.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Focus.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Geolocation.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/History.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Info.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/LPTitle.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/MultiInputExt.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Scrolling.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/SmartMultiInputExt.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Storage.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Timer.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Title.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/Tree.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/UITableExt.js create mode 100644 run/input/core/app/z2ui5/webapp/cc/UploadSetExt.js create mode 100644 run/input/core/app/z2ui5/webapp/controller/App.controller.js create mode 100644 run/input/core/app/z2ui5/webapp/controller/View1.controller.js create mode 100644 run/input/core/app/z2ui5/webapp/core/AppState.js create mode 100644 run/input/core/app/z2ui5/webapp/core/DebugTool.fragment.xml create mode 100644 run/input/core/app/z2ui5/webapp/core/DebugTool.js create mode 100644 run/input/core/app/z2ui5/webapp/core/ErrorView.js create mode 100644 run/input/core/app/z2ui5/webapp/core/FrontendAction.js create mode 100644 run/input/core/app/z2ui5/webapp/core/Lib.js create mode 100644 run/input/core/app/z2ui5/webapp/core/Messages.js create mode 100644 run/input/core/app/z2ui5/webapp/core/Server.js create mode 100644 run/input/core/app/z2ui5/webapp/core/ViewSlots.js create mode 100644 run/input/core/app/z2ui5/webapp/css/style.css create mode 100644 run/input/core/app/z2ui5/webapp/index.html create mode 100644 run/input/core/app/z2ui5/webapp/manifest.json create mode 100644 run/input/core/app/z2ui5/webapp/model/models.js create mode 100644 run/input/core/app/z2ui5/webapp/view/App.view.xml create mode 100644 run/input/core/package-lock.json create mode 100644 run/input/core/package.json create mode 100644 run/input/core/srv/app/samples/README.md create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_001.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_003.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_004.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_005.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_006.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_008.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_009.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_011.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_012.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_015.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_017.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_019.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_020.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_021.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_022.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_024.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_025.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_026.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_027.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_028.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_030.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_035.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_038.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_041.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_047.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_048.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_051.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_052.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_053.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_056.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_059.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_061.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_062.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_064.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_065.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_067.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_068.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_069.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_070.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_071.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_073.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_074.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_075.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_078.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_080.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_081.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_088.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_097.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_098.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_101.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_103.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_104.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_106.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_109.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_110.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_122.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_125.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_126.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_133.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_136.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_144.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_160.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_161.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_163.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_166.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_167.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_173.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_175.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_176.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_181.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_187.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_189.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_197.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_202.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_205.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_206.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_207.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_208.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_209.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_210.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_213.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_214.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_215.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_216.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_217.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_218.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_219.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_220.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_221.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_222.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_223.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_224.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_225.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_226.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_227.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_228.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_229.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_230.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_231.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_232.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_233.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_234.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_235.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_236.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_237.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_238.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_239.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_240.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_241.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_242.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_245.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_246.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_247.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_248.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_249.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_250.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_251.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_252.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_257.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_259.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_260.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_261.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_262.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_263.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_264.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_265.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_266.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_267.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_270.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_271.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_272.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_273.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_274.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_275.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_276.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_278.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_279.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_280.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_281.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_282.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_283.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_287.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_288.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_289.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_290.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_291.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_292.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_293.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_294.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_295.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_296.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_297.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_298.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_299.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_300.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_302.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_303.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_306.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_307.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_316.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_325.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_330.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_352.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_362.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_363.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_364.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_366.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_367.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_368.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_369.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_370.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_371.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_372.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_373.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_374.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_375.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_376.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_377.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_378.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_379.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_demo_app_380.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_sample_app_001.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cl_sample_context.js create mode 100644 run/input/core/srv/app/samples/z2ui5_cx_sample_error.js create mode 100644 run/input/core/srv/z2ui5/00/00/abap_rtti.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_char_utilities.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_classdescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_datadescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_elemdescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_format.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_objectdescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_refdescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_structdescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_tabledescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_tstmp.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_typedescr.js create mode 100644 run/input/core/srv/z2ui5/00/00/cl_abap_unit_assert.js create mode 100644 run/input/core/srv/z2ui5/00/00/cx_sy_dyn_call_illegal_class.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_cl_ajson.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_cl_ajson_filter_lib.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_cl_ajson_mapping.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_cl_ajson_refinitlib.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_cl_ajson_utilities.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_cx_ajson_error.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_if_ajson.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_if_ajson_filter.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_if_ajson_iterator.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_if_ajson_mapping.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_if_ajson_refinit.js create mode 100644 run/input/core/srv/z2ui5/00/01/z2ui5_if_ajson_types.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_aunit.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_classdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_complexdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_datadescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_elemdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_intfdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_objectdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_refdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_structdescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_tabledescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cl_srt_typedescr.js create mode 100644 run/input/core/srv/z2ui5/00/02/z2ui5_cx_srt.js create mode 100644 run/input/core/srv/z2ui5/00/03/01/z2ui5_cl_util_db.js create mode 100644 run/input/core/srv/z2ui5/00/03/01/z2ui5_cl_util_ext.js create mode 100644 run/input/core/srv/z2ui5/00/03/02/z2ui5_cl_util_api.js create mode 100644 run/input/core/srv/z2ui5/00/03/02/z2ui5_cl_util_api_c.js create mode 100644 run/input/core/srv/z2ui5/00/03/02/z2ui5_cl_util_api_s.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_a2ui5_context.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_a2ui5_http.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_a2ui5_json_fltr.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util_http.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util_json_fltr.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util_log.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util_msg.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util_range.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cl_util_xml.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cx_a2ui5_error.js create mode 100644 run/input/core/srv/z2ui5/00/03/z2ui5_cx_util_error.js create mode 100644 run/input/core/srv/z2ui5/01/01/z2ui5_cl_core_srv_draft.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_action.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_app.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_client.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_handler.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_srv_bind.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_srv_event.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_cl_core_srv_model.js create mode 100644 run/input/core/srv/z2ui5/01/02/z2ui5_if_core_types.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_app_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_app_xml.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_appstate_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_camerapicture_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_cameraselector_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_component_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_debugtool_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_debugtool_xml.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_dirty_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_errorview_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_favicon_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_fileuploader_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_focus_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_frontendaction_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_geolocation_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_history_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_index_html.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_info_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_lib_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_lptitle_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_manifest_json.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_messages_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_models_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_multiinputext_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_scrolling_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_server_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_smartmultiinpu_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_storage_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_style_css.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_timer_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_title_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_tree_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_uitableext_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_uploadsetext_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_util_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_view1_js.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_view1_xml.js create mode 100644 run/input/core/srv/z2ui5/01/03/z2ui5_cl_app_viewslots_js.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_cl_app_hello_world.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_cl_app_startup.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_cl_exit.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_cl_http_handler.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_cl_xml_view.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_cl_xml_view_cc.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_if_action.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_if_app.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_if_client.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_if_exit.js create mode 100644 run/input/core/srv/z2ui5/02/z2ui5_if_types.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_db.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_ext.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_http.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_log.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_msg.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_range.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cl_util_xml.js create mode 100644 run/input/core/srv/z2ui5/99/01/z2ui5_cx_util_error.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_data.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_demo_output.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_error.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_file_dl.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_file_ul.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_get_range.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_get_range_m.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_html.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_image_editor.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_input_val.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_js_loader.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_messages.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_pdf.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_table.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_textedit.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_to_confirm.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_to_inform.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_cl_pop_to_select.js create mode 100644 run/input/core/srv/z2ui5/99/02/z2ui5_pop_preferred_param.js create mode 100644 run/input/core/srv/z2ui5/engine.js create mode 100644 run/input/core/srv/z2ui5/register-apps.js create mode 100644 run/input/core/srv/z2ui5/z2ui5_asset.js create mode 100644 run/input/core/srv/z2ui5/z2ui5_port.js create mode 100644 scripts/assemble-cap.js create mode 100644 scripts/mirror-core.js create mode 100644 scripts/publish-cap.js create mode 100644 src/.gitignore create mode 100644 src/.nvmrc create mode 100644 src/LICENSE create mode 100644 src/README.md create mode 100644 src/_media/image-1.png create mode 100644 src/_media/image.png create mode 100644 src/app/index.html create mode 100644 src/db/schema.cds create mode 100644 src/mta.yaml create mode 100644 src/package-lock.json create mode 100644 src/package.json create mode 100644 src/srv/app/README.md create mode 100644 src/srv/app/z2ui5_cl_app_read_odata.js create mode 100644 src/srv/external/northwind.csn create mode 100644 src/srv/external/northwind.xml create mode 100644 src/srv/server.js create mode 100644 src/srv/z2ui5-service.cds create mode 100644 src/srv/z2ui5-service.js create mode 100644 src/test/starter.test.js create mode 100644 src/test/z2ui5_cl_xml_view.test.js create mode 100644 src/xs-security.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..594f92c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,31 @@ +name: test + +# Runs the app build + the CAP app's jest suite on every pull request (and +# on pushes to main): assemble the app from src/ + the committed core mirror +# (run/input/core), install and run its tests. Make this check "Required" in +# the branch protection rules of `main` so a PR can only be merged once the +# tests pass. + +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version: 22 + - run: npm run assemble + # one install covers the app AND the vendored core (its deps are part + # of the app lock, placed under core/node_modules/) + - run: npm ci + working-directory: run/output/cap2UI5 + - run: npm test diff --git a/.github/workflows/update_cap.yml b/.github/workflows/update_cap.yml new file mode 100644 index 0000000..d21ab8f --- /dev/null +++ b/.github/workflows/update_cap.yml @@ -0,0 +1,98 @@ +name: update cap + +# The one pipeline of this repo: mirror the published core package from +# builder-abap2UI5-js, assemble the full CAP app (src/ + vendored core + +# webapp overlay), gate it with the app's jest suite, commit the refreshed +# mirror here and publish the built app 1:1 to the deployable repo +# cap2UI5/cap2UI5. +# +# Runs event-driven on every push to main. That includes the trigger +# commits builder-abap2UI5-js pushes here via deploy key (its trigger_cap +# workflow updates UPSTREAM_HEAD after a core rebuild), so the app follows +# every core update — plus changes to the build tooling itself. The nightly +# cron remains as a safety net. +# +# Cross-repo push uses an SSH deploy key: the public half is registered on +# cap2UI5/cap2UI5 with write access, the private half is the secret +# ACTION_KEY_APP here. Without the secret the workflow still builds and +# tests, it just skips the publish. + +on: + push: + branches: [main] + schedule: + - cron: "0 6 * * *" # 06:00 UTC nightly — after the builder-abap2UI5-js pipelines (03:00–05:00) + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: update-cap + cancel-in-progress: false + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + ref: main + - uses: actions/setup-node@v5 + with: + node-version: 22 + - run: npm run mirror_core + - name: commit refreshed mirror + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add run/input + if git diff --cached --quiet; then + echo "mirror unchanged" + else + git commit -m "mirror: update run/input/core ($(cut -c1-12 run/input/UPSTREAM_COMMIT))" + git pull --rebase origin main + git push origin HEAD:main + fi + - run: npm run assemble + # one install covers the app AND the vendored core (its deps are part + # of the app lock, placed under core/node_modules/) + - run: npm ci + working-directory: run/output/cap2UI5 + - run: npm test + - name: publish built app to cap2UI5/cap2UI5 + env: + ACTION_KEY_APP: ${{ secrets.ACTION_KEY_APP }} + run: | + set -euo pipefail + if [ -z "$ACTION_KEY_APP" ]; then + echo "::warning::secret ACTION_KEY_APP not set — skipping publish to cap2UI5/cap2UI5" + exit 0 + fi + UPSTREAM=$(cat run/input/UPSTREAM_COMMIT) + APP="$RUNNER_TEMP/cap2UI5" + + mkdir -p ~/.ssh + echo "$ACTION_KEY_APP" > ~/.ssh/app_key + chmod 600 ~/.ssh/app_key + ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null + export GIT_SSH_COMMAND="ssh -i ~/.ssh/app_key -o IdentitiesOnly=yes" + + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git clone --depth 1 --branch main git@github.com:cap2UI5/cap2UI5.git "$APP" + + PUBLISH_TARGET="$APP" npm run publish + + cd "$APP" + git add -A + if git diff --cached --quiet; then + echo "app unchanged — no publish commit" >> "$GITHUB_STEP_SUMMARY" + else + git commit -m "build: publish app (core @ ${UPSTREAM:0:12})" \ + -m "builder: ${GITHUB_SHA}" \ + -m "run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" + git push origin HEAD:main + echo "published to cap2UI5/cap2UI5@main: $(git rev-parse --short HEAD)" >> "$GITHUB_STEP_SUMMARY" + fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb36405 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.mirror_tmp/ +.DS_Store +run/output/ diff --git a/README.md b/README.md index fba98ba..3bd4a01 100644 --- a/README.md +++ b/README.md @@ -1 +1,100 @@ -# builder-cap2UI5 \ No newline at end of file +# builder-cap2UI5 — the CAP app build project + +[![test](https://github.com/cap2UI5/builder-cap2UI5/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/cap2UI5/builder-cap2UI5/actions/workflows/test.yml) +[![update cap](https://github.com/cap2UI5/builder-cap2UI5/actions/workflows/update_cap.yml/badge.svg?branch=main)](https://github.com/cap2UI5/builder-cap2UI5/actions/workflows/update_cap.yml) + +This project **generates the deployable CAP app** +[cap2UI5](https://github.com/cap2UI5/cap2UI5) from the hand-maintained source +in [`src/`](src/) plus the published core package (the npm package +`abap2UI5`), mirrored from +[builder-abap2UI5-js](https://github.com/cap2UI5/builder-abap2UI5-js). + +> [!IMPORTANT] +> Everything in this project is generated automatically — by AI (Claude) and +> by a sync pipeline that consumes the upstream +> [abap2UI5](https://github.com/abap2UI5/abap2UI5) sources. Review and test +> before relying on it. + +> [!IMPORTANT] +> **The cap2UI5 app repo is a build artifact — do not hand-edit it.** Every +> publish wipes and rewrites it. The hand-written source lives in +> [`src/`](src/); edit there and re-run the build. (Your own apps go in +> `src/srv/app/` or an external `Z2UI5_APP_DIRS` folder — never in the app +> repo's `srv/app/`, which is regenerated.) + +cap2UI5 is organized as three repositories, from framework to finished app: + +| Repository | What it is | +|---|---| +| [`builder-abap2UI5-js`](https://github.com/cap2UI5/builder-abap2UI5-js) | abap2UI5 ported to JavaScript — generates the core package `abap2UI5` | +| [`builder-cap2UI5`](https://github.com/cap2UI5/builder-cap2UI5) (here) | generates the full CAP app from `src/` + the published core | +| [`cap2UI5`](https://github.com/cap2UI5/cap2UI5) | the finished, deployable CAP app (**generated**) | + +## Build + +```bash +npm run mirror_core # snapshot builder-abap2UI5-js:core/ → run/input/core + # (MIRROR_SOURCE=/path/to/builder-abap2UI5-js uses a local checkout) + +npm run build_cap # assemble + publish → regenerate ../cap2UI5 (a sibling + # checkout of cap2UI5/cap2UI5; override with PUBLISH_TARGET=…) +``` + +No dependencies — the scripts are plain Node. What the build does: + +| Step | What it does | +|---|---| +| `npm run mirror_core` | snapshot the published core package from builder-abap2UI5-js into `run/input/core` (the upstream commit is recorded in `run/input/UPSTREAM_COMMIT`) | +| `npm run assemble` | `src/` → `run/output/cap2UI5` (verbatim), vendor `run/input/core` → `core/`, then overlay the core's `app/z2ui5/webapp` → `app/z2ui5/webapp` (the copy served by CDS statics and zipped by the mta html5 module — taken from the published core, so the two cannot drift) | +| `npm run publish` | 1:1 copy `run/output/cap2UI5` → the app checkout (`../cap2UI5` or `PUBLISH_TARGET`) — the very last step | +| `npm run build_cap` | `assemble` then `publish` | +| `npm test` | runs the CAP app's own jest suite in `run/output/cap2UI5` (needs one `npm ci` there first — it covers the app **and** the vendored core) | + +The framework is consumed as the npm dependency `abap2UI5`: `src/` links the +mirrored package (`file:../run/input/core`), the published app the **vendored +copy** (`file:./core`) — the app repo is fully self-contained. The build's +only transformations: that dependency-path rewrite in `package.json` / +`package-lock.json`, plus merging the core's own lock entries into the app +lock (under `core/node_modules/`), since the vendored core sits inside the +app's package root and npm manages its deps as part of the app tree. + +## `src/` — the hand-written source + +`src/` is the **source of truth** for the CAP app: the skeleton (`server.js`, +`z2ui5-service.*`, `db/`, `package.json`, `mta.yaml`, `srv/external/`), the +platform wiring (draft store → CDS entity `cap2ui5.z2ui5_t_01`, app discovery +→ `srv/app/`), the bundled custom app `srv/app/z2ui5_cl_app_read_odata.js`, +and the docs. Published as the app repo minus the vendored core and the +generated webapp overlay. + +`src/` is itself a fully functional minimal CAP project — the starting point +of cap2UI5 with the same basic setup as abap2UI5: a mini frontend +(`app/index.html`), the http service (`POST /rest/root/z2ui5`) and the draft +persistence. Run and test it standalone (it links the core via +`file:../run/input/core`, so run `npm run mirror_core` first): + +```bash +cd src +npm install +npx cds watch # → http://localhost:4004/index.html +npm test # jest: boots the server via cds.test(), asserts all three layers +``` + +See the [minimal base section](src/README.md#the-minimal-base) in the source +README for details. + +## Pipeline + +The **update cap** workflow (`.github/workflows/update_cap.yml`) runs on +every push to `main` — including the trigger commits builder-abap2UI5-js +pushes here via deploy key (its `trigger_cap` workflow updates +`UPSTREAM_HEAD` after a core rebuild) — plus a nightly cron as safety net. +It mirrors the core, assembles the app, gates it with the app's jest suite, +commits the refreshed `run/input/core` here and publishes the built app 1:1 +to [cap2UI5](https://github.com/cap2UI5/cap2UI5) (deploy key, secret +`ACTION_KEY_APP`). The **test** workflow runs the same assemble + jest gate +on every pull request. + +## License + +MIT. diff --git a/UPSTREAM_HEAD b/UPSTREAM_HEAD new file mode 100644 index 0000000..3ff4be6 --- /dev/null +++ b/UPSTREAM_HEAD @@ -0,0 +1 @@ +8d084d2437340b9588b48ccf1f4c728cb65b6617 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9eac884 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,16 @@ +{ + "name": "builder-cap2ui5", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "builder-cap2ui5", + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=20" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0e53ee6 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "builder-cap2ui5", + "version": "1.0.0", + "private": true, + "description": "Builder project for the full CAP app \u2014 mirrors the published core package (abap2UI5) from builder-abap2UI5-js, assembles src/ + the vendored core + its webapp and publishes the result 1:1 into the cap2UI5 app repository", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "scripts": { + "mirror_core": "node scripts/mirror-core.js", + "assemble": "node scripts/assemble-cap.js", + "publish": "node scripts/publish-cap.js", + "build_cap": "node scripts/assemble-cap.js && node scripts/publish-cap.js", + "test": "npm --prefix run/output/cap2UI5 test" + }, + "repository": "github:cap2UI5/builder-cap2UI5" +} diff --git a/run/input/UPSTREAM_COMMIT b/run/input/UPSTREAM_COMMIT new file mode 100644 index 0000000..3ff4be6 --- /dev/null +++ b/run/input/UPSTREAM_COMMIT @@ -0,0 +1 @@ +8d084d2437340b9588b48ccf1f4c728cb65b6617 diff --git a/run/input/core/README.md b/run/input/core/README.md new file mode 100644 index 0000000..52aceb8 --- /dev/null +++ b/run/input/core/README.md @@ -0,0 +1,52 @@ +# abap2UI5 core — the platform-neutral framework package + +This is the npm package `abap2UI5`: the engine, the transpiled framework +classes, the z2ui5 webapp and the bundled samples — **no CAP, no express, no +platform code**. Every platform consumes this one package: + +| Consumer | How | +|---|---| +| [`cap2UI5`](https://github.com/cap2UI5/cap2UI5) | the full CAP app — `"abap2UI5": "file:./core"` (vendored copy of this package) | +| [`adapters/cap/`](../adapters/cap/) | minimal CAP wrapper | +| [`adapters/node/`](../adapters/node/) | bare `node:http` server | +| [`adapters/express/`](../adapters/express/) | express middleware | +| [`adapters/web/`](../adapters/web/) | serverless browser bundle | + +> [!IMPORTANT] +> **This folder is a generated build artifact** — assembled from the +> hand-written source in [`src/`](../src/) plus the transpiled +> upstream [abap2UI5](https://github.com/abap2UI5/abap2UI5) sources. Do not +> hand-edit it; edit `src/` and re-run `npm run build_core` at the +> [repo root](../). + +## The seam + +The platform surface is tiny — see [`srv/z2ui5/engine.js`](srv/z2ui5/engine.js): + +```js +const engine = require("abap2UI5/engine"); +engine.set_store({ load, save }); // draft persistence port +engine.register_app_dir("/my/apps"); // or register_app_class(Cls) +http POST → await engine.roundtrip(body, reqInfo) // → JSON string +http GET → engine.bootstrap_html(reqInfo) // → { html, headers } +statics → engine.WEBAPP_DIR (+ engine.ui5_resources_dir()) +``` + +Everything below the engine is platform-agnostic: without an injected draft +store a volatile in-memory fallback is used (fine for tests, wrong for +production — inject your own). + +## Layout + +| Path | What it is | +|---|---| +| `srv/z2ui5/` | the framework: `engine.js`, the ports (`z2ui5_port.js`, `z2ui5_asset.js`), the class trees `00/`–`99/` | +| `srv/app/samples/` | the bundled sample apps (transpiled from upstream) | +| `app/z2ui5/webapp/` | the z2ui5 frontend (mirrored + patched from upstream) | + +The internal layout intentionally mirrors the historical CAP project paths so +the exports map, asset port and serialized draft references stay stable. + +## License + +MIT. diff --git a/run/input/core/app/z2ui5/webapp/Component.js b/run/input/core/app/z2ui5/webapp/Component.js new file mode 100644 index 0000000..b110470 --- /dev/null +++ b/run/input/core/app/z2ui5/webapp/Component.js @@ -0,0 +1,249 @@ +sap.ui.define( + [ + "sap/ui/core/UIComponent", + "z2ui5/model/models", + "z2ui5/core/Server", + "sap/ui/VersionInfo", + "z2ui5/core/DebugTool", + "z2ui5/core/Lib", + "z2ui5/core/AppState", + "z2ui5/Util", + "sap/ui/core/routing/HashChanger", + ], + ( + UIComponent, + Models, + Server, + VersionInfo, + DebugTool, + Lib, + AppState, + DateUtil, + HashChanger, + ) => { + "use strict"; + + return UIComponent.extend("z2ui5.Component", { + metadata: { + manifest: "json", + interfaces: ["sap.ui.core.IAsyncContentCreation"], + }, + + init() { + // The global "z2ui5" object holds the shared state for the whole + // app; core/AppState owns it. initGlobal() creates the global if + // needed, resets the internal state to clean defaults and provides + // a fresh oConfig - so the base init() and all helpers can rely on + // a fully initialized global from here on. + AppState.initGlobal(); + + UIComponent.prototype.init.call(this); + + AppState.getGlobal("oConfig").ComponentData = this.getComponentData(); + + // The date helpers are a public contract: apps use them via the + // z2ui5.Util global (XML view formatter strings) or via + // core:require of the z2ui5/Util module. Publish the global here - + // since the custom controls were split out of App.controller.js, + // nothing else loads the module eagerly anymore. + AppState.setGlobal("Util", DateUtil); + + AppState.state.oDeviceModel = Models.createDeviceModel(); + this.setModel(AppState.state.oDeviceModel, "device"); + + this._initLaunchpad(); + this._initVersionInfo(); + + this._installUnloadListener(); + this._installDebugToolShortcut(); + this._installScrollListener(); + + // The stopped router removed with the manifest routing section used + // to initialize the HashChanger (and its underlying hasher + // singleton) as a side effect. Without that init hasher never + // learns the URL's current hash, so the app-state cleanup after + // every roundtrip (View1._updateBrowserHistory calling + // replaceHash("")) is treated as a change and rewrites the URL to + // "...#" - every app start ended with a dangling "#". Initialize it + // explicitly; inside the FLP the shell has already done this and + // init() is a guarded no-op. + HashChanger.getInstance().init(); + }, + + // ------------------------------------------------------------------ + // Event listeners installed in init() and removed in exit() + // ------------------------------------------------------------------ + + _installUnloadListener() { + this._boundUnload = this._onUnload.bind(this); + // Safari on iOS does not fire "beforeunload" reliably, so we use + // "pagehide" there. iPads on iPadOS 13+ report a Mac user agent + // ("desktop site" default) - the touch-point probe catches those, + // while real Macs report 0 touch points. + const isIos = + /iPad|iPhone/.test(navigator.userAgent) || + (navigator.userAgent.includes("Mac") && navigator.maxTouchPoints > 1); + this._unloadEvent = isIos ? "pagehide" : "beforeunload"; + window.addEventListener(this._unloadEvent, this._boundUnload); + }, + + _installDebugToolShortcut() { + // Ctrl + F12 opens / closes the in-app debug tool. + this._boundKeydown = (event) => { + if (event.ctrlKey && event.key === "F12") { + const state = AppState.state; + if (!state.debugTool) state.debugTool = new DebugTool(); + state.debugTool.toggle(); + } + }; + document.addEventListener("keydown", this._boundKeydown); + }, + + _installScrollListener() { + // Scroll events do not bubble, but they do trigger capture-phase + // listeners on ancestors - a single document-level listener observes + // every scrollable container. Server.onScrollCapture records the + // last scrolled element per view slot for the S_SCROLL request info. + this._boundScroll = (event) => Server.onScrollCapture(event); + document.addEventListener("scroll", this._boundScroll, { + capture: true, + passive: true, + }); + }, + + // ------------------------------------------------------------------ + // SAP Fiori Launchpad integration (only when running inside FLP) + // ------------------------------------------------------------------ + + _initLaunchpad() { + const Container = sap.ui.require("sap/ushell/Container"); + if (!Container) return; // not running inside the launchpad -> nothing to do + + const launchpad = { Container }; + this._launchpad = launchpad; + AppState.state.oLaunchpad = launchpad; + + // The FLP services load asynchronously. By the time they resolve, the + // component may already have been destroyed (e.g. user navigated away + // before the services were ready). setIfAlive guards against writing + // to a stale launchpad object in that case. + const setIfAlive = (key, value) => { + if (Lib.isAlive(this) && this._launchpad === launchpad) { + launchpad[key] = value; + } + }; + + // ShellUIService is a UI5 service (factory + // sap.ushell.ui5service.ShellUIService, declared in manifest.json), + // not a Container service. Requesting it via Container.getServiceAsync + // resolves to sap/ushell/services/ShellUIService.js, which does not + // exist in the (ABAP) launchpad and fails with a 404. The component's + // getService() honors the manifest declaration and returns the + // correctly scoped instance. + this.getService("ShellUIService") + .then((s) => setIfAlive("ShellUIService", s)) + .catch((e) => + Lib.logError("Component: ShellUIService init failed", e), + ); + + Container.getServiceAsync("CrossApplicationNavigation") + .then((s) => setIfAlive("CrossAppNavigator", s)) + .catch((e) => + Lib.logError( + "Component: CrossApplicationNavigation init failed", + e, + ), + ); + + sap.ui.require( + ["sap/ushell/services/AppConfiguration"], + (ac) => setIfAlive("AppConfiguration", ac), + (e) => Lib.logError("Component: AppConfiguration init failed", e), + ); + }, + + async _initVersionInfo() { + try { + const info = await VersionInfo.load(); + if (Lib.isAlive(this)) { + AppState.getGlobal("oConfig").S_UI5 = { + VERSION: info.version, + BUILDTIMESTAMP: info.buildTimestamp, + GAV: info.gav, + THEME: this._getTheme(), + }; + } + } catch (e) { + Lib.logError("Component: VersionInfo load failed", e); + } + }, + + _getTheme() { + // sap/ui/core/Theming only exists since UI5 1.118, so it must not be + // a hard dependency of this module - older bootstraps (e.g. 1.108) + // would fail to load the component. On 1.118+ the core itself loads + // Theming, so the probing require finds it; otherwise fall back to + // the legacy Configuration API. + try { + const Theming = sap.ui.require("sap/ui/core/Theming"); + if (Theming?.getTheme) return Theming.getTheme(); + /* ui5lint-disable no-globals, no-deprecated-api -- + deliberate fallback for UI5 releases without sap/ui/core/Theming + (added in 1.118); the modern API is used in the branch above. */ + if (sap.ui.getCore) { + return sap.ui.getCore().getConfiguration().getTheme(); + } + /* ui5lint-enable no-globals, no-deprecated-api */ + } catch (e) { + Lib.logError("Component: reading theme failed", e); + } + return ""; + }, + + _onUnload() { + window.removeEventListener(this._unloadEvent, this._boundUnload); + this.destroy(); + }, + + // ------------------------------------------------------------------ + // Component teardown + // ------------------------------------------------------------------ + + exit() { + window.removeEventListener(this._unloadEvent, this._boundUnload); + document.removeEventListener("keydown", this._boundKeydown); + document.removeEventListener("scroll", this._boundScroll, { + capture: true, + }); + + // The debug tool is created lazily by the Ctrl+F12 shortcut - + // destroy it (which also closes its dialog) so a re-launch (FLP) + // does not leak the control instance. + if (AppState.state.debugTool) { + AppState.state.debugTool.destroy(); + AppState.state.debugTool = null; + } + + Server.endSession(); + + // Robust launchpad teardown: + // 1. Clear the FLP dirty flag so it does not carry over into the + // next app the user opens. + // 2. Detach the shared launchpad object so a subsequent re-launch + // starts from a clean state and any still-pending init Promises + // become no-ops via setIfAlive(). + try { + this._launchpad?.Container?.setDirtyFlag?.(false); + } catch (e) { + Lib.logError("Component: clearing FLP dirty flag failed", e); + } + if (AppState.state.oLaunchpad === this._launchpad) { + AppState.state.oLaunchpad = null; + } + this._launchpad = null; + + if (UIComponent.prototype.exit) UIComponent.prototype.exit.call(this); + }, + }); + }, +); diff --git a/run/input/core/app/z2ui5/webapp/Util.js b/run/input/core/app/z2ui5/webapp/Util.js new file mode 100644 index 0000000..fb9b864 --- /dev/null +++ b/run/input/core/app/z2ui5/webapp/Util.js @@ -0,0 +1,35 @@ +// PUBLIC date helpers for apps: exposed as the z2ui5.Util global and as +// the z2ui5/Util module (used in XML view formatter strings). Part of the +// public contract - do not rename or change the existing functions. +sap.ui.define([], () => { + "use strict"; + + // Splits an 8-character ABAP date string "YYYYMMDD" into the [year, month, + // day] tuple JavaScript's Date constructor expects. Note: Date months are + // 0-based, so we subtract 1 from the month component. + function parseYmd(d) { + return [ + Number(d.slice(0, 4)), + Number(d.slice(4, 6)) - 1, + Number(d.slice(6, 8)), + ]; + } + + return { + DateCreateObject(s) { + return new Date(s); + }, + DateAbapDateToDateObject(d) { + return new Date(...parseYmd(d)); + }, + // t is an ABAP time string "HHMMSS"; if omitted we default to midnight. + DateAbapDateTimeToDateObject(d, t = "000000") { + return new Date( + ...parseYmd(d), + Number(t.slice(0, 2)), + Number(t.slice(2, 4)), + Number(t.slice(4, 6)), + ); + }, + }; +}); diff --git a/run/input/core/app/z2ui5/webapp/cc/CameraPicture.js b/run/input/core/app/z2ui5/webapp/cc/CameraPicture.js new file mode 100644 index 0000000..5297f64 --- /dev/null +++ b/run/input/core/app/z2ui5/webapp/cc/CameraPicture.js @@ -0,0 +1,221 @@ +sap.ui.define( + [ + "sap/ui/core/Control", + "sap/m/Dialog", + "sap/m/Button", + "sap/ui/core/HTML", + "z2ui5/core/Lib", + ], + (Control, Dialog, Button, HTML, Lib) => { + "use strict"; + // Camera button: opens a dialog with the live camera stream, captures + // a photo on demand and hands it to the backend as a base64 JPEG in + // `value` (plus a small preview thumbnail) via the OnPhoto event. + const _CTX_2D_OPTS = { willReadFrequently: true }; + const _THUMB_W = 300; + // width/height size the trigger button; a bare number is treated as px. + const toCssSize = (val) => (/^\d+$/.test(val) ? `${val}px` : val); + return Control.extend("z2ui5.cc.CameraPicture", { + metadata: { + properties: { + id: { type: "string" }, + value: { type: "string" }, + thumbnail: { type: "string" }, + // Empty default leaves the trigger button auto-sized; a bare + // number is treated as px (see renderer / onAfterRendering). + width: { type: "string", defaultValue: "" }, + height: { type: "string", defaultValue: "" }, + autoplay: { type: "boolean", defaultValue: true }, + facingMode: { type: "string" }, + deviceId: { type: "string" }, + }, + events: { + OnPhoto: { + allowPreventDefault: true, + parameters: { + photo: { + type: "string", + }, + }, + }, + // Fired when the trigger button is pressed (the backend binds it + // via the `press` attribute, the same way as OnPhoto). + press: { + allowPreventDefault: true, + parameters: {}, + }, + }, + }, + + capture() { + const video = document.getElementById(`${this.getId()}-video`); + const canvas = document.getElementById(`${this.getId()}-canvas`); + if (!video || !canvas) return; + + const videoWidth = video.videoWidth; + const videoHeight = video.videoHeight; + canvas.width = videoWidth; + canvas.height = videoHeight; + + const ctx = canvas.getContext("2d", _CTX_2D_OPTS); + if (!ctx) return; + ctx.drawImage(video, 0, 0, videoWidth, videoHeight); + + // Full-resolution JPEG (quality 0.85) for the value, plus a small + // thumbnail (max width _THUMB_W) at lower quality for previews. + let resultb64; + try { + resultb64 = canvas.toDataURL("image/jpeg", 0.85); + } catch (e) { + Lib.logError("CameraPicture: canvas toDataURL failed", e); + return; + } + + const thumbH = videoWidth + ? Math.round((videoHeight * _THUMB_W) / videoWidth) + : _THUMB_W; + const thumbCanvas = document.createElement("canvas"); + thumbCanvas.width = _THUMB_W; + thumbCanvas.height = thumbH; + const thumbCtx = thumbCanvas.getContext("2d", _CTX_2D_OPTS); + if (thumbCtx) thumbCtx.drawImage(canvas, 0, 0, _THUMB_W, thumbH); + + let thumbB64 = ""; + try { + thumbB64 = thumbCanvas.toDataURL("image/jpeg", 0.7); + } catch (e) { + Lib.logError("CameraPicture: thumb toDataURL failed", e); + } + + if (Lib.isDestroyed(this)) return; + this.setProperty("value", resultb64); + this.setProperty("thumbnail", thumbB64); + this.fireOnPhoto({ photo: resultb64 }); + this._stopCamera(); + }, + + _stopCamera() { + // Stop every track of the active stream so the OS frees the camera. + if (this._stream) { + for (const track of this._stream.getTracks()) track.stop(); + } + this._stream = null; + const video = document.getElementById(`${this.getId()}-video`); + if (video) video.srcObject = null; + }, + + onPicture() { + if (this._oScanDialog?.isOpen()) return; + if (!this._oScanDialog) { + this._oScanDialog = new Dialog({ + title: "Device Photo Function", + contentWidth: "640px", + contentHeight: "480px", + horizontalScrolling: false, + verticalScrolling: false, + stretch: true, + afterClose: () => this._stopCamera(), + content: [ + new HTML({ + id: `${this.getId()}PictureContainer`, + content: `