Skip to content

Client API reference, a decision-first install journey, and walkthrough steps 11–12 - #177

Merged
oblomov-dev merged 10 commits into
mainfrom
claude/abap2ui5-repo-structure-x5dnfl
Aug 22, 2026
Merged

Client API reference, a decision-first install journey, and walkthrough steps 11–12#177
oblomov-dev merged 10 commits into
mainfrom
claude/abap2ui5-repo-structure-x5dnfl

Conversation

@oblomov-dev

Copy link
Copy Markdown
Member

Seven commits closing the site's largest gaps for both audiences:

Infrastructure

  • Client API reference, generateddocs/resources/api.md (sidebar: Resources → Client API) plus a fetchable docs/public/api/client-api.json, both generated from z2ui5_if_client at the pinned release (37 methods with parameters/defaults/ABAP-Doc, cs_* constant structures, obsolete badges). Acquisition/parsing shared with check-api-names.mjs so the two gates cannot drift. Wired as the seventh check (check:api-reference) in npm run check, check.yml and deploy.yml; llms.txt picks the page up automatically from the sidebar. The new parser also exposed and fixed a real bug in check-api-names.mjs: nested constant group names like cs_device-system-phone were wrongly rejected (1543 → 1628 validated names).
  • Committed root llms.txt pointer — a clone previously contained no AI index at all (generated ones are gitignored). The pointer names the published URLs (llms.txt, llms-full.txt, per-page .md, client-api.json); rationale for not committing the generated files documented in AGENTS.md.
  • README check-count fix (five → six, now seven).

Content

  • Quickstart, decision-first — one choice up front (browser playground → live demo → own system), then a numbered end-to-end install journey: release pull, the four frontend delivery branches explained (and why the basic install needs none), HTTP handler, first ?app_start= call, and an explicit Verify step with the framework's literal error text and the VS Code extension's new "Check System Connection" command as the diagnosis tool.
  • Common Failures as an error index — 13 message → cause → fix entries; every message grepped from the framework source or taken from documented real cases, nothing invented.
  • Walkthrough steps 11–12 — "From Playground to Production" (transport/productive-usage/security in journey order, invoice app as the running example) and "Unit Tests" (step 10's class unchanged plus a DEFERRED/LOCAL FRIENDS ABAP Unit include, compiled separately against 1.143.0 with the gate's exact abaplint setup).
  • Flywheel paragraph on the contribution page: second-time questions become a Common Failures entry, a docs paragraph, or a check.

All seven checks green before each commit (53 app-class examples compiled, 1669 API names validated). Part of an ecosystem-wide pass; no cross-repo merge dependency.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45


Generated by Claude Code

claude added 7 commits August 21, 2026 16:00
The sixth gate arrived with dc7c799 and was written into AGENTS.md and the
check chain, but the README kept counting five — so the file most people read
first described a smaller CI than the one their pull request has to pass, and
the one gate it left out is the one that fails without anybody touching this
repository. Count six, and name check:api-names in the list so the prose
matches package.json again.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
Every abap2UI5 app is written against one interface - z2ui5_if_client, handed
to the app as `client` on every roundtrip - and no page anywhere listed it.
The interface carries nearly two hundred ABAP-Doc lines on its methods,
parameters and constants, and the only way to read any of it was to open the
source file; a reader asking "what can client-> do" reversed the answer out of
cookbook examples, and an agent fell back on training data.

So the reference is GENERATED, the way the Working Samples blocks are, because
a hand-written API page is wrong the release after it is written:

  scripts/generate-api-reference.mjs   parses the interface at the release the
      site names - methods with parameter types, defaults and preferred
      parameters, the cs_* constant structures with their values and run
      labels, the types, and the ABAP-Doc on all of them - and writes two
      committed artefacts:

  docs/resources/api.md                the page, between api:start/end markers
      like every other generated block; the intro around them is hand-written.
      Methods are grouped by the interface's own prefixes (view_*, nest*,
      popup_*/popover_*, _bind*, message_*, ...), obsolete methods carry a
      badge derived from their own doc. In the sidebar under Resources, which
      also puts it into the generated llms.txt automatically.

  docs/public/api/client-api.json      the same model as one JSON document, so
      AI tooling fetches one URL instead of parsing a page. Committed, unlike
      llms.txt: it is a claim about another repository at a pinned release,
      not a projection of the pages next to it - the samples-block case.

