From 00b03633bd2aece6f3822bf451dfa912ef19fd90 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 01:19:38 +0000 Subject: [PATCH] Publish the samples as @cap2ui5/samples, a package a CAP project adds abap2UI5's samples run in any system they are pulled into; these ran only as a project of their own. cap2UI5's plugin now loads the apps a dependency declares (cap2UI5 "Serve the apps a package brings, beside the project's own"), and it is published as @cap2ui5/cds-plugin 0.3.0. So the samples become @cap2ui5/samples: `npm add -D @cap2ui5/samples` in a CAP project, and cds watch lists every sample beside the project's own apps. - package.json: the name, version 0.1.0 and what npm shows; files is srv/apps, the README, the changelog and the license; "cap2ui5": { "apps": "srv/apps" } is where the plugin finds the apps; the plugin is a peer dependency (^0.3.0), so the samples run on the project's own. Everything the repository needs for itself is a devDependency. - srv/apps: every sample imports @cap2ui5/cds-plugin - the 69 generated ones regenerated by abap2js 0.3.0 from the pin (the import line is the only change), the two hand-written ones edited the same way; generate and originals take abap2js and the runtime from the new name. - scripts/consumer-test.mjs: packs the samples as publish would, installs the tarball with the plugin into a throwaway CAP project that has an app of its own, serves it, and checks that the plugin loads every sample from the package, a sample shows its view and the project's app still answers. `--plugin ` runs it before the plugin is on npm. - test.yml: the plugin from npm, as a project installs it - it used to pack cap2UI5's plugin from a branch that has since been deleted, so the workflow could not run any more - and the consumer test; callable by release.yml. - release.yml: a tag v runs test.yml on the tagged commit and publishes by trusted publishing, as cap2UI5's release.yml does; the first version is published by hand, and its header and the README say how, `npm trust` included. - README: how to add the samples to a project, how to publish; the note about installing the plugin from a branch is gone. CHANGELOG: 0.1.0. Tested against @cap2ui5/cds-plugin 0.3.0 packed from cap2UI5's branch: npm test (9 tests, every sample over the wire), check:generated, the differential test (all 71 behave as their ABAP originals), and the consumer test - 71 app modules loaded from @cap2ui5/samples in a project that installed the tarball. CI needs @cap2ui5/cds-plugin 0.3.0 on npm. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018bBcFp146qnMCmXWztQaH8 --- .github/workflows/release.yml | 105 +++++++++++++++++++++ .github/workflows/test.yml | 33 +++---- CHANGELOG.md | 22 +++++ README.md | 72 +++++++++++---- package.json | 46 ++++++++-- scripts/consumer-test.mjs | 153 +++++++++++++++++++++++++++++++ scripts/generate.mjs | 2 +- scripts/originals.mjs | 2 +- srv/apps/z2ui5_cl_smp_app_011.js | 2 +- srv/apps/z2ui5_cl_smp_app_026.js | 2 +- srv/apps/z2ui5_cl_smp_app_027.js | 2 +- srv/apps/z2ui5_cl_smp_app_050.js | 2 +- srv/apps/z2ui5_cl_smp_app_065.js | 2 +- srv/apps/z2ui5_cl_smp_app_067.js | 2 +- srv/apps/z2ui5_cl_smp_app_088.js | 2 +- srv/apps/z2ui5_cl_smp_app_109.js | 2 +- srv/apps/z2ui5_cl_smp_app_120.js | 2 +- srv/apps/z2ui5_cl_smp_app_122.js | 2 +- srv/apps/z2ui5_cl_smp_app_125.js | 2 +- srv/apps/z2ui5_cl_smp_app_133.js | 2 +- srv/apps/z2ui5_cl_smp_app_143.js | 2 +- srv/apps/z2ui5_cl_smp_app_161.js | 2 +- srv/apps/z2ui5_cl_smp_app_163.js | 2 +- srv/apps/z2ui5_cl_smp_app_166.js | 2 +- srv/apps/z2ui5_cl_smp_app_167.js | 2 +- srv/apps/z2ui5_cl_smp_app_170.js | 2 +- srv/apps/z2ui5_cl_smp_app_173.js | 2 +- srv/apps/z2ui5_cl_smp_app_176.js | 2 +- srv/apps/z2ui5_cl_smp_app_186.js | 2 +- srv/apps/z2ui5_cl_smp_app_189.js | 2 +- srv/apps/z2ui5_cl_smp_app_202.js | 2 +- srv/apps/z2ui5_cl_smp_app_255.js | 2 +- srv/apps/z2ui5_cl_smp_app_279.js | 2 +- srv/apps/z2ui5_cl_smp_app_305.js | 2 +- srv/apps/z2ui5_cl_smp_app_316.js | 2 +- srv/apps/z2ui5_cl_smp_app_325.js | 2 +- srv/apps/z2ui5_cl_smp_app_327.js | 2 +- srv/apps/z2ui5_cl_smp_app_361.js | 2 +- srv/apps/z2ui5_cl_smp_app_382.js | 2 +- srv/apps/z2ui5_cl_smp_app_445.js | 2 +- srv/apps/z2ui5_cl_smp_app_448.js | 2 +- srv/apps/z2ui5_cl_smp_app_449.js | 2 +- srv/apps/z2ui5_cl_smp_app_450.js | 2 +- srv/apps/z2ui5_cl_smp_app_456.js | 2 +- srv/apps/z2ui5_cl_smp_app_457.js | 2 +- srv/apps/z2ui5_cl_smp_app_460.js | 2 +- srv/apps/z2ui5_cl_smp_app_462.js | 2 +- srv/apps/z2ui5_cl_smp_app_465.js | 2 +- srv/apps/z2ui5_cl_smp_app_466.js | 2 +- srv/apps/z2ui5_cl_smp_app_467.js | 2 +- srv/apps/z2ui5_cl_smp_app_469.js | 2 +- srv/apps/z2ui5_cl_smp_app_470.js | 2 +- srv/apps/z2ui5_cl_smp_app_472.js | 2 +- srv/apps/z2ui5_cl_smp_app_473.js | 2 +- srv/apps/z2ui5_cl_smp_app_474.js | 2 +- srv/apps/z2ui5_cl_smp_app_488.js | 2 +- srv/apps/z2ui5_cl_smp_app_489.js | 2 +- srv/apps/z2ui5_cl_smp_app_490.js | 2 +- srv/apps/z2ui5_cl_smp_app_491.js | 2 +- srv/apps/z2ui5_cl_smp_app_492.js | 2 +- srv/apps/z2ui5_cl_smp_app_493.js | 2 +- srv/apps/z2ui5_cl_smp_app_494.js | 2 +- srv/apps/z2ui5_cl_smp_app_495.js | 2 +- srv/apps/z2ui5_cl_smp_app_496.js | 2 +- srv/apps/z2ui5_cl_smp_app_498.js | 2 +- srv/apps/z2ui5_cl_smp_app_499.js | 2 +- srv/apps/z2ui5_cl_smp_app_503.js | 2 +- srv/apps/z2ui5_cl_smp_app_506.js | 2 +- srv/apps/z2ui5_cl_smp_app_507.js | 2 +- srv/apps/z2ui5_cl_smp_app_508.js | 2 +- srv/apps/z2ui5_cl_smp_app_509.js | 2 +- srv/apps/z2ui5_cl_smp_app_510.js | 2 +- srv/apps/z2ui5_cl_smp_app_511.js | 2 +- srv/apps/z2ui5_cl_smp_app_513.js | 2 +- srv/apps/z2ui5_cl_smp_app_514.js | 2 +- srv/apps/z2ui5_cl_smp_app_515.js | 2 +- srv/apps/z2ui5_cl_smp_app_516.js | 2 +- srv/apps/z2ui5_cl_smp_app_518.js | 2 +- srv/apps/z2ui5_cl_smp_app_519.js | 2 +- 79 files changed, 460 insertions(+), 117 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 scripts/consumer-test.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..887b6fb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,105 @@ +# Publishes the samples as the npm package `@cap2ui5/samples` when a tag +# v is pushed. The version is package.json's - bump it, and move the +# changelog's Unreleased lines under it, in the pull request that prepares the +# release; the job refuses a tag that says something else. +# +# Trusted publishing (OIDC), as cap2UI5's own release.yml publishes the +# plugin: no NPM_TOKEN to leak or rotate, and npm records a provenance +# attestation tying the tarball to this run and commit. The package's +# Settings -> Trusted Publisher on npmjs.com has to name this repository and +# this workflow file - on the command line: +# +# npx npm@11 trust github @cap2ui5/samples --file release.yml \ +# --repo cap2UI5/samples --allow-publish +# +# That setting can only be made for a package that ALREADY EXISTS, so the very +# first version is published by hand, once, after `npm login`: +# +# npm publish --access public +# +# (no --provenance there: npm generates an attestation only from a supported +# CI and aborts anywhere else) - and the Trusted Publisher is set right after: +# cap2UI5's v0.2.0 was tagged while its package existed without one, and its +# release failed with ENEEDAUTH. Until the package exists, a failed publish +# here is a warning naming that bootstrap; once it exists, a failed publish is +# an error. +name: release + +on: + push: + tags: + - "v*.*.*" + # Everything except the publish: the same tests, the tarball listed, no + # registry write. + workflow_dispatch: + +permissions: + contents: read + +jobs: + # everything test.yml runs - the samples over the wire, the package in a + # throwaway project, the translation and the differential test - on the + # commit to publish + test: + uses: ./.github/workflows/test.yml + + publish: + needs: test + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + id-token: write # trusted publishing + provenance + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: .nvmrc + + # Node 22 ships npm 10.x, which has no OIDC support. PINNED, not + # @latest: this is the one job in the repository that holds a publishing + # identity. The same pin as cap2UI5's release.yml. + - name: Use an npm that can publish via OIDC + run: npm install -g npm@12.0.2 + + # The tag is the version claim; package.json is what gets published. A + # mismatch caught here costs a minute, caught afterwards a burned version + # number. + - name: The tag and package.json agree + if: github.ref_type == 'tag' + run: | + PKG="v$(node -p "require('./package.json').version")" + if [ "$PKG" != "$GITHUB_REF_NAME" ]; then + echo "::error::tag $GITHUB_REF_NAME does not match package.json ($PKG)" + exit 1 + fi + + # what the tarball will contain, in the log, before it is immutable + - name: What is in the tarball + run: npm pack --dry-run + + - name: Publish + if: github.ref_type == 'tag' + run: | + set -u + NAME="$(node -p "require('./package.json').name")" + VERSION="$(node -p "require('./package.json').version")" + if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then + echo "$NAME@$VERSION is already on the registry - nothing to do" + exit 0 + fi + if npm publish --provenance --access public; then + echo "published $NAME@$VERSION" + exit 0 + fi + if npm view "$NAME" version >/dev/null 2>&1; then + echo "::error::$NAME is on the registry, but publishing $VERSION failed - see the npm output above (the Trusted Publisher not pointing at this repository and release.yml?)" + exit 1 + fi + echo "::warning::$NAME@$VERSION was NOT published: the package does not exist on the registry yet, and trusted publishing can only be configured for one that does. Bootstrap it once by hand (the header of this workflow), then every tag publishes here." + + - name: Dry run only + if: github.ref_type != 'tag' + run: echo "Not a tag - everything ran except the publish." diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c0f099e..2395431 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,35 +4,32 @@ on: push: branches: [main] pull_request: + # release.yml runs all of this on the tagged commit before it publishes + workflow_call: + +permissions: + contents: read jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: .nvmrc - # Until cap2ui5 0.2.0 is on npm, the samples run against cap2UI5's plugin: - # packed as `npm publish` packs it, and installed alone - which brings the - # other dependencies along, as the README says for a local checkout. Once - # it is published this goes, a package-lock.json pins it, and `cache: npm` - # and npm ci come back. - # - # The ref is the branch that adds abap2js (and t.numc, which - # z2ui5_cl_smp_app_067 needs) until that is on cap2UI5's main - then this - # line goes too. - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - repository: cap2UI5/cap2UI5 - ref: claude/absp2ui5-cap2ui5-transfer-7pg6dg - path: .cap2ui5 - persist-credentials: false - - run: npm pack --pack-destination "$RUNNER_TEMP" - working-directory: .cap2ui5/plugin - - run: npm install --no-save --no-audit --no-fund "$RUNNER_TEMP"/cap2ui5-*.tgz + # The plugin from npm, in the version the peer dependency names - what a + # project that adds the samples runs them on. No lockfile, as in + # cap2UI5: the run tests what an install gets today. + - run: npm install --no-audit --no-fund - run: npm test + # ---- the package: packed as publish packs it, installed into a + # throwaway CAP project beside an app of its own, and served + - run: npm run consumer-test + # ---- the translation: srv/apps is what abap2js makes of the pinned samples - id: pin run: echo "sha=$(cat ABAP2UI5_SAMPLES_PIN)" >> "$GITHUB_OUTPUT" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e671460 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog + +All notable changes to `@cap2ui5/samples` are recorded here. The format +follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the +versions [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - 2026-09-29 + +The first release: abap2UI5's samples as a package a CAP project adds. + +- 71 of abap2UI5's 129 samples as cap2UI5 apps in `srv/apps/`: 69 translated + by abap2js from abap2UI5/samples at the commit in `ABAP2UI5_SAMPLES_PIN`, + two ported by hand. The differential test holds every one of them to its + ABAP original. +- `npm add @cap2ui5/samples` in a project with `@cap2ui5/cds-plugin` 0.3 - a + peer dependency - and the samples run beside the project's own apps: the + package declares them for the plugin, `"cap2ui5": { "apps": "srv/apps" }`. + +[Unreleased]: https://github.com/cap2UI5/samples/compare/v0.1.0...HEAD +[0.1.0]: https://www.npmjs.com/package/@cap2ui5/samples/v/0.1.0 diff --git a/README.md b/README.md index 0122db2..d603789 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # cap2UI5 samples The [abap2UI5 samples](https://github.com/abap2UI5/samples) as -[cap2UI5](https://github.com/cap2UI5/cap2UI5) apps: every sample a plain -JavaScript class in `srv/apps/`, in an ordinary CAP project - **translated from -its ABAP original, not rewritten.** cap2ui5's `abap2js` reads the ABAP class +[cap2UI5](https://github.com/cap2UI5/cap2UI5) apps, published as +**`@cap2ui5/samples`**: add the package to a CAP project and they run beside +its own apps, as abap2UI5's samples run in the system they are pulled into. +Every sample is a plain JavaScript class in `srv/apps/` - **translated from +its ABAP original, not rewritten.** cap2UI5's `abap2js` reads the ABAP class and writes the module line for line: the same class name, the same attributes and methods, the same calls - the client is abap2UI5's `z2ui5_if_client` by its own names, the view is built with `z2ui5_cl_ui5_view_builder` - and the @@ -14,26 +16,34 @@ original's comments and texts, all of them, as they are. > **Status: 71 of the 129 samples.** 69 are generated by abap2js from > abap2UI5/samples at the commit in [`ABAP2UI5_SAMPLES_PIN`](ABAP2UI5_SAMPLES_PIN), > two are ported by hand; the [differential test](#the-differential-test) holds -> every one of them to its ABAP original. They need a cap2ui5 that is not on -> npm yet: 0.2.0 (the client under its ABAP names, the view builder) plus -> abap2js and `t.numc()`, which are on cap2UI5's branch -> `claude/absp2ui5-cap2ui5-transfer-7pg6dg` until they are on its `main`. -> Until then a plain `npm install` answers `ETARGET`; install the plugin packed -> from that branch instead, which brings the other dependencies along - CI does -> the same: -> -> ```bash -> git clone -b claude/absp2ui5-cap2ui5-transfer-7pg6dg https://github.com/cap2UI5/cap2UI5 ../cap2UI5 -> (cd ../cap2UI5/plugin && npm pack --pack-destination /tmp) -> npm install --no-save /tmp/cap2ui5-*.tgz -> ``` - -## Run +> every one of them to its ABAP original. + +## Add them to your project + +In a CAP project with [`@cap2ui5/cds-plugin`](https://github.com/cap2UI5/cap2UI5) +0.3 or later: + +```bash +npm add -D @cap2ui5/samples +cds watch # lists every sample beside your own apps +``` + +The plugin loads the apps a dependency declares in its `package.json` - +here `"cap2ui5": { "apps": "srv/apps" }` - beside the project's own, so every +sample starts under its ABAP name, e.g. +`/sap/bc/z2ui5?app_start=Z2UI5_CL_SMP_APP_493`. As a devDependency they are +there in development only: with `NODE_ENV=production` the plugin leaves a +devDependency's apps out, as CAP leaves out its plugins. `npm add` without +`-D` brings them to production too. An app of the project's own that has the +name of a sample stays the project's; the log says so. + +## Run this repository ```bash npm install npm run watch # cds watch - prints the address of every sample npm test # every sample driven over the wire +npm run consumer-test # the package: packed, installed into a throwaway CAP project, served ``` Log in as `alice` with an empty password (CAP's mocked development user), then @@ -226,3 +236,29 @@ counterpart: 3. **Every field is part of the model.** ABAP keeps a `PROTECTED` attribute out of it; a JavaScript field with an initial value is always bound. The client is the exception: assigned in `main( )` and not declared, it stays out. + +## Publishing + +A tag `v` publishes the package as `@cap2ui5/samples` +(`.github/workflows/release.yml`). It runs everything `test.yml` runs on the +tagged commit - the samples over the wire, the package in a throwaway +project, the translation and the differential test - and publishes by +trusted publishing, with provenance and no token. The version is +`package.json`'s: the pull request that prepares a release bumps it and moves +the changelog's `Unreleased` lines under it. The package carries `srv/apps/`, +this README, the changelog and the license - not the tests, the scripts or +the pin. A sample that needs a newer plugin raises the peer dependency on +`@cap2ui5/cds-plugin` with it. + +npm points a package at a workflow only once the package exists, so the +first version goes out by hand, once, from a clean checkout of `main` whose +CI is green - and the Trusted Publisher is set right after, or the next tag +fails to publish: + +```bash +npm install && npm test && npm run consumer-test +npm login +npm publish --access public +npx npm@11 trust github @cap2ui5/samples --file release.yml --repo cap2UI5/samples --allow-publish +git tag v0.1.0 && git push origin v0.1.0 # finds 0.1.0 on npm and publishes nothing +``` diff --git a/package.json b/package.json index 2fbe4de..98b49da 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,48 @@ { - "name": "cap2ui5-samples", - "private": true, - "description": "The abap2UI5 samples as cap2UI5 apps: plain JavaScript classes in a CAP project, views built with ViewBuilder.", + "name": "@cap2ui5/samples", + "version": "0.1.0", + "description": "abap2UI5's samples as cap2UI5 apps: add the package to a CAP project and they run beside its own apps. Every sample a plain JavaScript class, translated from its ABAP original line for line.", + "keywords": [ + "cap", + "cds", + "sap", + "ui5", + "sapui5", + "abap2ui5", + "cap2ui5", + "samples" + ], + "homepage": "https://github.com/cap2UI5/samples#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/cap2UI5/samples.git" + }, + "bugs": { + "url": "https://github.com/cap2UI5/samples/issues" + }, + "license": "MIT", "type": "module", + "files": [ + "srv/apps", + "README.md", + "CHANGELOG.md", + "LICENSE" + ], + "cap2ui5": { + "apps": "srv/apps" + }, "engines": { "node": ">=22" }, - "dependencies": { - "@cap-js/sqlite": "^3", - "@sap/cds": "^10", - "cap2ui5": "^0.2.0" + "peerDependencies": { + "@cap2ui5/cds-plugin": "^0.3.0" }, "devDependencies": { "@abaplint/transpiler-cli": "2.13.91", "@cap-js/cds-test": "^1.0.2", + "@cap-js/sqlite": "^3", + "@cap2ui5/cds-plugin": "^0.3.0", + "@sap/cds": "^10", "fast-xml-parser": "^5.11.1" }, "scripts": { @@ -23,7 +52,8 @@ "generate": "node scripts/generate.mjs", "check:generated": "node scripts/generate.mjs --check", "originals": "node scripts/originals.mjs", - "differential": "node scripts/originals.mjs && node --test test/differential.mjs" + "differential": "node scripts/originals.mjs && node --test test/differential.mjs", + "consumer-test": "node scripts/consumer-test.mjs" }, "cds": { "requires": { diff --git a/scripts/consumer-test.mjs b/scripts/consumer-test.mjs new file mode 100644 index 0000000..de862ca --- /dev/null +++ b/scripts/consumer-test.mjs @@ -0,0 +1,153 @@ +#!/usr/bin/env node +/** + * consumer-test - the samples the way a project gets them: + * `npm add @cap2ui5/samples`. + * + * Everything else here runs the samples as THIS project's apps - srv/apps + * under its own root. That proves the samples work; it proves nothing about + * the PACKAGE. A `files` list that forgets srv/apps, a `cap2ui5.apps` naming + * the wrong directory, an import that only resolves inside this checkout - + * none of those can fail here, and all of them fail in the project that adds + * the package. + * + * So this packs the samples as `npm publish` would, installs the tarball + * into a throwaway CAP project that has an app of its own and the plugin, + * serves it, and checks that + * + * - the tarball carries every sample, and nothing of the tests or scripts + * - the plugin loads the samples from the installed package, beside the + * project's own app + * - a sample starts and shows its view, and the project's app still answers + * + * The plugin comes from npm, in the version the samples' peerDependencies + * name - or, with --plugin , from a packed plugin, before that + * version is published. + * + * Usage: node scripts/consumer-test.mjs [--plugin ] [--keep] + */ +import { execFileSync, spawn } from "node:child_process"; +import { createRequire } from "node:module"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { setTimeout as sleep } from "node:timers/promises"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const args = process.argv.slice(2); +const KEEP = args.includes("--keep"); +const at = args.indexOf("--plugin"); +const PLUGIN_TGZ = at >= 0 ? path.resolve(args[at + 1]) : null; +const run = (cmd, argv, cwd) => execFileSync(cmd, argv, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }); + +// the ports fetch( ) refuses to connect to - the WHATWG "bad port" list, +// as cap2UI5's test server keeps it +const BAD_PORTS = new Set([5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668, 6669, 6679, 6697]); +let PORT; +do PORT = 5000 + Math.floor(Math.random() * 2000); while (BAD_PORTS.has(PORT)); + +let failures = 0; +const check = (name, ok, detail = "") => { + console.log(`${ok ? " ok " : " FAIL"} ${name}${detail ? ` ${detail}` : ""}`); + if (!ok) failures++; +}; + +const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8")); +const samples = fs.readdirSync(path.join(ROOT, pkg.cap2ui5.apps)).filter((f) => /\.(c|m)?js$/.test(f)); + +const dir = fs.mkdtempSync(path.join(os.tmpdir(), "cap2ui5-samples-consumer-")); +const proj = path.join(dir, "proj"); +let server; +try { + console.log(`consumer-test: ${dir}`); + + // --- pack, exactly as publish would ----------------------------------------- + const [packed] = JSON.parse(run("npm", ["pack", "--json", "--pack-destination", dir], ROOT)); + const files = packed.files.map((f) => f.path); + const apps = files.filter((f) => f.startsWith(`${pkg.cap2ui5.apps}/`)); + check("the tarball carries every sample", apps.length === samples.length, `${apps.length} of ${samples.length}`); + for (const f of ["package.json", "README.md", "CHANGELOG.md", "LICENSE"]) { + check(`the tarball carries ${f}`, files.includes(f)); + } + const stray = files.filter((f) => /^(test|scripts|\.github)\//.test(f)); + check("the tarball carries no tests, scripts or workflows", stray.length === 0, stray.slice(0, 3).join(" ")); + + // --- a CAP project that has never heard of this repository ------------------ + fs.mkdirSync(path.join(proj, "srv", "apps"), { recursive: true }); + fs.writeFileSync(path.join(proj, "package.json"), JSON.stringify({ + name: "cap2ui5-samples-consumer-probe", + private: true, + dependencies: { + "@cap-js/sqlite": pkg.devDependencies["@cap-js/sqlite"], + "@sap/cds": pkg.devDependencies["@sap/cds"], + }, + cds: { requires: { db: { kind: "sqlite", credentials: { url: ":memory:" } } } }, + }, null, 2)); + fs.writeFileSync(path.join(proj, "srv", "apps", "probe.js"), ` +const { defineApp } = require("@cap2ui5/cds-plugin"); +defineApp("ZCL_PROBE", class { + from = "the project"; + main(client) { + if (client.check_on_navigated()) { + client.view_display(\`\`); + } + } +}); +`); + const plugin = PLUGIN_TGZ ?? `@cap2ui5/cds-plugin@${pkg.peerDependencies["@cap2ui5/cds-plugin"]}`; + run("npm", ["install", "--no-audit", "--no-fund", plugin, path.join(dir, packed.filename)], proj); + check("npm install of the samples and the plugin succeeds", true, PLUGIN_TGZ ? path.basename(PLUGIN_TGZ) : plugin); + + // --- served ------------------------------------------------------------------ + const serve = createRequire(path.join(proj, "package.json")).resolve("@sap/cds/bin/serve.js"); + server = spawn(process.execPath, [serve], { + cwd: proj, + env: { ...process.env, PORT: String(PORT), NODE_ENV: "development" }, + stdio: ["ignore", "pipe", "pipe"], + detached: true, + }); + let out = ""; + server.stdout.on("data", (d) => (out += d)); + server.stderr.on("data", (d) => (out += d)); + for (let i = 0; i < 90 && !out.includes("server listening") && server.exitCode === null; i++) await sleep(1000); + check("the server starts with the samples installed", out.includes("server listening"), + out.includes("server listening") ? "" : out.slice(-1500)); + + const loaded = out.match(/(\d+) app module\(s\) loaded from @cap2ui5\/samples/); + check("the plugin loads the samples from the installed package", Number(loaded?.[1]) === samples.length, + loaded?.[0] ?? "no log line naming @cap2ui5/samples"); + check("and the project's own app beside them", /1 app module\(s\) loaded from srv\/apps/.test(out)); + + const url = `http://127.0.0.1:${PORT}/rest/root/z2ui5`; + const post = async (app) => { + const r = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json", Authorization: "Basic " + Buffer.from("alice:").toString("base64") }, + body: JSON.stringify({ value: { S_FRONT: { + ID: "", APP: app, EVENT: "", T_EVENT_ARG: [], ORIGIN: "http://127.0.0.1", PATHNAME: "/rest/root/z2ui5", + SEARCH: `?app_start=${app}`, HASH: "", CONFIG: {} }, XX: {}, MODEL: {} } }), + }); + const text = await r.text(); + let json = null; + try { json = JSON.parse(text); } catch { /* an error page */ } + return { status: r.status, text, json }; + }; + const view = (r) => (r.json?.S_FRONT?.S_ACTION?.T_SYSTEM ?? []) + .find((a) => a[0] === "VIEW_SLOTS" && a[1] === "display" && a[2] === "MAIN")?.[3] ?? ""; + + const hello = await post("Z2UI5_CL_SMP_APP_493"); + check("a sample starts and shows its view", hello.status === 200 && /title="abap2UI5 - /.test(view(hello)), + `${hello.status} ${hello.status === 200 ? "" : hello.text.slice(0, 200)}`); + const own = await post("ZCL_PROBE"); + check("the project's own app still answers", own.status === 200 && own.json?.MODEL?.FROM === "the project", + `${own.status} ${JSON.stringify(own.json?.MODEL ?? {})}`); +} catch (e) { + check("the consumer test ran through", false, String(e.stderr || e.message).trim().split("\n").slice(0, 3).join(" | ")); +} finally { + if (server) try { process.kill(-server.pid, "SIGKILL"); } catch { /* already gone */ } + if (KEEP) console.log(`kept: ${dir}`); + else fs.rmSync(dir, { recursive: true, force: true }); +} + +console.log(failures ? `\nconsumer-test: ${failures} FAILED` : "\nconsumer-test: OK"); +process.exit(failures ? 1 : 0); diff --git a/scripts/generate.mjs b/scripts/generate.mjs index d2252c4..596fad9 100644 --- a/scripts/generate.mjs +++ b/scripts/generate.mjs @@ -22,7 +22,7 @@ import { execFileSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import { abap2js, Abap2jsError } from "cap2ui5"; +import { abap2js, Abap2jsError } from "@cap2ui5/cds-plugin"; const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const args = process.argv.slice(2); diff --git a/scripts/originals.mjs b/scripts/originals.mjs index 980e1fd..69e2b49 100644 --- a/scripts/originals.mjs +++ b/scripts/originals.mjs @@ -33,7 +33,7 @@ const head = execFileSync("git", ["-C", checkout, "rev-parse", "HEAD"], { encodi if (head !== pin) throw new Error(`${checkout} is at ${head}, ABAP2UI5_SAMPLES_PIN says ${pin}`); // the transpiler the runtime was built with: its output is tied to the runtime -const runtimeDir = path.dirname(require.resolve("@abap2ui5/node-runtime/package.json", { paths: [require.resolve("cap2ui5")] })); +const runtimeDir = path.dirname(require.resolve("@abap2ui5/node-runtime/package.json", { paths: [require.resolve("@cap2ui5/cds-plugin")] })); const wanted = JSON.parse(fs.readFileSync(path.join(runtimeDir, "package.json"), "utf8")).abap2ui5?.transpiler; const have = JSON.parse(fs.readFileSync(require.resolve("@abaplint/transpiler-cli/package.json"), "utf8")).version; if (wanted && wanted !== have) { diff --git a/srv/apps/z2ui5_cl_smp_app_011.js b/srv/apps/z2ui5_cl_smp_app_011.js index f77a150..fa55cfd 100644 --- a/srv/apps/z2ui5_cl_smp_app_011.js +++ b/srv/apps/z2ui5_cl_smp_app_011.js @@ -2,7 +2,7 @@ // @summary An editable table: input cells, adding and deleting rows, multi-select and a toolbar over them. // @docs https://abap2ui5.github.io/docs/cookbook/model/tables https://abap2ui5.github.io/docs/tutorials/walkthrough/step-8 https://abap2ui5.github.io/docs/tutorials/walkthrough/step-10 // @origin abap2UI5/samples src/z2ui5_cl_smp_app_011.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_011", class { diff --git a/srv/apps/z2ui5_cl_smp_app_026.js b/srv/apps/z2ui5_cl_smp_app_026.js index 2cacadd..f0305a7 100644 --- a/srv/apps/z2ui5_cl_smp_app_026.js +++ b/srv/apps/z2ui5_cl_smp_app_026.js @@ -2,7 +2,7 @@ // @summary A Popover anchored to the control that opened it, with the placements to choose from and a confirm/cancel footer. // @docs https://abap2ui5.github.io/docs/cookbook/popup_popover/popover // @origin abap2UI5/samples src/z2ui5_cl_smp_app_026.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_026", class { diff --git a/srv/apps/z2ui5_cl_smp_app_027.js b/srv/apps/z2ui5_cl_smp_app_027.js index 5d7e477..d7fb389 100644 --- a/srv/apps/z2ui5_cl_smp_app_027.js +++ b/srv/apps/z2ui5_cl_smp_app_027.js @@ -2,7 +2,7 @@ // @summary Expression binding in the view - conditions, composite parts and a regular expression decide visible and enabled without asking the backend. // @docs https://abap2ui5.github.io/docs/cookbook/model/expression_binding // @origin abap2UI5/samples src/z2ui5_cl_smp_app_027.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_027", class { diff --git a/srv/apps/z2ui5_cl_smp_app_050.js b/srv/apps/z2ui5_cl_smp_app_050.js index ec4b459..387721d 100644 --- a/srv/apps/z2ui5_cl_smp_app_050.js +++ b/srv/apps/z2ui5_cl_smp_app_050.js @@ -2,7 +2,7 @@ // @summary Ships a stylesheet with the view, so an app can carry its own design without a change to the UI5 theme. // @docs https://abap2ui5.github.io/docs/cookbook/view/definition // @origin abap2UI5/samples src/z2ui5_cl_smp_app_050.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_050", class { diff --git a/srv/apps/z2ui5_cl_smp_app_065.js b/srv/apps/z2ui5_cl_smp_app_065.js index d81c8e4..bdee66f 100644 --- a/srv/apps/z2ui5_cl_smp_app_065.js +++ b/srv/apps/z2ui5_cl_smp_app_065.js @@ -2,7 +2,7 @@ // @summary A nested view: nest_view_display renders a second view inside the first, and shows which model refresh reaches it. // @docs https://abap2ui5.github.io/docs/cookbook/view/nested_views // @origin abap2UI5/samples src/z2ui5_cl_smp_app_065.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_065", class { diff --git a/srv/apps/z2ui5_cl_smp_app_067.js b/srv/apps/z2ui5_cl_smp_app_067.js index c6ae480..cae2383 100644 --- a/srv/apps/z2ui5_cl_smp_app_067.js +++ b/srv/apps/z2ui5_cl_smp_app_067.js @@ -2,7 +2,7 @@ // @summary Formats amounts with sap.ui.model.type.Currency, so decimals and leading zeros follow the currency rather than the ABAP field. // @docs https://abap2ui5.github.io/docs/cookbook/model/formatter // @origin abap2UI5/samples src/z2ui5_cl_smp_app_067.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_067", class { diff --git a/srv/apps/z2ui5_cl_smp_app_088.js b/srv/apps/z2ui5_cl_smp_app_088.js index 8571f4b..47e9cc8 100644 --- a/srv/apps/z2ui5_cl_smp_app_088.js +++ b/srv/apps/z2ui5_cl_smp_app_088.js @@ -2,7 +2,7 @@ // @summary Switches the page of a NavContainer and the tab of an IconTabBar by ID, so navigation inside a view costs no roundtrip. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_088.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_088", class { diff --git a/srv/apps/z2ui5_cl_smp_app_109.js b/srv/apps/z2ui5_cl_smp_app_109.js index 6e5b955..4c43b68 100644 --- a/srv/apps/z2ui5_cl_smp_app_109.js +++ b/srv/apps/z2ui5_cl_smp_app_109.js @@ -2,7 +2,7 @@ // @summary A QuickView contact card in a Popover: grouped fields, and links that call the phone or the mail app. // @docs https://abap2ui5.github.io/docs/cookbook/popup_popover/popover // @origin abap2UI5/samples src/z2ui5_cl_smp_app_109.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_109", class { diff --git a/srv/apps/z2ui5_cl_smp_app_120.js b/srv/apps/z2ui5_cl_smp_app_120.js index 25f3f5f..6347666 100644 --- a/srv/apps/z2ui5_cl_smp_app_120.js +++ b/srv/apps/z2ui5_cl_smp_app_120.js @@ -2,7 +2,7 @@ // @summary Asks the browser for the device's position - latitude, longitude and altitude - and what happens when the user says no. // @docs https://abap2ui5.github.io/docs/cookbook/device_capabilities/geolocation // @origin abap2UI5/samples src/z2ui5_cl_smp_app_120.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_120", class { diff --git a/srv/apps/z2ui5_cl_smp_app_122.js b/srv/apps/z2ui5_cl_smp_app_122.js index 7239eb9..659516b 100644 --- a/srv/apps/z2ui5_cl_smp_app_122.js +++ b/srv/apps/z2ui5_cl_smp_app_122.js @@ -2,7 +2,7 @@ // @summary Asks the frontend what it is: UI5 version, theme, operating system, browser and user agent, in one call. // @docs https://abap2ui5.github.io/docs/cookbook/device_capabilities/info // @origin abap2UI5/samples src/z2ui5_cl_smp_app_122.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_122", class { diff --git a/srv/apps/z2ui5_cl_smp_app_125.js b/srv/apps/z2ui5_cl_smp_app_125.js index b1008f5..bf9c84d 100644 --- a/srv/apps/z2ui5_cl_smp_app_125.js +++ b/srv/apps/z2ui5_cl_smp_app_125.js @@ -2,7 +2,7 @@ // @summary Sets the browser tab title from the app, so a bookmarked or duplicated window says which app it holds. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/title // @origin abap2UI5/samples src/z2ui5_cl_smp_app_125.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_125", class { diff --git a/srv/apps/z2ui5_cl_smp_app_133.js b/srv/apps/z2ui5_cl_smp_app_133.js index 6f88eda..ade332e 100644 --- a/srv/apps/z2ui5_cl_smp_app_133.js +++ b/srv/apps/z2ui5_cl_smp_app_133.js @@ -2,7 +2,7 @@ // @summary Sets the focus into an Input and selects its text, so the next keystroke overwrites rather than appends. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/focus // @origin abap2UI5/samples src/z2ui5_cl_smp_app_133.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_133", class { diff --git a/srv/apps/z2ui5_cl_smp_app_143.js b/srv/apps/z2ui5_cl_smp_app_143.js index a56713f..0b7013c 100644 --- a/srv/apps/z2ui5_cl_smp_app_143.js +++ b/srv/apps/z2ui5_cl_smp_app_143.js @@ -2,7 +2,7 @@ // @summary Keeps the active sap.ui.table column filters across a view model update, through the abap2UI5 uitableext custom control - without it they are reset. // @docs https://abap2ui5.github.io/docs/cookbook/model/tables // @origin abap2UI5/samples src/z2ui5_cl_smp_app_143.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_data = { field1: "", diff --git a/srv/apps/z2ui5_cl_smp_app_161.js b/srv/apps/z2ui5_cl_smp_app_161.js index 943f6af..0d274eb 100644 --- a/srv/apps/z2ui5_cl_smp_app_161.js +++ b/srv/apps/z2ui5_cl_smp_app_161.js @@ -2,7 +2,7 @@ // @summary A dialog opened from inside a dialog, and what closing the inner one does to the stack. // @docs https://abap2ui5.github.io/docs/cookbook/popup_popover/popup // @origin abap2UI5/samples src/z2ui5_cl_smp_app_161.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_161", class { diff --git a/srv/apps/z2ui5_cl_smp_app_163.js b/srv/apps/z2ui5_cl_smp_app_163.js index 949a761..94dbf91 100644 --- a/srv/apps/z2ui5_cl_smp_app_163.js +++ b/srv/apps/z2ui5_cl_smp_app_163.js @@ -1,7 +1,7 @@ // @keywords menu menuitem popover button messagetoast require module // @summary A Menu opened as a popover from a Button, whose items call a UI5 module loaded with core:require, so the click is answered in the frontend. // @origin abap2UI5/samples src/z2ui5_cl_smp_app_163.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_163", class { diff --git a/srv/apps/z2ui5_cl_smp_app_166.js b/srv/apps/z2ui5_cl_smp_app_166.js index 71b9349..beee119 100644 --- a/srv/apps/z2ui5_cl_smp_app_166.js +++ b/srv/apps/z2ui5_cl_smp_app_166.js @@ -2,7 +2,7 @@ // @summary Binds a form to a structure with INCLUDEs, so the included components are reachable under their own names on one flat level. // @docs https://abap2ui5.github.io/docs/cookbook/model/binding // @origin abap2UI5/samples src/z2ui5_cl_smp_app_166.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_struc_incl = { incl_title: "", diff --git a/srv/apps/z2ui5_cl_smp_app_167.js b/srv/apps/z2ui5_cl_smp_app_167.js index b0f2dc6..e6c989d 100644 --- a/srv/apps/z2ui5_cl_smp_app_167.js +++ b/srv/apps/z2ui5_cl_smp_app_167.js @@ -2,7 +2,7 @@ // @summary Sends extra arguments with an event (t_arg), so a handler knows which row, which value or which fixed payload it was called for. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/backend https://abap2ui5.github.io/docs/tutorials/walkthrough/step-6 // @origin abap2UI5/samples src/z2ui5_cl_smp_app_167.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_167", class { diff --git a/srv/apps/z2ui5_cl_smp_app_170.js b/srv/apps/z2ui5_cl_smp_app_170.js index c336426..bdf58f1 100644 --- a/srv/apps/z2ui5_cl_smp_app_170.js +++ b/srv/apps/z2ui5_cl_smp_app_170.js @@ -2,7 +2,7 @@ // @summary A NavContainer inside a dialog: several pages in one popup, with back and forward between them. // @docs https://abap2ui5.github.io/docs/cookbook/popup_popover/popup // @origin abap2UI5/samples src/z2ui5_cl_smp_app_170.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_170", class { diff --git a/srv/apps/z2ui5_cl_smp_app_173.js b/srv/apps/z2ui5_cl_smp_app_173.js index e494198..616d06b 100644 --- a/srv/apps/z2ui5_cl_smp_app_173.js +++ b/srv/apps/z2ui5_cl_smp_app_173.js @@ -2,7 +2,7 @@ // @summary Builds the columns of a table at runtime with template:repeat, including the if/then/else the templating language brings. // @docs https://abap2ui5.github.io/docs/cookbook/view/xml_templating // @origin abap2UI5/samples src/z2ui5_cl_smp_app_173.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_data = { name: "", diff --git a/srv/apps/z2ui5_cl_smp_app_176.js b/srv/apps/z2ui5_cl_smp_app_176.js index eb1ce65..f2bb00c 100644 --- a/srv/apps/z2ui5_cl_smp_app_176.js +++ b/srv/apps/z2ui5_cl_smp_app_176.js @@ -2,7 +2,7 @@ // @summary XML templating inside a nested view: the generated content is built where the sub view is rendered. // @docs https://abap2ui5.github.io/docs/cookbook/view/nested_views https://abap2ui5.github.io/docs/cookbook/view/xml_templating // @origin abap2UI5/samples src/z2ui5_cl_smp_app_176.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_data = { name: "", diff --git a/srv/apps/z2ui5_cl_smp_app_186.js b/srv/apps/z2ui5_cl_smp_app_186.js index 93d74b4..6401233 100644 --- a/srv/apps/z2ui5_cl_smp_app_186.js +++ b/srv/apps/z2ui5_cl_smp_app_186.js @@ -2,7 +2,7 @@ // @summary Sends a file to the browser as a download - an xstring encoded as base64, handed over as an attachment. // @docs https://abap2ui5.github.io/docs/cookbook/device_capabilities/upload_download // @origin abap2UI5/samples src/z2ui5_cl_smp_app_186.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_186", class { diff --git a/srv/apps/z2ui5_cl_smp_app_189.js b/srv/apps/z2ui5_cl_smp_app_189.js index 10d7aa1..a067f07 100644 --- a/srv/apps/z2ui5_cl_smp_app_189.js +++ b/srv/apps/z2ui5_cl_smp_app_189.js @@ -2,7 +2,7 @@ // @summary Moves the cursor to the next Input when Enter is pressed - the fast entry a form needs. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/focus // @origin abap2UI5/samples src/z2ui5_cl_smp_app_189.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_189", class { diff --git a/srv/apps/z2ui5_cl_smp_app_202.js b/srv/apps/z2ui5_cl_smp_app_202.js index a6cfff4..ac18d70 100644 --- a/srv/apps/z2ui5_cl_smp_app_202.js +++ b/srv/apps/z2ui5_cl_smp_app_202.js @@ -2,7 +2,7 @@ // @summary Drives a Wizard from the backend: setting the next step and discarding progress by ID, which is how a branching wizard is steered. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_202.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_202", class { diff --git a/srv/apps/z2ui5_cl_smp_app_255.js b/srv/apps/z2ui5_cl_smp_app_255.js index 8c0de31..c4741f8 100644 --- a/srv/apps/z2ui5_cl_smp_app_255.js +++ b/srv/apps/z2ui5_cl_smp_app_255.js @@ -2,7 +2,7 @@ // @summary Lays a page out with FlexBox and custom CSS classes - tiles, panels and a QuickView popover, all from the view chain. // @docs https://abap2ui5.github.io/docs/cookbook/view/definition // @origin abap2UI5/samples src/z2ui5_cl_smp_app_255.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_255", class { diff --git a/srv/apps/z2ui5_cl_smp_app_279.js b/srv/apps/z2ui5_cl_smp_app_279.js index 5ddea41..457e57f 100644 --- a/srv/apps/z2ui5_cl_smp_app_279.js +++ b/srv/apps/z2ui5_cl_smp_app_279.js @@ -2,7 +2,7 @@ // @summary Refuses to leave an app with unsaved changes: the confirmation popup in front of nav_app_leave, and how the dirty flag gets there. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/navigation/inner_app // @origin abap2UI5/samples src/z2ui5_cl_smp_app_279.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_279", class { diff --git a/srv/apps/z2ui5_cl_smp_app_305.js b/srv/apps/z2ui5_cl_smp_app_305.js index ea00a1d..f373b81 100644 --- a/srv/apps/z2ui5_cl_smp_app_305.js +++ b/srv/apps/z2ui5_cl_smp_app_305.js @@ -1,7 +1,7 @@ // @keywords color background conditional formatting style data attribute // @summary Colours single table cells from the backend: the row carries its colour as custom data and a stylesheet turns it into a background. // @origin abap2UI5/samples src/z2ui5_cl_smp_app_305.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_row = { title: "", diff --git a/srv/apps/z2ui5_cl_smp_app_316.js b/srv/apps/z2ui5_cl_smp_app_316.js index c38eb25..f684ce3 100644 --- a/srv/apps/z2ui5_cl_smp_app_316.js +++ b/srv/apps/z2ui5_cl_smp_app_316.js @@ -2,7 +2,7 @@ // @summary Opens mailto:, tel: and sms: links through URLHelper, so the device answers with its own mail or phone app instead of the browser. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/url_handling // @origin abap2UI5/samples src/z2ui5_cl_smp_app_316.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_316", class { diff --git a/srv/apps/z2ui5_cl_smp_app_325.js b/srv/apps/z2ui5_cl_smp_app_325.js index e926c15..529fd85 100644 --- a/srv/apps/z2ui5_cl_smp_app_325.js +++ b/srv/apps/z2ui5_cl_smp_app_325.js @@ -2,7 +2,7 @@ // @summary Copies text into the browser clipboard from the backend: a follow-up action carries the string, a toast confirms what landed there. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/clipboard // @origin abap2UI5/samples src/z2ui5_cl_smp_app_325.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_325", class { diff --git a/srv/apps/z2ui5_cl_smp_app_327.js b/srv/apps/z2ui5_cl_smp_app_327.js index 2adcc1d..cb90a49 100644 --- a/srv/apps/z2ui5_cl_smp_app_327.js +++ b/srv/apps/z2ui5_cl_smp_app_327.js @@ -2,7 +2,7 @@ // @summary Writes to the browser's local and session storage and reads it back, so a value survives a reload without any state in the backend. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/clipboard // @origin abap2UI5/samples src/z2ui5_cl_smp_app_327.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; // Both fields are strings on purpose. The value round-trips through the // browser and back through the storage, so whatever sits under the key is diff --git a/srv/apps/z2ui5_cl_smp_app_361.js b/srv/apps/z2ui5_cl_smp_app_361.js index 06f1fb9..614b3d6 100644 --- a/srv/apps/z2ui5_cl_smp_app_361.js +++ b/srv/apps/z2ui5_cl_smp_app_361.js @@ -1,7 +1,7 @@ // @keywords logoff signout icf session end fiori launchpad // @summary Ends the session from the client - the logoff an ICF session or a Fiori launchpad needs, triggered as a follow-up action. // @origin abap2UI5/samples src/z2ui5_cl_smp_app_361.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_361", class { diff --git a/srv/apps/z2ui5_cl_smp_app_382.js b/srv/apps/z2ui5_cl_smp_app_382.js index 7c027fd..f0a1c2a 100644 --- a/srv/apps/z2ui5_cl_smp_app_382.js +++ b/srv/apps/z2ui5_cl_smp_app_382.js @@ -2,7 +2,7 @@ // @summary Every MessageBox type - confirm, warning, error, success, information - and what a custom action button changes about the answer. // @docs https://abap2ui5.github.io/docs/cookbook/translation_messages/message // @origin abap2UI5/samples src/z2ui5_cl_smp_app_382.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_382", class { diff --git a/srv/apps/z2ui5_cl_smp_app_445.js b/srv/apps/z2ui5_cl_smp_app_445.js index 471c2b5..4e4b46f 100644 --- a/srv/apps/z2ui5_cl_smp_app_445.js +++ b/srv/apps/z2ui5_cl_smp_app_445.js @@ -2,7 +2,7 @@ // @summary Reads the sap.ui.Device model - phone, tablet or desktop, orientation and resize - so a view can react to the device it is on. // @docs https://abap2ui5.github.io/docs/cookbook/model/device_model https://abap2ui5.github.io/docs/cookbook/device_capabilities/info // @origin abap2UI5/samples src/z2ui5_cl_smp_app_445.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_445", class { diff --git a/srv/apps/z2ui5_cl_smp_app_448.js b/srv/apps/z2ui5_cl_smp_app_448.js index 4455e7a..144b793 100644 --- a/srv/apps/z2ui5_cl_smp_app_448.js +++ b/srv/apps/z2ui5_cl_smp_app_448.js @@ -2,7 +2,7 @@ // @summary Expands a Panel by calling setExpanded on it by ID - a whitelisted control call, no roundtrip and no model behind it. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_448.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_448", class { diff --git a/srv/apps/z2ui5_cl_smp_app_449.js b/srv/apps/z2ui5_cl_smp_app_449.js index 1d2cc7a..ee3e8b5 100644 --- a/srv/apps/z2ui5_cl_smp_app_449.js +++ b/srv/apps/z2ui5_cl_smp_app_449.js @@ -2,7 +2,7 @@ // @summary Opens the PDF viewer by calling it by ID, so a document can be shown from an event without rebuilding the view. // @docs https://abap2ui5.github.io/docs/cookbook/device_capabilities/pdf https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_449.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_449", class { diff --git a/srv/apps/z2ui5_cl_smp_app_450.js b/srv/apps/z2ui5_cl_smp_app_450.js index 6424afe..41ee31c 100644 --- a/srv/apps/z2ui5_cl_smp_app_450.js +++ b/srv/apps/z2ui5_cl_smp_app_450.js @@ -2,7 +2,7 @@ // @summary ABAP DATS and TIMS strings in the view: the conversion in both directions, including what an initial 00000000 has to become. // @docs https://abap2ui5.github.io/docs/cookbook/model/formatter // @origin abap2UI5/samples src/z2ui5_cl_smp_app_450.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_450", class { diff --git a/srv/apps/z2ui5_cl_smp_app_456.js b/srv/apps/z2ui5_cl_smp_app_456.js index 2145d1c..8e622f5 100644 --- a/srv/apps/z2ui5_cl_smp_app_456.js +++ b/srv/apps/z2ui5_cl_smp_app_456.js @@ -2,7 +2,7 @@ // @summary Appointments in a PlanningCalendar: start and end as date objects, which is what the control binds against. // @docs https://abap2ui5.github.io/docs/cookbook/model/formatter // @origin abap2UI5/samples src/z2ui5_cl_smp_app_456.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_appointment = { start_at: "", diff --git a/srv/apps/z2ui5_cl_smp_app_457.js b/srv/apps/z2ui5_cl_smp_app_457.js index 95e24d1..e2f545f 100644 --- a/srv/apps/z2ui5_cl_smp_app_457.js +++ b/srv/apps/z2ui5_cl_smp_app_457.js @@ -2,7 +2,7 @@ // @summary The DatePicker's dateValue wants a JavaScript date object rather than a string - what that means for the binding of an ABAP date. // @docs https://abap2ui5.github.io/docs/cookbook/model/formatter // @origin abap2UI5/samples src/z2ui5_cl_smp_app_457.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_457", class { diff --git a/srv/apps/z2ui5_cl_smp_app_460.js b/srv/apps/z2ui5_cl_smp_app_460.js index 0d48c13..8a32768 100644 --- a/srv/apps/z2ui5_cl_smp_app_460.js +++ b/srv/apps/z2ui5_cl_smp_app_460.js @@ -2,7 +2,7 @@ // @summary A nested ABAP table rendered as a sap.m.Tree - the hierarchy comes from the data, not from the view. // @docs https://abap2ui5.github.io/docs/cookbook/model/trees // @origin abap2UI5/samples src/z2ui5_cl_smp_app_460.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_node_level3 = { text: "", diff --git a/srv/apps/z2ui5_cl_smp_app_462.js b/srv/apps/z2ui5_cl_smp_app_462.js index 701c5f4..4366721 100644 --- a/srv/apps/z2ui5_cl_smp_app_462.js +++ b/srv/apps/z2ui5_cl_smp_app_462.js @@ -2,7 +2,7 @@ // @summary A tree inside a dialog, including which nodes stay expanded when the popup is opened again. // @docs https://abap2ui5.github.io/docs/cookbook/model/trees // @origin abap2UI5/samples src/z2ui5_cl_smp_app_462.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_node_level3 = { text: "", diff --git a/srv/apps/z2ui5_cl_smp_app_465.js b/srv/apps/z2ui5_cl_smp_app_465.js index 04721c1..e7b3be3 100644 --- a/srv/apps/z2ui5_cl_smp_app_465.js +++ b/srv/apps/z2ui5_cl_smp_app_465.js @@ -2,7 +2,7 @@ // @summary Opens and closes a Popover by ID (toggleBy), so the anchor decides and no roundtrip is needed. // @docs https://abap2ui5.github.io/docs/cookbook/popup_popover/popover https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_465.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_465", class { diff --git a/srv/apps/z2ui5_cl_smp_app_466.js b/srv/apps/z2ui5_cl_smp_app_466.js index e531aba..80fdf12 100644 --- a/srv/apps/z2ui5_cl_smp_app_466.js +++ b/srv/apps/z2ui5_cl_smp_app_466.js @@ -2,7 +2,7 @@ // @summary Puts icons inside a text through placeholders that UI5 expands, so a status line can carry a glyph without its own control. // @docs https://abap2ui5.github.io/docs/cookbook/model/formatter // @origin abap2UI5/samples src/z2ui5_cl_smp_app_466.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_466", class { diff --git a/srv/apps/z2ui5_cl_smp_app_467.js b/srv/apps/z2ui5_cl_smp_app_467.js index f2a2af0..e0b0a8d 100644 --- a/srv/apps/z2ui5_cl_smp_app_467.js +++ b/srv/apps/z2ui5_cl_smp_app_467.js @@ -2,7 +2,7 @@ // @summary The UI5 message model: validation messages carry the field they belong to, so the control shows the state and one list holds them all. // @docs https://abap2ui5.github.io/docs/cookbook/translation_messages/message // @origin abap2UI5/samples src/z2ui5_cl_smp_app_467.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_message = { message: "", diff --git a/srv/apps/z2ui5_cl_smp_app_469.js b/srv/apps/z2ui5_cl_smp_app_469.js index b1e3c4d..02ccf61 100644 --- a/srv/apps/z2ui5_cl_smp_app_469.js +++ b/srv/apps/z2ui5_cl_smp_app_469.js @@ -10,7 +10,7 @@ // restores this app from its draft and enters main( ) via // check_on_navigated( ) - the view must be rendered again there, or the // browser keeps showing the hub it navigated away from. -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_469", class { diff --git a/srv/apps/z2ui5_cl_smp_app_470.js b/srv/apps/z2ui5_cl_smp_app_470.js index 577c4ea..7b924e6 100644 --- a/srv/apps/z2ui5_cl_smp_app_470.js +++ b/srv/apps/z2ui5_cl_smp_app_470.js @@ -12,7 +12,7 @@ // popup's relative bindings - including its component list's aggregation binding - // resolve against the selected product. The row index arrives as the event arg // (the pressed control's binding-context path). -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_item = { name: "", diff --git a/srv/apps/z2ui5_cl_smp_app_472.js b/srv/apps/z2ui5_cl_smp_app_472.js index 809c282..bf7e6a6 100644 --- a/srv/apps/z2ui5_cl_smp_app_472.js +++ b/srv/apps/z2ui5_cl_smp_app_472.js @@ -2,7 +2,7 @@ // @summary A Link whose default browser action is suppressed (check_prevent_default), so the app handles the click instead of the href. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_472.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_472", class { diff --git a/srv/apps/z2ui5_cl_smp_app_473.js b/srv/apps/z2ui5_cl_smp_app_473.js index af2a003..199cd45 100644 --- a/srv/apps/z2ui5_cl_smp_app_473.js +++ b/srv/apps/z2ui5_cl_smp_app_473.js @@ -1,7 +1,7 @@ // @keywords menuitem nested submenu textpath controller path // @summary A nested Menu that reports the FULL path of the item that was chosen, not just its text. // @origin abap2UI5/samples src/z2ui5_cl_smp_app_473.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_473", class { diff --git a/srv/apps/z2ui5_cl_smp_app_474.js b/srv/apps/z2ui5_cl_smp_app_474.js index 50d82ce..b350e7e 100644 --- a/srv/apps/z2ui5_cl_smp_app_474.js +++ b/srv/apps/z2ui5_cl_smp_app_474.js @@ -2,7 +2,7 @@ // @summary The URL policy of a MessagePopover: which links it will follow and which it refuses, and why the default is the strict one. // @docs https://abap2ui5.github.io/docs/cookbook/translation_messages/message // @origin abap2UI5/samples src/z2ui5_cl_smp_app_474.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_474", class { diff --git a/srv/apps/z2ui5_cl_smp_app_488.js b/srv/apps/z2ui5_cl_smp_app_488.js index 711eb57..321a0db 100644 --- a/srv/apps/z2ui5_cl_smp_app_488.js +++ b/srv/apps/z2ui5_cl_smp_app_488.js @@ -9,7 +9,7 @@ // called it. On return this app enters main( ) via check_on_navigated( ) and // reads both from client->get( ): the event name from -event, the payload as a // data reference from -r_event_data. -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_488", class { diff --git a/srv/apps/z2ui5_cl_smp_app_489.js b/srv/apps/z2ui5_cl_smp_app_489.js index 143d7ab..960b112 100644 --- a/srv/apps/z2ui5_cl_smp_app_489.js +++ b/srv/apps/z2ui5_cl_smp_app_489.js @@ -4,7 +4,7 @@ // name and the entered data without knowing which app called it (no // get_app_prev( ), no cast to the caller's class). This app is a hidden // helper (never listed on its own in the overview). -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_result = { product: "", diff --git a/srv/apps/z2ui5_cl_smp_app_490.js b/srv/apps/z2ui5_cl_smp_app_490.js index a940f25..a1fbd59 100644 --- a/srv/apps/z2ui5_cl_smp_app_490.js +++ b/srv/apps/z2ui5_cl_smp_app_490.js @@ -9,7 +9,7 @@ // actions in order and awaits each build, so the anchor exists by the time // the popover opens. Also re-opens the popover TOGETHER with a view rebuild // on an event, and contrasts it with a popover alone (no view rebuild). -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_490", class { diff --git a/srv/apps/z2ui5_cl_smp_app_491.js b/srv/apps/z2ui5_cl_smp_app_491.js index 4feda9a..8512bce 100644 --- a/srv/apps/z2ui5_cl_smp_app_491.js +++ b/srv/apps/z2ui5_cl_smp_app_491.js @@ -2,7 +2,7 @@ // @summary Sets the browser tab's favicon at runtime, from an image the backend hands over as a data URI. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/title // @origin abap2UI5/samples src/z2ui5_cl_smp_app_491.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_491", class { diff --git a/srv/apps/z2ui5_cl_smp_app_492.js b/srv/apps/z2ui5_cl_smp_app_492.js index 3d545b1..bbe8d10 100644 --- a/srv/apps/z2ui5_cl_smp_app_492.js +++ b/srv/apps/z2ui5_cl_smp_app_492.js @@ -2,7 +2,7 @@ // @summary Navigates the browser to a same-domain URL with the location_reload front-end action, with a scratch input beside it to show what the reload takes with it. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/url_handling // @origin abap2UI5/samples src/z2ui5_cl_smp_app_492.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_492", class { diff --git a/srv/apps/z2ui5_cl_smp_app_493.js b/srv/apps/z2ui5_cl_smp_app_493.js index 33bd333..9f81928 100644 --- a/srv/apps/z2ui5_cl_smp_app_493.js +++ b/srv/apps/z2ui5_cl_smp_app_493.js @@ -2,7 +2,7 @@ // @summary The smallest app that runs: one class, one view_display( ), a Page with a title - the shape every other sample starts from. // @docs https://abap2ui5.github.io/docs/get_started/hello_world https://abap2ui5.github.io/docs/cookbook/view/definition https://abap2ui5.github.io/docs/cookbook/expert_more/snippets https://abap2ui5.github.io/docs/tutorials/walkthrough/step-1 // @origin abap2UI5/samples src/z2ui5_cl_smp_app_493.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_493", class { diff --git a/srv/apps/z2ui5_cl_smp_app_494.js b/srv/apps/z2ui5_cl_smp_app_494.js index bea35c9..c8d3680 100644 --- a/srv/apps/z2ui5_cl_smp_app_494.js +++ b/srv/apps/z2ui5_cl_smp_app_494.js @@ -2,7 +2,7 @@ // @summary Binds a class attribute to an Input with _bind( ), so what the user types is in the ABAP variable on the next roundtrip - a Text shows it back and a MessageBox confirms the roundtrip. // @docs https://abap2ui5.github.io/docs/cookbook/model/binding https://abap2ui5.github.io/docs/tutorials/walkthrough/step-4 // @origin abap2UI5/samples src/z2ui5_cl_smp_app_494.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_494", class { diff --git a/srv/apps/z2ui5_cl_smp_app_495.js b/srv/apps/z2ui5_cl_smp_app_495.js index 1d04751..65db711 100644 --- a/srv/apps/z2ui5_cl_smp_app_495.js +++ b/srv/apps/z2ui5_cl_smp_app_495.js @@ -2,7 +2,7 @@ // @summary The three questions main( ) asks - init, event, navigated - as one dispatcher, showing what survives a roundtrip and what a navigation does to it. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/life_cycle https://abap2ui5.github.io/docs/cookbook/expert_more/snippets https://abap2ui5.github.io/docs/tutorials/walkthrough/step-3 // @origin abap2UI5/samples src/z2ui5_cl_smp_app_495.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_step = { no: "", diff --git a/srv/apps/z2ui5_cl_smp_app_496.js b/srv/apps/z2ui5_cl_smp_app_496.js index c3958a9..b29658a 100644 --- a/srv/apps/z2ui5_cl_smp_app_496.js +++ b/srv/apps/z2ui5_cl_smp_app_496.js @@ -2,7 +2,7 @@ // @summary What Ctrl+F12 opens: the request and response payload, the generated XML view, the model, the source and the error log - the first place to look when something does not render. // @docs https://abap2ui5.github.io/docs/cookbook/troubleshooting/common_failures // @origin abap2UI5/samples src/z2ui5_cl_smp_app_496.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_tab = { name: "", diff --git a/srv/apps/z2ui5_cl_smp_app_498.js b/srv/apps/z2ui5_cl_smp_app_498.js index 9433da1..dcaf8ac 100644 --- a/srv/apps/z2ui5_cl_smp_app_498.js +++ b/srv/apps/z2ui5_cl_smp_app_498.js @@ -21,7 +21,7 @@ // cs_event-app_state_set_active: an empty argument list switches it on, a // single space is how the event form says false. Consolidates the former z2ui5_cl_smp_app_321 (bookmark) // and z2ui5_cl_smp_app_323 (share) into one sample. -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_498", class { diff --git a/srv/apps/z2ui5_cl_smp_app_499.js b/srv/apps/z2ui5_cl_smp_app_499.js index bf0c8c3..687fa74 100644 --- a/srv/apps/z2ui5_cl_smp_app_499.js +++ b/srv/apps/z2ui5_cl_smp_app_499.js @@ -33,7 +33,7 @@ // z2ui5_cl_smp_app_468 and z2ui5_cl_smp_app_480. Replaces the former // z2ui5_cl_smp_app_322, which pushed a suffix past the UI5 HashChanger and // had to reach for raw JavaScript to step back. -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_499", class { diff --git a/srv/apps/z2ui5_cl_smp_app_503.js b/srv/apps/z2ui5_cl_smp_app_503.js index c72a9e7..9fd98ba 100644 --- a/srv/apps/z2ui5_cl_smp_app_503.js +++ b/srv/apps/z2ui5_cl_smp_app_503.js @@ -1,7 +1,7 @@ // @keywords unit test abapunit testclasses assert testable logic method // @summary The app logic in a method of its own - no client, no attributes - so the local test class beside the class can assert it with ABAP Unit. // @origin abap2UI5/samples src/z2ui5_cl_smp_app_503.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_503", class { diff --git a/srv/apps/z2ui5_cl_smp_app_506.js b/srv/apps/z2ui5_cl_smp_app_506.js index 9bf194e..e398a9b 100644 --- a/srv/apps/z2ui5_cl_smp_app_506.js +++ b/srv/apps/z2ui5_cl_smp_app_506.js @@ -13,7 +13,7 @@ // check_arg_literal quotes every argument of that wire as a string, so the // wire gives up expressions and carries data. Two buttons over the same // argument show both readings side by side. -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_506", class { diff --git a/srv/apps/z2ui5_cl_smp_app_507.js b/srv/apps/z2ui5_cl_smp_app_507.js index c1bbbe4..37d62cb 100644 --- a/srv/apps/z2ui5_cl_smp_app_507.js +++ b/srv/apps/z2ui5_cl_smp_app_507.js @@ -13,7 +13,7 @@ // its enabled = false and becomes editable // - omit_initial_paths = MAXVALUE: only that column is omitted, the // boolean still travels, and both rows render as intended -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_row = { name: "", diff --git a/srv/apps/z2ui5_cl_smp_app_508.js b/srv/apps/z2ui5_cl_smp_app_508.js index 6a202e9..e5b31c1 100644 --- a/srv/apps/z2ui5_cl_smp_app_508.js +++ b/srv/apps/z2ui5_cl_smp_app_508.js @@ -10,7 +10,7 @@ // `_bind( val = quantity path = abap_true )` returns, under a name that // says what it does. It registers the attribute like every bind: a path // the view names must be in the model, or the client renders nothing. -import { defineApp, t, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; const ty_s_row = { product: "", diff --git a/srv/apps/z2ui5_cl_smp_app_509.js b/srv/apps/z2ui5_cl_smp_app_509.js index e3029d5..4a441c7 100644 --- a/srv/apps/z2ui5_cl_smp_app_509.js +++ b/srv/apps/z2ui5_cl_smp_app_509.js @@ -9,7 +9,7 @@ // a list binds to the array and a text to a member, and no ABAP structure // has to mirror keys that may not even be valid ABAP names. Outbound only: // the client sends nothing back into that node. -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_509", class { diff --git a/srv/apps/z2ui5_cl_smp_app_510.js b/srv/apps/z2ui5_cl_smp_app_510.js index a21e194..f3f31c6 100644 --- a/srv/apps/z2ui5_cl_smp_app_510.js +++ b/srv/apps/z2ui5_cl_smp_app_510.js @@ -11,7 +11,7 @@ // to ONE slot - cs_view-nested or cs_view-nested2 - so the focus is looked // for in the view the app meant and nowhere else: a slot that is not open // answers with nothing instead of the first match somewhere else. -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_510", class { diff --git a/srv/apps/z2ui5_cl_smp_app_511.js b/srv/apps/z2ui5_cl_smp_app_511.js index ea1afdc..29de25d 100644 --- a/srv/apps/z2ui5_cl_smp_app_511.js +++ b/srv/apps/z2ui5_cl_smp_app_511.js @@ -13,7 +13,7 @@ // Needs abap2UI5 newer than 1.144.0 - check_queue_last is appended to // ty_s_event_control after that release; on an older framework the class // does not activate (unknown component of s_ctrl). -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_511", class { diff --git a/srv/apps/z2ui5_cl_smp_app_513.js b/srv/apps/z2ui5_cl_smp_app_513.js index 078ef80..580c0d8 100644 --- a/srv/apps/z2ui5_cl_smp_app_513.js +++ b/srv/apps/z2ui5_cl_smp_app_513.js @@ -2,7 +2,7 @@ // @summary Writes a whitelisted CSS declaration onto a control's own DOM node with the css control method - for a value the control has no property for. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_513.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_513", class { diff --git a/srv/apps/z2ui5_cl_smp_app_514.js b/srv/apps/z2ui5_cl_smp_app_514.js index 1296029..9b59ce6 100644 --- a/srv/apps/z2ui5_cl_smp_app_514.js +++ b/srv/apps/z2ui5_cl_smp_app_514.js @@ -2,7 +2,7 @@ // @summary Jumps a Carousel to a page that was cloned from a bound template - addressed positionally as id/aggregation/index, the only way to reach a clone. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_514.clas.abap -import { defineApp, t, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, t, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; const ty_s_page = { title: "", diff --git a/srv/apps/z2ui5_cl_smp_app_515.js b/srv/apps/z2ui5_cl_smp_app_515.js index f6ec3f1..3c56034 100644 --- a/srv/apps/z2ui5_cl_smp_app_515.js +++ b/srv/apps/z2ui5_cl_smp_app_515.js @@ -2,7 +2,7 @@ // @summary Shows and hides the global BusyIndicator from ABAP through control_global - the singleton has no id, so a global target is the only wire that reaches it. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_515.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_515", class { diff --git a/srv/apps/z2ui5_cl_smp_app_516.js b/srv/apps/z2ui5_cl_smp_app_516.js index 05e277f..9b1ff67 100644 --- a/srv/apps/z2ui5_cl_smp_app_516.js +++ b/srv/apps/z2ui5_cl_smp_app_516.js @@ -2,7 +2,7 @@ // @summary Sets the HTML inputmode of an Input through the bound inputMode property of z2ui5.cc.InputExt - the keyboard layout is model data, not an action. // @docs https://abap2ui5.github.io/docs/cookbook/browser_interaction/soft_keyboard // @origin abap2UI5/samples src/z2ui5_cl_smp_app_516.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_516", class { diff --git a/srv/apps/z2ui5_cl_smp_app_518.js b/srv/apps/z2ui5_cl_smp_app_518.js index b0935b4..cfd7a84 100644 --- a/srv/apps/z2ui5_cl_smp_app_518.js +++ b/srv/apps/z2ui5_cl_smp_app_518.js @@ -2,7 +2,7 @@ // @summary Registers the sap.tnt icon collection with IconPool so a sap-icon://SAP-icons-TNT/... URI resolves - without it the icon renders no glyph and logs nothing. // @docs https://abap2ui5.github.io/docs/cookbook/event_navigation/frontend // @origin abap2UI5/samples src/z2ui5_cl_smp_app_518.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder, z2ui5_if_client } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_518", class { diff --git a/srv/apps/z2ui5_cl_smp_app_519.js b/srv/apps/z2ui5_cl_smp_app_519.js index 5543bac..c315e30 100644 --- a/srv/apps/z2ui5_cl_smp_app_519.js +++ b/srv/apps/z2ui5_cl_smp_app_519.js @@ -2,7 +2,7 @@ // @summary Puts the screen texts in the class's own text elements instead of an i18n file, so SE63 translates them and the app shows them in the logon language. // @docs https://abap2ui5.github.io/docs/cookbook/translation_messages/translation_i18n // @origin abap2UI5/samples src/z2ui5_cl_smp_app_519.clas.abap -import { defineApp, z2ui5_cl_ui5_view_builder } from "cap2ui5"; +import { defineApp, z2ui5_cl_ui5_view_builder } from "@cap2ui5/cds-plugin"; defineApp("Z2UI5_CL_SMP_APP_519", class {