@open-rap/compiler 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/AGENTS.md CHANGED
@@ -9,7 +9,7 @@ writes an `AGENTS.md` in the projects it creates.
9
9
  A TypeScript compiler (pnpm monorepo) that turns the sources of a RAP BO (abapGit format) into a
10
10
  Node.js application: OData V4, RAP managed runtime, ABAP transpiled by abaplint, PostgreSQL,
11
11
  OpenUI5 UI. Read [README.md](README.md), [docs/GUIDE.md](docs/GUIDE.md) and the list of decisions
12
- [docs/DECISIONS.md](docs/DECISIONS.md) (D1 to D71) first.
12
+ [docs/DECISIONS.md](docs/DECISIONS.md) (D1 to D78) first.
13
13
 
14
14
  ```
15
15
  packages/model/ types of the IR (model.json) and shared derivations (OData, value helps, MCP)
@@ -37,6 +37,8 @@ npx vitest run packages/compiler/test/ui.test.ts # one file
37
37
  node packages/compiler/dist/cli.js check fixtures/travel
38
38
  node packages/compiler/dist/cli.js dev fixtures/travel --port 8081
39
39
  node scripts/build-site.mjs _site # the website, with the documentation pages
40
+ pnpm changeset # the changeset of a pull request: the bump and its line in the changelog (D77)
41
+ pnpm check:version # one version in every file that carries it
40
42
  ```
41
43
 
42
44
  The runtime tests import the built `@open-rap/compiler`: run `pnpm build` before running them
@@ -64,6 +66,11 @@ after a change to the compiler.
64
66
  names, pull requests (title, description, review comments), issues and release notes.
65
67
  9. **Generated files**: never edit `.rapt/`, `dist/`, `packages/compiler/docs/`, nor the virtual
66
68
  objects `<standard>/…` (standard views, D44).
69
+ 10. **Versions** (D77): never change a version by hand. A pull request that changes what ships
70
+ (sources of a package, `docs/`, the dependencies of a published package) adds a changeset
71
+ (`pnpm changeset`: `patch` for a fix, `minor` for a feature; one line in English for the
72
+ changelog), or `pnpm changeset add --empty` when it must not be released; the CI checks it.
73
+ The *Version packages* pull request bumps the versions, its merge releases.
67
74
 
68
75
  ## Adding a feature, in practice
69
76
 
package/docs/DECISIONS.md CHANGED
@@ -1321,7 +1321,9 @@ correspond to points 1 to 13 of §11 of PLAN.md. The milestones M1 to M6 are tho
1321
1321
  runs `rapt --help`, `rapt check` and `rapt build` of the fixture; then, when the secret
1322
1322
  `NPM_TOKEN` is set, publishes them (`workspace:*` becomes the version of the tag). npm
1323
1323
  provenance is added when the repository is public. Once: create the `open-rap-runtime`
1324
- organization on npmjs.com and the `NPM_TOKEN` secret ([DEPLOYMENT.md](DEPLOYMENT.md)). The name
1324
+ organization on npmjs.com and the `NPM_TOKEN` secret ([DEPLOYMENT.md](DEPLOYMENT.md)).
1325
+ *Since D77 and D78: the version is the committed one, and npm trusts the workflow by trusted
1326
+ publishing, without `NPM_TOKEN`.* The name
1325
1327
  `rapt` is taken on npm, hence `open-rap-runtime`.
1326
1328
  - **Why**: the same CLI everywhere; CI can check RAP sources without VS Code; a terminal agent
1327
1329
  can install it in one command.
@@ -1505,6 +1507,8 @@ correspond to points 1 to 13 of §11 of PLAN.md. The milestones M1 to M6 are tho
1505
1507
 
1506
1508
  ## D71 — Feedback: a public feedback repository and a form on the website
1507
1509
 
1510
+ _The issues moved to the repository itself once public: see D74._
1511
+
1508
1512
  - **Context**: the repository is private, so its issues are not open to the users; bug reports
1509
1513
  and feature requests had no place.
1510
1514
  - **Decision**: a public repository, `ClementRingot/open-rap-runtime-feedback`, holds the issues,
@@ -1552,3 +1556,175 @@ correspond to points 1 to 13 of §11 of PLAN.md. The milestones M1 to M6 are tho
1552
1556
  - **Tests**: `vscode/test/rapt.test.ts` (name of a project in the prompts, applications of the
1553
1557
  workspace, URL of the feedback form); a launchpad of three projects (one already built, two without floorplan) under a folder
1554
1558
  with an accent built by `rapt launchpad` in 2 s.
1559
+
1560
+ ## D73 — The missing abapGit files are written before a build in VS Code
1561
+
1562
+ - **Context**: a project written by hand or by an AI agent can lack its abapGit files
1563
+ (`.abapgit.xml`, the XML of the objects): `rapt build` does not need them, but the sources then
1564
+ do not import into an SAP system with abapGit, which is the purpose of the project.
1565
+ - **Decision**: *Build the application* (standalone or launchpad) and *Build the launchpad* run
1566
+ `rapt abapgit` on each application before building it: the missing files are written, the
1567
+ existing ones are kept. The written files are listed in the log of the extension and announced
1568
+ in a message; the objects that cannot be completed (a table without source) are logged; a
1569
+ failure does not stop the build. The command line (`rapt build`, `rapt launchpad`) writes
1570
+ nothing into the sources: in a terminal or a CI, `rapt abapgit` is run explicitly.
1571
+ - **Why**: the build of the extension is the moment the user hands the application over; the
1572
+ sources that go with it must be importable as they are.
1573
+ - **Tests**: `vscode/test/rapt.test.ts` (missing files written, existing files kept, a second run
1574
+ writes nothing).
1575
+
1576
+ ## D74 — The repository is public: feedback goes to its own issues
1577
+
1578
+ - **Context**: the repository `ClementRingot/Open-RAP-Runtime` becomes public, so its issues are
1579
+ open to the users; the separate feedback repository of D71 is no longer needed.
1580
+ - **Decision**: the feedback form of the website (and so the VS Code command *RAP: Report a bug
1581
+ or request a feature…*) opens a pre-filled issue in the repository itself, with the same issue
1582
+ forms, now in `.github/ISSUE_TEMPLATE` (bug report, feature request; blank issues disabled).
1583
+ The npm packages give the repository and its issues (`repository`, `bugs`). The repository
1584
+ `open-rap-runtime-feedback` points to the new place; its issues stay readable. The rest of D71
1585
+ holds (fields filled from the query string, version and environment from the extension).
1586
+ - **Tests**: `compiler/test/docs.test.ts` (no link to the former name of the repository).
1587
+
1588
+ ## D75 — The launchpad of the workspace in development
1589
+
1590
+ - **Context**: `rapt dev` runs one application with its development launchpad (D49); with several
1591
+ applications in a workspace (D69), the launchpad with all of them only existed as a build
1592
+ (`rapt launchpad`, then Docker). The commands of the extension were also active when they could
1593
+ not work (open the application before it serves, stop without a session).
1594
+ - **Decision**: `rapt launchpad dev <launchpad.json> [--port 8090] [--host] [--json]` starts a
1595
+ `rapt dev` session for each application with `source`, on the port of its `url`, and serves the
1596
+ launchpad (its configuration resolved from the models of the sessions) on port 8090. The
1597
+ launchpad waits until every application is built, then follows their rebuilds; a change of
1598
+ `launchpad.json` adds, removes or restarts the sessions and regenerates the launchpad. Checks
1599
+ (LPD010): an application with `build` is not started (warning); a URL that is not local or
1600
+ without a port, a port taken twice or by the launchpad, no application with sources are errors.
1601
+ The files go to `.rapt/launchpad` next to `launchpad.json`. In VS Code, *RAP: Start the
1602
+ launchpad (rapt dev, all the applications)* (palette, context menu and title bar of
1603
+ `launchpad.json`, view of the RAP objects) asks for the missing floorplans then runs it. The
1604
+ extension keeps a single session: starting an application or the launchpad stops the other,
1605
+ since both use the same `.rapt/dev` and ports. Context keys `rapt.devRunning`, `rapt.devReady`
1606
+ and `rapt.devMode` grey out *Open the application* until the session serves and *Stop* without
1607
+ a session; the launchpad commands need an application or a `launchpad.json`
1608
+ (`rapt.hasApp || rapt.hasLaunchpad`). The roots of the sessions are real paths (no Windows 8.3
1609
+ short name, which `fs.watch` does not support). The regenerations run one at a time; one that
1610
+ throws (a file that cannot be written) is reported (`launchpad-failed`) and the next change of
1611
+ `launchpad.json` or of an application tries again.
1612
+ - **Why**: the launchpad is how the applications of a workspace are used together (navigation,
1613
+ counters); developing them one at a time hides the result, and Docker is too slow for each save.
1614
+ - **Tests**: `compiler/test/launchpad-dev.test.ts` (plan and LPD010, an application behind the
1615
+ launchpad, regeneration on a change of `launchpad.json`, ports freed on close, a launchpad that cannot be
1616
+ written then generated on the next change),
1617
+ `vscode/test/rapt.test.ts` (context keys, arguments of the sessions).
1618
+
1619
+ ## D76 — A Web API or a Fiori application: chosen at the creation, kept out of the launchpad
1620
+
1621
+ - **Context**: what makes a service a Web API is the type of its service binding (*OData V4 -
1622
+ Web API*, `BINDING_TYPE_CATEGORY` 1, D60). `rapt new` and *New complete business object…* only
1623
+ created UI bindings; a Web API was made by hand (`rapt generate binding --binding-type
1624
+ webapi`) and was then added to the launchpad like an application: a tile with no UI behind it,
1625
+ and a floorplan asked for nothing. A service with both a UI and a Web API binding, common on
1626
+ SAP, built the first one found (SRVD002).
1627
+ - **Decision**: the type of the binding stays the only source of truth, as on SAP; it is chosen
1628
+ at the creation and respected everywhere.
1629
+ - **Creation**: `rapt new <src> <Entity> --binding-type webapi` (VS Code: *New complete
1630
+ business object…* asks "Fiori application (UI)" or "Web API" first; `rapt agent`:
1631
+ `bindingType` of `rapt_new_business_object`) writes the service and binding with the names
1632
+ of SAP for an API (`ZRT_API_TRAVEL`, `ZRT_API_TRAVEL_O4`, category 1), no metadata extension
1633
+ (nor `@Metadata.allowExtensions`), and does not add the project to the launchpad.
1634
+ - **Launchpad**: `rapt launchpad add` (and the extension, which adds the applications of the
1635
+ workspace before building or starting the launchpad) leaves a Web API out: `webApi: true`,
1636
+ `added: false`, no error, `launchpad.json` not created for it. A tile of `launchpad.json` on
1637
+ a Web API is left out of the launchpad with the warning **LPD011**; the application itself
1638
+ can stay in `apps` (built and served behind the launchpad, at its service path).
1639
+ - **Floorplan**: `rapt floorplan` lists no entity set for a Web API (`webApi: true`), and
1640
+ refuses to set one; the extension says so instead of asking.
1641
+ - **Two bindings**: `--binding <name>` designates one of the bindings of the service (its type
1642
+ with it); without it, the UI binding is preferred over the Web API ones, with SRVD002 as an
1643
+ info naming the other one; several UI bindings remain a SRVD002 warning.
1644
+ - **RAP Objects view**: each service binding shows its kind, `UI` or `Web API`.
1645
+ - **A binding alone**: the catalog of `rapt generate` gives each value of `--binding-type` its
1646
+ meaning (`labels`: "UI: a Fiori application, in the launchpad", "Web API: for other systems,
1647
+ without UI, not in the launchpad"), shown by the wizard *New RAP object…*, whose *Complete
1648
+ business object* also asks it (*Service*). The quick picks (*New RAP object (quick
1649
+ picks)…*) ask the type of a binding too. The proposed name follows the service definition
1650
+ and the type, as SAP names them (`ZRT_UI_TRAVEL` → `ZRT_UI_TRAVEL_O4` or
1651
+ `ZRT_API_TRAVEL_O4`, `ZUI_ORDER` → `ZAPI_ORDER_O4`), until the user types one.
1652
+ - **Why**: the choice is made where the developer thinks about it (what is the service for?),
1653
+ the result activates on SAP as is, and the launchpad never shows a tile that cannot open.
1654
+ - **Tests**: `compiler/test/web-api-app.test.ts` (names, files, model, floorplan, rapt new and
1655
+ rapt launchpad add, LPD011, the choice between two bindings), `compiler/test/agent.test.ts`
1656
+ (`bindingType`), `vscode/test/rapt.test.ts` (arguments of rapt new and of the wizard, names of
1657
+ a binding, kind of a binding, notice), `vscode/test/wizard.test.ts` (the page of the wizard in
1658
+ a browser: labels, proposed names, answers).
1659
+
1660
+ ## D77 — Versions and releases by Changesets
1661
+
1662
+ - **Context**: a release meant changing the version by hand in seven files (the five
1663
+ `package.json`, `RUNTIME_VERSION`, the generator of the reference snapshot), then running the
1664
+ Release workflow with the same version; nothing tied a change to its version, and there was no
1665
+ changelog. LISA, another repository of the maintainer, releases with Changesets.
1666
+ - **Decision**: [Changesets](https://github.com/changesets/changesets) (`@changesets/cli`, MIT),
1667
+ as in LISA, with one version for the five packages (a `fixed` group; the VS Code extension is
1668
+ private: versioned, never published to npm by Changesets).
1669
+ - **Each pull request** that changes what ships adds a changeset (`pnpm changeset`). What
1670
+ ships (`scripts/lib/versions.mjs`): the sources of a package (not its tests), the grammars
1671
+ and build scripts of the extension, `docs/` (copied into the compiler), the installed fields
1672
+ of a published `package.json` (dependencies, `bin`, `exports`, `contributes`…). The CI
1673
+ refuses a pull request without one (`scripts/require-changeset.mjs`); `pnpm changeset add
1674
+ --empty` declares a change that must not be released; the Version packages pull request,
1675
+ and a pull request that bumps the version itself, are exempt.
1676
+ - **On `main`**, the *Changesets* workflow (`changesets/action`) keeps the *Version packages*
1677
+ pull request up to date: `pnpm changeset:version` bumps the packages, writes their
1678
+ `CHANGELOG.md`, copies the version into the files that carry it
1679
+ (`scripts/sync-versions.mjs`), updates the lockfile and checks the result.
1680
+ - **Its merge releases**: without pending changesets, `scripts/release-version.mjs` tags the
1681
+ committed version `vX.Y.Z` on the merge commit (when not tagged yet, nor being released) and
1682
+ runs `release.yml` on the tag. Unlike LISA, no GitHub App is needed for that: the tag is
1683
+ created with the `GITHUB_TOKEN` (it does not start the tag trigger, so no second run) and the
1684
+ `workflow_dispatch` it sends does start the workflow. An optional App gives the CI to the
1685
+ Version packages pull request.
1686
+ - **One version everywhere**: `pnpm check:version` (CI) fails on a drift; `release.yml` checks
1687
+ that the tag is the committed version instead of writing the version at release time. The
1688
+ notes of the GitHub release are the sections of the version in the changelogs, merged
1689
+ (`scripts/release-notes.mjs`).
1690
+ - **Why**: the only human step of a release is merging a pull request that shows the version and
1691
+ its changelog; a change cannot be merged without saying whether and how it is released; the
1692
+ version can no longer differ between the files.
1693
+ - **Tests**: `scripts/lib/versions.test.mjs` (the files of the version, `sync-versions.mjs` and
1694
+ `check-version-sync.mjs` with a tag, what ships, changesets, the notes merged from several
1695
+ changelogs); `changeset version` checked on a copy of the repository (the five packages bumped
1696
+ together, the mirrors copied).
1697
+
1698
+ ## D78 — Publishing without tokens: trusted publishing
1699
+
1700
+ - **Context**: `release.yml` published with three long-lived secrets (`NPM_TOKEN`, `VSCE_PAT`,
1701
+ `OVSX_PAT`). A stolen token publishes anything, until someone revokes it; the tokens also
1702
+ expire and have to be renewed. LISA already publishes to npm by trusted publishing.
1703
+ - **Decision**: every registry trusts the workflow `release.yml` of this repository by OIDC;
1704
+ the jobs have `id-token: write` and no secret.
1705
+ - **npm**: npm 11.21.1 (trusted publishing needs 11.5.1 or later; Node.js 22 comes with npm
1706
+ 10), without `registry-url` in `setup-node` (it writes an `.npmrc` waiting for a token).
1707
+ The four archives already checked (`pnpm pack`: `workspace:*` replaced by the version) are
1708
+ published by `npm publish <archive>`: npm exchanges the identity token, pnpm does not. The
1709
+ provenance is attested automatically. A version already on npm is skipped.
1710
+ - **Visual Studio Marketplace**: `vsce publish --oidc` (`@vscode/vsce` 4.1.0, which also builds
1711
+ the `.vsix`), with `--skip-duplicate`; the publisher declares a Trusted Publishing policy. The
1712
+ extension is published by the publisher `abaper` of the maintainer (it was `clementringot`
1713
+ in `package.json`, a publisher that does not exist on the Marketplace): its ID becomes
1714
+ `abaper.open-rap-runtime-vscode`.
1715
+ - **Open VSX**: `ovsx publish --trusted-publishing` (`ovsx` 1.3.0, run by `npx` in the CI
1716
+ only: EPL-2.0, never distributed), with `--skip-duplicate`; the namespace `abaper` declares
1717
+ its trusted publisher.
1718
+ - The Marketplace and Open VSX steps run when the repository variables
1719
+ `PUBLISH_VS_MARKETPLACE` and `PUBLISH_OPEN_VSX` are `true`, so that a release does not fail
1720
+ before their trusted publisher is declared. npm and the GitHub release always run.
1721
+ - The only stored credential left is the private key of the GitHub App of the release train
1722
+ (D77), which only opens the Version packages pull request.
1723
+ - **Why**: nothing to steal nor to renew; a version can only come from this workflow on this
1724
+ repository, which the npm provenance shows; the release can be re-run (each registry skips a
1725
+ version it has).
1726
+ - **Tests**: the `.vsix` built with `@vscode/vsce` 4.1.0 (the embedded `rapt` checks the
1727
+ fixture); the options `--oidc` (`vsce`) and `--trusted-publishing` (`ovsx`) checked in the help
1728
+ of the pinned versions; the workflow runs on the next release (npm needs its trusted publisher
1729
+ declared first, [DEPLOYMENT.md](DEPLOYMENT.md)).
1730
+
@@ -86,28 +86,72 @@ HTTPS address.
86
86
 
87
87
  ## Publishing a version of Open RAP Runtime (maintainers)
88
88
 
89
- A tag `v1.2.3` runs `release.yml`: the VS Code extension (GitHub release, Marketplace with the
90
- `VSCE_PAT` secret, Open VSX with `OVSX_PAT`) and the CLI on npm ([D65](DECISIONS.md)):
91
- `open-rap-runtime` (the `rapt` command), `@open-rap/model`, `@open-rap/compiler` and
92
- `@open-rap/runtime`, all in version 1.2.3.
93
-
94
- Once, for npm:
95
-
96
- 1. Create the organization **`open-rap`** on npmjs.com (free for public packages): it
97
- holds the `@open-rap` scope.
98
- 2. Create a *Granular Access Token* (*Read and write*, packages `open-rap-runtime` and scope
99
- `@open-rap`, or the whole organization) and save it as the **`NPM_TOKEN`** secret of the
100
- repository (*Settings → Secrets and variables → Actions*).
101
-
102
- Without `NPM_TOKEN`, the `npm` job builds and checks the packages (archives of `pnpm pack`
103
- installed by npm, `rapt check` and `rapt build` of the fixture) but publishes nothing. npm
104
- provenance (the link between the package and the workflow) is added when the repository is
105
- public.
89
+ The versions are managed by [Changesets](https://github.com/changesets/changesets)
90
+ ([D77](DECISIONS.md)). The five packages — `open-rap-runtime` (the `rapt` command),
91
+ `@open-rap/model`, `@open-rap/compiler`, `@open-rap/runtime` and the VS Code extension — share
92
+ one version.
93
+
94
+ 1. **Each pull request** that changes what ships (the sources of a package, `docs/`, the
95
+ dependencies of a published package) adds a changeset: `pnpm changeset`, the bump (`patch`
96
+ for a fix, `minor` for a feature, `major`) and one line for the changelog. A change that must
97
+ not be released records it with `pnpm changeset add --empty`. The CI refuses a pull request
98
+ without one (`scripts/require-changeset.mjs`).
99
+ 2. **On `main`**, the *Changesets* workflow (`.github/workflows/changesets.yml`) keeps a
100
+ *Version packages* pull request open: the next version of the five packages, their
101
+ `CHANGELOG.md`, and the version copied into `RUNTIME_VERSION` and the reference snapshot
102
+ (`pnpm changeset:version`).
103
+ 3. **Merging the Version packages pull request** releases: the workflow tags the version
104
+ `vX.Y.Z` on the merge commit and runs `release.yml` on the tag — the VS Code extension (GitHub
105
+ release with the `.vsix` and the notes of the changelogs, the Visual Studio Marketplace, Open
106
+ VSX), the CLI on npm ([D65](DECISIONS.md)), then the website.
107
+
108
+ `pnpm check:version` checks that every file carries the same version (the CI runs it), and
109
+ `release.yml` refuses a tag that is not the committed version.
110
+
111
+ ### No token: trusted publishing ([D78](DECISIONS.md))
112
+
113
+ The repository stores no token for the registries. `release.yml` asks GitHub for an identity
114
+ token of the job (`id-token: write`); each registry exchanges it for a short-lived credential,
115
+ provided this repository and the workflow file `release.yml` are declared as its trusted
116
+ publisher. To set up once:
117
+
118
+ - **npm** — for each of the four packages (`open-rap-runtime`, `@open-rap/model`,
119
+ `@open-rap/compiler`, `@open-rap/runtime`): npmjs.com → the package → *Settings* →
120
+ *Trusted Publisher* → *GitHub Actions*: owner `ClementRingot`, repository
121
+ `Open-RAP-Runtime`, workflow `release.yml`, no environment. npm then attests the provenance
122
+ of each version. Then, in *Settings* → *Publishing access*, the packages can refuse tokens
123
+ (*Require two-factor authentication and disallow tokens*), and the `NPM_TOKEN` secret is
124
+ deleted.
125
+ - **Visual Studio Marketplace** — in the management page of the publisher `abaper`, a
126
+ *Trusted Publishing* policy for this repository and `release.yml`; then the repository
127
+ variable **`PUBLISH_VS_MARKETPLACE`** = `true` (*Settings → Secrets and variables → Actions →
128
+ Variables*), and the `VSCE_PAT` secret is deleted.
129
+ - **Open VSX** — on open-vsx.org, the trusted publisher of the namespace `abaper` for this
130
+ repository and `release.yml` (the Eclipse publisher agreement signed); then the variable
131
+ **`PUBLISH_OPEN_VSX`** = `true`, and the `OVSX_PAT` secret is deleted.
132
+
133
+ Without the variable, the Marketplace or Open VSX step is skipped; the GitHub release and npm
134
+ are always published. A version already on a registry is skipped (`--skip-duplicate`, `npm
135
+ view`), so a failed release is simply re-run.
136
+
137
+ The only stored credential is the private key of the **GitHub App** of the release train
138
+ (variable `RELEASE_APP_ID`, secret `RELEASE_APP_PRIVATE_KEY`, as in LISA): with it, the Version
139
+ packages pull request is opened by the App and the CI runs on it. Without it, the train still
140
+ works with the `GITHUB_TOKEN`, and the CI only runs once the pull request is merged.
141
+
142
+ By hand, for a release the train did not start: *Actions → Release → Run workflow* with the
143
+ committed version (`0.2.0`), or `git tag v0.2.0 && git push origin v0.2.0` on the commit of that
144
+ version.
145
+
146
+ To build the `.vsix` locally:
106
147
 
107
148
  ```sh
108
- git tag v0.1.0 && git push origin v0.1.0
149
+ pnpm install && pnpm build
150
+ cd packages/vscode && pnpm run package # open-rap-runtime-vscode.vsix (~31 MB)
109
151
  ```
110
152
 
111
- Or without a tag: *Actions → Release → Run workflow* with the version (`0.1.0`); the release then
112
- creates the tag `v0.1.0` on the commit of the run.
153
+ `pnpm run package` compiles the extension (esbuild), prepares `rapt/`
154
+ (`scripts/stage-rapt.mjs`: packages of the repository and dependencies installed from the npm
155
+ registry, useless files removed), then calls `vsce package`.
156
+
113
157
 
@@ -8,7 +8,7 @@ exit code is 1 as soon as there is an error (or a warning with `--warnings-as-er
8
8
  | PRJ001 | error | No service definition, or several without `--service` |
9
9
  | PRJ002 | error | The requested service definition does not exist |
10
10
  | SRVD001 | error | Syntax error in a service definition |
11
- | SRVD002 | warning | Several bindings for the service |
11
+ | SRVD002 | info / warning | Several bindings for the service: a UI binding and Web API ones, the UI one is built (info, D76); otherwise the first one (warning); `--binding <name>` chooses |
12
12
  | SRVD003 | warning | Binding that is not OData V4 |
13
13
  | SRVD004 | error | Entity set exposed twice |
14
14
  | SRVD005 | error | Exposed entity not found |
@@ -105,6 +105,8 @@ exit code is 1 as soon as there is an error (or a warning with `--warnings-as-er
105
105
  | LPD007 | warning | Role of a tile missing from the `rapt/authorizations.json` of the applications (the IdP must still give it) |
106
106
  | LPD008 | error | Malformed space or page in `launchpad.json` (title, pages, sections, roles) (D48) |
107
107
  | LPD009 | error | Malformed `source` application (not a path, or with `build`), folder not found, or application that does not build with the launchpad (D69) |
108
+ | LPD010 | error / warning | `rapt launchpad dev`: application without a local `url` with a port, port taken by another application or by the launchpad, no application with sources (errors); application without sources, not started (warning) (D75) |
109
+ | LPD011 | warning | Tile of an application that is an OData V4 - Web API (no UI): the tile is left out (D76) |
108
110
  | SEED001 | error | Unreadable or malformed `rapt/seed.json` (object table → array of rows expected) |
109
111
  | SEED002 | error | `rapt/seed.json`: table or field unknown to the application |
110
112
  | NR001 | error | Unreadable or malformed `rapt/number-ranges.json`: object longer than 10 characters, interval longer than 2 characters, non-numeric or inverted bounds |
package/docs/FEATURES.md CHANGED
@@ -211,6 +211,7 @@ dependent ETag, remote APIs.
211
211
  | `sap-*` parameters | ✅ | Ignored. |
212
212
  | Authentication: dev mode, Bearer JWT (OIDC, JWKS) | ✅ | Browser sessions (PKCE): M6; *client credentials* tokens (technical user); development OAuth 2.0 server (`/oauth`, client credentials and PKCE) in `rapt dev` (D60). |
213
213
  | *OData V4 - Web API* binding | ✅ | Without UI annotations, value helps, side effects, feature control; active instances of a draft BO (D60). |
214
+ | A Web API created as such (`rapt new --binding-type webapi`, *New complete business object…*), kept out of the launchpad; the UI binding preferred when a service has both | ✅ | D76; LPD011, SRVD002. |
214
215
  | `$apply`: `filter`, `groupby`, `aggregate` (`sum`, `min`, `max`, `average`, `countdistinct`, `$count`) | ✅ | With the DCL of the user; other transformations: 501 (D52). |
215
216
  | Enumeration types (`EnumType`): JSON by member name, literals `Ns.Type'M'` | ✅ | `enhanced` mode, CDS enumerated types (D55). |
216
217
  | JSON batch, `$value`, single properties | ❌ | Not in the MVP. |
@@ -255,6 +256,8 @@ dependent ETag, remote APIs.
255
256
  | Docker: launchpad, applications and their databases, Keycloak (`oidc` profile) | ✅ | Generated `docker-compose.yml`. |
256
257
  | Spaces and pages (`spaces` → `pages` → `sections`), assigned to roles | ✅ | Space tabs, list of the pages, last space remembered (D48). |
257
258
  | Development launchpad (`rapt dev`): application, documentation, `$metadata`, MCP | ✅ | D49. |
259
+ | Launchpad of the workspace in development (`rapt launchpad dev`, *RAP: Start the launchpad*): every application rebuilt on save, behind the launchpad | ✅ | D75; LPD010. |
260
+ | Web APIs never in the launchpad: not added, their tiles left out | ✅ | D76; LPD011. |
258
261
  | One "Launchpad" per workspace, applications added when they are created (`rapt new`, `rapt floorplan`, `rapt launchpad add`) | ✅ | D69; idempotent, `--launchpad`, `--no-launchpad`. |
259
262
  | Applications built with the launchpad from their sources (`source`); deployment of the complete launchpad or of one application alone | ✅ | D69; `out/launchpad/apps/<id>`, LPD009. |
260
263
  | Personalization by the user, notifications, navigation between applications from an application | ❌ | See KNOWN_GAPS. |
@@ -282,6 +285,7 @@ dependent ETag, remote APIs.
282
285
  | VS Code extension: commands of the CLI, Problems, wizard, *RAP Objects* view, floorplans | ✅ | D39, D61. |
283
286
  | `rapt` on the PATH of the terminals of VS Code | ✅ | Shims of the extension (D64). |
284
287
  | MCP server of rapt for AI coding agents (`rapt agent`), registered in the agent mode of VS Code | ✅ | Check, objects, floorplans, abapGit, documentation (D64). |
285
- | npm package `open-rap-runtime` (`rapt`, `npx open-rap-runtime`) | ✅ | D65; archives of `pnpm pack` checked on each tag before publication with `NPM_TOKEN`. |
288
+ | npm package `open-rap-runtime` (`rapt`, `npx open-rap-runtime`) | ✅ | D65; archives of `pnpm pack` checked on each release before publication. |
289
+ | Releases by Changesets (*Version packages* pull request, changelogs) and trusted publishing to npm, the Marketplace and Open VSX, without stored tokens | ✅ | D77, D78. |
286
290
  | Website with the documentation | ✅ | D62, D63. |
287
- | Feedback form (website, *RAP: Report a bug or request a feature…*) to the public feedback repository | ✅ | D71. |
291
+ | Feedback form (website, *RAP: Report a bug or request a feature…*) to the issues of the repository | ✅ | D71, D74. |
package/docs/GUIDE.md CHANGED
@@ -35,12 +35,13 @@ nothing else to install), then in the command palette (`Ctrl+Shift+P`):
35
35
 
36
36
  | Command | Effect |
37
37
  |---|---|
38
- | *RAP: New complete business object…* | `rapt new`: a complete managed BO (table, CDS, BDEF, behavior pool, service, binding), with initial data; possible in an empty folder |
38
+ | *RAP: New complete business object…* | `rapt new`: a complete managed BO (table, CDS, BDEF, behavior pool, service, binding), with initial data; possible in an empty folder. It first asks what the service is for: a Fiori application (UI) or a Web API for other systems ([D76](DECISIONS.md)) |
39
39
  | *RAP: New RAP object…* | create object by object with the wizard, like *New ABAP Repository Object* of ADT: the types by category (Dictionary, Core Data Services, Behavior, Business Services, Source Code Library), a filter, a description, the fields of the type (source object, exposed entities, binding type…) |
40
40
  | *RAP: Choose the floorplan of the application…* | `rapt floorplan`: List Report, Worklist, Analytical List Page or Form Entry, with what each one needs; asked anyway before the first generation |
41
41
  | *RAP: Show the intermediate representation* | `rapt ir`: the model (`model.json`) in an editor |
42
42
  | *RAP: Build the launchpad (all the applications)…* | `rapt launchpad`: the launchpad of the workspace and all its applications ([D69](DECISIONS.md)) |
43
43
  | *RAP: Start rapt dev* | builds, starts and opens the development launchpad; restarts on each save |
44
+ | *RAP: Start the launchpad (rapt dev, all the applications)* | `rapt launchpad dev`: every application of the launchpad in development, behind the launchpad ([D75](DECISIONS.md)) |
44
45
  | *RAP: Check the BO* | `rapt check`: diagnostics in the Problems tab (also on each save) |
45
46
  | *RAP: Build the application…* | either the **launchpad with all the applications** (`rapt launchpad`) or the **application alone** (`rapt build`, standalone) |
46
47
  | *RAP: Generate the abapGit files* | `rapt abapgit`: the missing XML files for the import into SAP |
@@ -58,7 +59,8 @@ chosen: the extension asks for it when it was not ([D66](DECISIONS.md)).
58
59
  The **RAP Objects** view of the explorer arranges the objects of the project like the project
59
60
  explorer of ADT (dictionary, data definitions, metadata extensions, access controls, behavior
60
61
  definitions, services, classes); its title bar creates an object, checks the project and starts
61
- `rapt dev` ([D61](DECISIONS.md)).
62
+ `rapt dev` ([D61](DECISIONS.md)). Each service binding shows its kind, `UI` or `Web API`
63
+ ([D76](DECISIONS.md)).
62
64
 
63
65
  Syntax highlighting covers ABAP, CDS (DDLS, DDLX, DCL, SRVD, tables, types) and BDEF.
64
66
 
@@ -385,7 +387,8 @@ for the file in the project then its parent folders (up to the root of the git r
385
387
  otherwise creates it in the parent folder of the project; `--launchpad <file>` designates
386
388
  another one, `--no-launchpad` adds nothing. The VS Code extension puts it next to the
387
389
  `.code-workspace` (or in the first folder of the workspace). An application already present is
388
- never changed: titles, tiles and roles are edited by hand.
390
+ never changed: titles, tiles and roles are edited by hand. A Web API is never added: it has no
391
+ UI to open, and a tile on one is left out (LPD011, [D76](DECISIONS.md)).
389
392
 
390
393
  ```
391
394
  rap-apps/
@@ -426,6 +429,15 @@ separately. The content is organized in groups, or in **spaces and pages** ([D48
426
429
  }
427
430
  ```
428
431
 
432
+ **The launchpad in development** ([D75](DECISIONS.md)): `rapt launchpad dev launchpad.json`
433
+ starts `rapt dev` for each application with sources (`source`), each on the port of its `url`
434
+ (`http://localhost:8081/`…), and the launchpad in front of them on `http://localhost:8090/`
435
+ (`--port`, `--host`). Each save rebuilds its application; a change of `launchpad.json` updates
436
+ the launchpad, starts the added applications and stops the removed ones. The applications with
437
+ `build` are not started (LPD010 warning); two applications on the same port, or an application
438
+ without a local port, are errors (LPD010). `--json` writes one event per line, with the `app`
439
+ of the application.
440
+
429
441
  ## 10. Shipping
430
442
 
431
443
  Two ways to deploy ([D69](DECISIONS.md)):
@@ -466,12 +478,13 @@ Dockerfile, docker-compose.yml, keycloak/, manifest.yml container, PostgreSQL,
466
478
  | `rapt check <src>` | diagnostics (`file:line:column: severity CODE message`), exit code 1 on error |
467
479
  | `rapt build <src> --out <dir>` | generated application |
468
480
  | `rapt dev <src>` | development loop |
469
- | `rapt new <src> <Entity> [--prefix ZRT] [--description …]` | complete BO, added to the launchpad of the workspace |
481
+ | `rapt new <src> <Entity> [--prefix ZRT] [--description …] [--binding-type webapi]` | complete BO, added to the launchpad of the workspace; with `--binding-type webapi`, a Web API (no UI, not in the launchpad) |
470
482
  | `rapt generate <src> <type> <name> [--from X] [--for Y] [--expose A,B] [--root]` | one object |
471
483
  | `rapt floorplan <src> [<EntitySet> <floorplan>]` | floorplan of a root entity set; the application is added to the launchpad |
472
484
  | `rapt abapgit <src> [--check]` | missing abapGit XML files |
473
485
  | `rapt mcp <src>` | MCP tools (`rapt/mcp.json`) |
474
486
  | `rapt launchpad <launchpad.json> --out <dir>` | launchpad, and the applications of their sources (`source`) |
487
+ | `rapt launchpad dev <launchpad.json> [--port 8090]` | development loop of all the applications of the launchpad, behind it |
475
488
  | `rapt launchpad add <src> [--launchpad f]` | adds the application to the launchpad of the workspace (created when missing) |
476
489
  | `rapt ir <src> [--out f]` | intermediate representation (JSON) |
477
490
  | `rapt agent [<workspace>]` | MCP server (stdio) of rapt for AI coding agents (§13) |
@@ -508,6 +521,27 @@ A service bound as *OData V4 - Web API* (`BINDING_TYPE_CATEGORY` 1 in the SRVB,
508
521
  `rapt generate . binding ZAPI_TRAVEL_O4 --for ZUI_TRAVEL --binding-type webapi`) has neither UI
509
522
  nor UI annotations; a draft BO only exposes its active instances there ([D60](DECISIONS.md)).
510
523
 
524
+ **A Web API or a Fiori application** ([D76](DECISIONS.md)): the type of the service binding
525
+ decides, as on SAP. Choose it when the business object is created: *RAP: New complete business
526
+ object…* asks "Fiori application (UI)" or "Web API" first; on the command line,
527
+ `rapt new my-api Partner --prefix ZPA --binding-type webapi` writes `ZPA_API_PARTNER` and its
528
+ binding `ZPA_API_PARTNER_O4` (category 1), without metadata extension. A Web API:
529
+
530
+ - is never added to the launchpad of the workspace (`rapt new`, `rapt launchpad add`, the
531
+ launchpad commands of VS Code); a tile written by hand on one is left out (LPD011);
532
+ - has no floorplan (`rapt floorplan` lists none, VS Code does not ask);
533
+ - shows `Web API` next to its binding in the *RAP Objects* view.
534
+
535
+ A binding alone is created the same way: *New RAP object… > Service binding* (or the quick
536
+ picks) asks its type, UI or Web API, and proposes the name SAP would give (`ZRT_UI_TRAVEL_O4`,
537
+ `ZRT_API_TRAVEL_O4`); on the command line, `rapt generate . binding ZRT_API_TRAVEL_O4 --for
538
+ ZRT_UI_TRAVEL --binding-type webapi`.
539
+
540
+ A service can have both bindings, as on SAP: `rapt dev` and the launchpad serve the UI one
541
+ (SRVD002 info), `rapt dev . --binding ZPA_API_PARTNER_O4` the Web API. To turn an application
542
+ into a Web API, change `BINDING_TYPE_CATEGORY` of its binding to `1` (or add a Web API binding
543
+ with *New RAP object… > Service binding*).
544
+
511
545
  In development, `rapt dev` serves an OAuth 2.0 server under `/oauth`:
512
546
 
513
547
  ```sh
@@ -178,6 +178,7 @@ Reference versions: `@abaplint/core` 2.120.98, `@abaplint/transpiler` 2.14.24,
178
178
  |---|---|
179
179
  | Development OAuth server | Development only: no refresh token, nor consent, nor revocation; signing key regenerated on each start. |
180
180
  | Web API of a draft BO | Active instances only (the draft is not exposed). |
181
+ | Service with a UI and a Web API binding | One binding served at a time: the UI one by default, the Web API with `rapt dev --binding <name>` (D76). On SAP, both are published. |
181
182
  | OData V2 | Not supported: the generated service is always OData V4 (SRVD003). |
182
183
 
183
184
  ## Enhanced mode (D45)
package/docs/README.md CHANGED
@@ -63,6 +63,8 @@ rapt dev my-project # http://localhost:8080/ — rebuilt
63
63
  files for the import into SAP).
64
64
  - **Development loop** `rapt dev`: embedded database, rebuild on each save, positioned
65
65
  diagnostics (`file:line:column`), development launchpad with the built-in documentation.
66
+ `rapt launchpad dev launchpad.json` does the same for every application of the workspace, each
67
+ on the port of its URL, behind the launchpad (`http://localhost:8090/`).
66
68
  - **Modes**: `standard` (strictly as on SAP, activatable on SAP) or `enhanced` (extensions:
67
69
  mandatory fields checked automatically, managed BO on a custom entity, CDS enumerated types
68
70
  exposed as OData `EnumType`).
@@ -81,7 +83,11 @@ rapt dev my-project # http://localhost:8080/ — rebuilt
81
83
  by the database view.
82
84
  - **Security**: OIDC (Keycloak, SAP Cloud Identity Services, Entra ID…), Web API bindings with
83
85
  OAuth 2.0 (client credentials, PKCE), authorization objects and `AUTHORITY-CHECK`, DCL, roles.
84
- - **One launchpad per workspace**: each application is added to it when it is created; ship
86
+ - **Web APIs**: a business object created as an API for other systems
87
+ (`rapt new … --binding-type webapi`, or the first question of *New complete business object…*)
88
+ has no UI and stays out of the launchpad.
89
+ - **One launchpad per workspace**: each application is added to it when it is created; develop
90
+ them together behind it (`rapt launchpad dev`, *RAP: Start the launchpad* in VS Code); ship
85
91
  either the launchpad with all its applications (`rapt launchpad`) or one application alone
86
92
  (`rapt build`).
87
93
  - **Deployment**: Docker, `docker compose`, SAP BTP Cloud Foundry (`cf push`), any Node.js
@@ -118,8 +124,7 @@ Open RAP Runtime, contains this documentation and serves the `.vsix` of the late
118
124
 
119
125
  Report a bug or request a feature with the
120
126
  [feedback form](https://clementringot.github.io/Open-Rap-Runtime/feedback.html) (it opens a
121
- pre-filled issue in the public
122
- [feedback repository](https://github.com/ClementRingot/open-rap-runtime-feedback)), or in VS Code
127
+ pre-filled issue in the [issues](https://github.com/ClementRingot/Open-RAP-Runtime/issues) of this repository), or in VS Code
123
128
  with *RAP: Report a bug or request a feature…*.
124
129
 
125
130
  ## Contributing
package/package.json CHANGED
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "name": "@open-rap/compiler",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Compiles SAP RAP sources (abapGit format) into a standalone Node.js OData V4 application.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "homepage": "https://clementringot.github.io/Open-Rap-Runtime/",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/ClementRingot/Open-RAP-Runtime.git",
11
+ "directory": "packages/compiler"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/ClementRingot/Open-RAP-Runtime/issues"
15
+ },
8
16
  "keywords": [
9
17
  "sap",
10
18
  "rap",
@@ -44,7 +52,7 @@
44
52
  "@abaplint/transpiler": "2.14.24",
45
53
  "chevrotain": "13.2.0",
46
54
  "fast-xml-parser": "5.12.0",
47
- "@open-rap/model": "0.1.1"
55
+ "@open-rap/model": "0.2.0"
48
56
  },
49
57
  "scripts": {
50
58
  "build": "tsc -p tsconfig.build.json && node scripts/copy-docs.mjs"