check:api-reference is the freshness gate - regenerate and compare, fail on a
difference, SKIP honestly when github.com is unreachable - wired into npm run
check, check.yml and deploy.yml the way the other six are, making it seven.

The acquisition moved into scripts/lib/client-interface.mjs, shared with
check-api-names so the two gates cannot drift on where the truth comes from.
And the generated page caught a real gap in that gate on its first run:
`cs_device-system-phone` - the full path exactly as an app spells it - was
rejected, because the parser never registered a nested group (`system`) as a
member of its parent, despite its own comment claiming that spelling resolves.
It does now.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
The three machine-readable artefacts - llms.txt, llms-full.txt, the per-page
markdown - are generated at build time and gitignored, and that stays right:
they are a projection of the pages next to them, so the only correct copy is
the one the build just made, and a committed copy would be stale on every
commit that touches a page. But it leaves a blind spot this repository itself
documents caring about: the agent that lands in a CHECKOUT rather than on the
site finds neither file and has no way to learn they exist.

So the root gets a committed llms.txt that is a pointer and nothing else - the
published URLs of the generated files and of client-api.json, plus one line on
where the sources live. It is maintained by hand because it names URLs, not
content, and it needs no freshness gate for the same reason. Committing the
generated files instead was considered and rejected in AGENTS.md, where the
distinction between a projection (build-time, gitignored) and a claim about
another repository (committed, gated) was already the rule.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
…y step

Two no-system paths existed - the playground behind every Run button and the
transpiled live demo - but the page opened mid-install, with the live demo in
a tip and the playground nowhere. Now the reader meets one decision before
any step: try it in the browser, explore the live demo, or install on your
own system - and only the third continues down the page.

The install itself becomes an end-to-end journey: pull a release rather than
main, know that the endpoint serves the frontend itself (with the four
delivery branches of abap2UI5/frontend named for the scenarios that do deploy
one), learn ?app_start= as the URL form everything else uses, and finish on
an explicit Verify step - what you should see, and for each wrong outcome the
place that explains it, from an inactive SICF node to the framework's own
"The app '...' does not exist in the system." The VS Code extension's
"Check System Connection" command is named there as the step-by-step
diagnosis, and the extension page now documents that command where the
launch URL is explained.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
The page explained ten failures by behavior - nothing renders, data does not
update - which helps when you know what you did. When all you have is a
literal error text, you need the other direction. The new index maps each
message to its cause and fix: the framework's own raised texts (the binding
errors, APP_SERIALIZATION_ERROR, the dispatch limit, the app that "does not
exist in the system"), the browser-side ones (failed module loads, the empty
string no UI5 enum accepts, the CSP EvalError, ICFEUCONFORBIDDEN), the
abapGit import that leaves an empty class stub behind, and the icon that
disappears without a word. Every text was verified against the framework
source or a documented real case - none invented.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
Step 10 refactored the invoice app and stopped; transport, security and
testing existed only as configuration pages nothing guided you through. Two
steps finish the arc. Step 11, From Playground to Production, takes the
finished app to a real system by walking the existing chapters in journey
order - the two data seams become real SQL, the framework gets pinned to a
release, the transport goes bottom-up so a failure names its layer,
authorization is placed at the service and in the app, and users get the
?app_start= URL as tile or bookmark - the chapters keep the details, the step
provides the order. Step 12 collects what Step 10's structure promised: the
data methods are plain ABAP, so the test class is ordinary ABAP Unit -
DEFERRED, LOCAL FRIENDS (an activation error when missing, not a style
issue), three tests through the same public attributes the view binds. Its
app class is Step 10's, reprinted so the step stands alone and stays under
check:examples; the test include was compiled against 1.143.0 with the same
abaplint setup the gate uses. Overview, sidebar and the two step-count
sentences follow, and the AGENTS.md button ledger records the reprinted
class: 61 complete classes, 39 with a button.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
The samples repositories run on a distillation rule - every fix found by
hand becomes a rule, a reference example or a gate, so nobody discovers it
twice. The contribution page now says the reader-facing half of the same
discipline: a question answered twice on Slack or in an issue wants to
become a Common Failures entry, a paragraph on the page that should have
answered it, or a check.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
Copilot AI lite review requested due to automatic review settings August 21, 2026 16:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

claude added 3 commits August 21, 2026 17:11
…out is

The figures in llms.txt were counted from sibling checkouts and silently
left out when none was at hand - and a checkout step that is
continue-on-error, or a workflow with no sample repository at all, is
exactly the build that publishes the copy agents actually fetch. So the
published file could carry no corpus sizes while every local build showed
them.

Each sample repository now commits the same catalogue as one JSON document,
catalogue.json at its root. countCatalogue walks a chain, first answer
wins: the checkout's catalogue.json, the checkout's SAMPLES.md through the
parser the sample links go through, the catalogue.json the repository
publishes on its default branch (fetched), then no number. The two
catalogue.json steps read the same file, so a build with a checkout and a
build without one publish the same figure - which is also why, inside a
checkout, catalogue.json outranks the SAMPLES.md parse: in samples the two
genuinely differ (SAMPLES.md also lists the src/00 system area and the
helpers; catalogue.json scopes itself to the portable src/01 set), and the
repository's own claim about itself is the one figure both paths can agree
on. The samples figure therefore reads 97 now, not 150, on both paths.

The discipline survives the new source: every step counts entries - a
class name plus a file pointer, the JSON shape of the row the SAMPLES.md
parser accepts - and never repeats a counts field, whose fixtures here
deliberately lie to prove it. The fetch may 404 (the file is not on main
until the sibling PRs merge), time out or find no network; each failure
costs the figure and never the build. generate-llms.mjs counts once per
repository and logs which source answered, so a figure that arrived from
the fallback when a checkout was expected is visible in the run output.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
The dispatcher skeleton on the life-cycle page declared render_main and
on_post and implemented neither, so the most-copied pattern in the
cookbook was a class that does not activate in any system — and the one
complete app example on the page the Run button could never reach,
because the playground rules rightly refuse a class that does not
compile as printed.

Implementing the two methods costs 27 lines and buys three things: the
example now compiles under check:examples like every other view-building
class, the page demonstrates the "one render method per view" rule it
preaches instead of only naming it, and the fence gets its Run button.
Verified in a served playground build end to end: the app starts, the
view renders, and typing into the input and pressing Post produces
"POST received: <the typed value>" — the whole lifecycle the page is
about, watched working.

The fixture pinning the declared-and-never-implemented shape stays; its
comment now records that the page it was watched failing on has been
completed, rather than pointing readers at a defect that no longer
exists.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
… it so

The playground rules fail towards no button, which is right for the
reader and wrong for the maintainer: an example nobody ever measured
looks exactly like an example that can never run. The ledger keeping
those apart lived as two numbers in AGENTS.md — "61 app classes, 39
with a button" — and had already drifted to 68 and 46 without a word
changing, because prose is where bookkeeping goes to go stale.

Measured first: of the 21 buttonless complete app classes (after the
life-cycle page was completed), every one is buttonless for a reason a
browser cannot fix — VBAK, SFLIGHT, SCARR and KNA1 SELECTs, EML against
CDS entities, ENQUEUE function modules, cl_bcs_message and
cl_demo_output, a DDIC lookup, a class-local class, an add-on
interface, and one authority check that deliberately shows nothing.

So the exclusions become explicit. Each of the 21 now carries a marker
directly above its fence —

  <!-- playground: no Run button — SELECTs from VBAK, which no browser database has -->

— and check:playground, the eighth gate, refuses a complete app class
with neither button nor marker, a marker above an example that HAS a
button, and a marker attached to nothing, so intent can neither be
omitted nor outlive a fix. --list prints every exclusion with both
reasons, which is the worklist for the next real measurement.
scripts/lib/playground-coverage.mjs holds the audit,
test/playground-coverage.test.mjs pins one fixture per verdict, and
check.yml and deploy.yml run the gate so it exists for pull requests,
not just for whoever reads package.json.

What stays hand-measured is stated rather than implied: whether a
BUTTONED example actually starts, which only a playground answers. Six
were driven in a served build this round — the newly buttoned
life-cycle class through its whole event roundtrip, quickstart, About,
Step 12, the tables page and the t100 SELECT — and all six started and
rendered. AGENTS.md's ledger now carries the measured figures the gate
reprints on every run: 68 app classes, 47 with a button, 21 excluded on
purpose.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLKJKRzJ6gYAM6i9Bjyt45
@oblomov-dev
oblomov-dev merged commit 13333f5 into main Aug 22, 2026
1 check passed
@oblomov-dev
oblomov-dev deleted the claude/abap2ui5-repo-structure-x5dnfl branch August 22, 2026 00:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants