@open-rap/compiler 0.0.0-stage → 0.1.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.
Files changed (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -2
  3. package/dist/agent/server.d.ts +35 -0
  4. package/dist/agent/server.js +408 -0
  5. package/dist/agent/server.js.map +1 -0
  6. package/dist/authoring/abapgit.d.ts +38 -0
  7. package/dist/authoring/abapgit.js +242 -0
  8. package/dist/authoring/abapgit.js.map +1 -0
  9. package/dist/authoring/catalog.d.ts +48 -0
  10. package/dist/authoring/catalog.js +117 -0
  11. package/dist/authoring/catalog.js.map +1 -0
  12. package/dist/authoring/floorplan.d.ts +28 -0
  13. package/dist/authoring/floorplan.js +31 -0
  14. package/dist/authoring/floorplan.js.map +1 -0
  15. package/dist/authoring/generate.d.ts +57 -0
  16. package/dist/authoring/generate.js +630 -0
  17. package/dist/authoring/generate.js.map +1 -0
  18. package/dist/authoring/mcp.d.ts +15 -0
  19. package/dist/authoring/mcp.js +52 -0
  20. package/dist/authoring/mcp.js.map +1 -0
  21. package/dist/authoring/new.d.ts +35 -0
  22. package/dist/authoring/new.js +389 -0
  23. package/dist/authoring/new.js.map +1 -0
  24. package/dist/bdef/ast.d.ts +249 -0
  25. package/dist/bdef/ast.js +3 -0
  26. package/dist/bdef/ast.js.map +1 -0
  27. package/dist/bdef/lexer.d.ts +105 -0
  28. package/dist/bdef/lexer.js +148 -0
  29. package/dist/bdef/lexer.js.map +1 -0
  30. package/dist/bdef/parser.d.ts +22 -0
  31. package/dist/bdef/parser.js +1012 -0
  32. package/dist/bdef/parser.js.map +1 -0
  33. package/dist/build.d.ts +26 -0
  34. package/dist/build.js +62 -0
  35. package/dist/build.js.map +1 -0
  36. package/dist/cds/adapter.d.ts +91 -0
  37. package/dist/cds/adapter.js +381 -0
  38. package/dist/cds/adapter.js.map +1 -0
  39. package/dist/cds/expression-ast.d.ts +65 -0
  40. package/dist/cds/expression-ast.js +330 -0
  41. package/dist/cds/expression-ast.js.map +1 -0
  42. package/dist/cli.d.ts +9 -0
  43. package/dist/cli.js +485 -0
  44. package/dist/cli.js.map +1 -0
  45. package/dist/dcl/parser.d.ts +59 -0
  46. package/dist/dcl/parser.js +338 -0
  47. package/dist/dcl/parser.js.map +1 -0
  48. package/dist/ddic/catalog.d.ts +17 -0
  49. package/dist/ddic/catalog.js +211 -0
  50. package/dist/ddic/catalog.js.map +1 -0
  51. package/dist/ddic/cds-types.d.ts +47 -0
  52. package/dist/ddic/cds-types.js +131 -0
  53. package/dist/ddic/cds-types.js.map +1 -0
  54. package/dist/ddic/table-source.d.ts +70 -0
  55. package/dist/ddic/table-source.js +500 -0
  56. package/dist/ddic/table-source.js.map +1 -0
  57. package/dist/ddic/xml.d.ts +65 -0
  58. package/dist/ddic/xml.js +201 -0
  59. package/dist/ddic/xml.js.map +1 -0
  60. package/dist/dev.d.ts +128 -0
  61. package/dist/dev.js +434 -0
  62. package/dist/dev.js.map +1 -0
  63. package/dist/diagnostics.d.ts +33 -0
  64. package/dist/diagnostics.js +53 -0
  65. package/dist/diagnostics.js.map +1 -0
  66. package/dist/gen/abap/derived-types.d.ts +26 -0
  67. package/dist/gen/abap/derived-types.js +323 -0
  68. package/dist/gen/abap/derived-types.js.map +1 -0
  69. package/dist/gen/abap/eml.d.ts +118 -0
  70. package/dist/gen/abap/eml.js +362 -0
  71. package/dist/gen/abap/eml.js.map +1 -0
  72. package/dist/gen/abap/enums.d.ts +13 -0
  73. package/dist/gen/abap/enums.js +74 -0
  74. package/dist/gen/abap/enums.js.map +1 -0
  75. package/dist/gen/abap/framework-http.d.ts +14 -0
  76. package/dist/gen/abap/framework-http.js +1049 -0
  77. package/dist/gen/abap/framework-http.js.map +1 -0
  78. package/dist/gen/abap/framework-query.d.ts +14 -0
  79. package/dist/gen/abap/framework-query.js +225 -0
  80. package/dist/gen/abap/framework-query.js.map +1 -0
  81. package/dist/gen/abap/framework-utils.d.ts +29 -0
  82. package/dist/gen/abap/framework-utils.js +3707 -0
  83. package/dist/gen/abap/framework-utils.js.map +1 -0
  84. package/dist/gen/abap/framework.d.ts +12 -0
  85. package/dist/gen/abap/framework.js +480 -0
  86. package/dist/gen/abap/framework.js.map +1 -0
  87. package/dist/gen/abap/generate.d.ts +40 -0
  88. package/dist/gen/abap/generate.js +238 -0
  89. package/dist/gen/abap/generate.js.map +1 -0
  90. package/dist/gen/abap/rewrite.d.ts +82 -0
  91. package/dist/gen/abap/rewrite.js +957 -0
  92. package/dist/gen/abap/rewrite.js.map +1 -0
  93. package/dist/gen/abap/shadow.d.ts +25 -0
  94. package/dist/gen/abap/shadow.js +175 -0
  95. package/dist/gen/abap/shadow.js.map +1 -0
  96. package/dist/gen/abap/tokens.d.ts +33 -0
  97. package/dist/gen/abap/tokens.js +87 -0
  98. package/dist/gen/abap/tokens.js.map +1 -0
  99. package/dist/gen/app/index.d.ts +25 -0
  100. package/dist/gen/app/index.js +322 -0
  101. package/dist/gen/app/index.js.map +1 -0
  102. package/dist/gen/csdl.d.ts +11 -0
  103. package/dist/gen/csdl.js +562 -0
  104. package/dist/gen/csdl.js.map +1 -0
  105. package/dist/gen/deploy.d.ts +12 -0
  106. package/dist/gen/deploy.js +53 -0
  107. package/dist/gen/deploy.js.map +1 -0
  108. package/dist/gen/docs/index.d.ts +35 -0
  109. package/dist/gen/docs/index.js +267 -0
  110. package/dist/gen/docs/index.js.map +1 -0
  111. package/dist/gen/docs/markdown.d.ts +23 -0
  112. package/dist/gen/docs/markdown.js +187 -0
  113. package/dist/gen/docs/markdown.js.map +1 -0
  114. package/dist/gen/docs/site.d.ts +17 -0
  115. package/dist/gen/docs/site.js +106 -0
  116. package/dist/gen/docs/site.js.map +1 -0
  117. package/dist/gen/keycloak.d.ts +21 -0
  118. package/dist/gen/keycloak.js +90 -0
  119. package/dist/gen/keycloak.js.map +1 -0
  120. package/dist/gen/launchpad/index.d.ts +48 -0
  121. package/dist/gen/launchpad/index.js +302 -0
  122. package/dist/gen/launchpad/index.js.map +1 -0
  123. package/dist/gen/launchpad/ui.d.ts +14 -0
  124. package/dist/gen/launchpad/ui.js +350 -0
  125. package/dist/gen/launchpad/ui.js.map +1 -0
  126. package/dist/gen/mcp.d.ts +23 -0
  127. package/dist/gen/mcp.js +244 -0
  128. package/dist/gen/mcp.js.map +1 -0
  129. package/dist/gen/sql-expressions.d.ts +12 -0
  130. package/dist/gen/sql-expressions.js +136 -0
  131. package/dist/gen/sql-expressions.js.map +1 -0
  132. package/dist/gen/sql.d.ts +38 -0
  133. package/dist/gen/sql.js +612 -0
  134. package/dist/gen/sql.js.map +1 -0
  135. package/dist/gen/ui/index.d.ts +7 -0
  136. package/dist/gen/ui/index.js +27 -0
  137. package/dist/gen/ui/index.js.map +1 -0
  138. package/dist/gen/ui/layout.d.ts +230 -0
  139. package/dist/gen/ui/layout.js +511 -0
  140. package/dist/gen/ui/layout.js.map +1 -0
  141. package/dist/gen/ui/static.d.ts +55 -0
  142. package/dist/gen/ui/static.js +2901 -0
  143. package/dist/gen/ui/static.js.map +1 -0
  144. package/dist/gen/ui/views.d.ts +10 -0
  145. package/dist/gen/ui/views.js +511 -0
  146. package/dist/gen/ui/views.js.map +1 -0
  147. package/dist/gen/vendor.d.ts +23 -0
  148. package/dist/gen/vendor.js +68 -0
  149. package/dist/gen/vendor.js.map +1 -0
  150. package/dist/gen/xml.d.ts +9 -0
  151. package/dist/gen/xml.js +42 -0
  152. package/dist/gen/xml.js.map +1 -0
  153. package/dist/index.d.ts +20 -0
  154. package/dist/index.js +20 -0
  155. package/dist/index.js.map +1 -0
  156. package/dist/input/project.d.ts +50 -0
  157. package/dist/input/project.js +128 -0
  158. package/dist/input/project.js.map +1 -0
  159. package/dist/ir/access-controls.d.ts +11 -0
  160. package/dist/ir/access-controls.js +148 -0
  161. package/dist/ir/access-controls.js.map +1 -0
  162. package/dist/ir/authorizations.d.ts +25 -0
  163. package/dist/ir/authorizations.js +178 -0
  164. package/dist/ir/authorizations.js.map +1 -0
  165. package/dist/ir/behaviors.d.ts +16 -0
  166. package/dist/ir/behaviors.js +548 -0
  167. package/dist/ir/behaviors.js.map +1 -0
  168. package/dist/ir/builder.d.ts +20 -0
  169. package/dist/ir/builder.js +505 -0
  170. package/dist/ir/builder.js.map +1 -0
  171. package/dist/ir/config.d.ts +25 -0
  172. package/dist/ir/config.js +130 -0
  173. package/dist/ir/config.js.map +1 -0
  174. package/dist/ir/dictionary.d.ts +54 -0
  175. package/dist/ir/dictionary.js +328 -0
  176. package/dist/ir/dictionary.js.map +1 -0
  177. package/dist/ir/entities.d.ts +58 -0
  178. package/dist/ir/entities.js +676 -0
  179. package/dist/ir/entities.js.map +1 -0
  180. package/dist/ir/expressions.d.ts +33 -0
  181. package/dist/ir/expressions.js +327 -0
  182. package/dist/ir/expressions.js.map +1 -0
  183. package/dist/ir/handlers.d.ts +63 -0
  184. package/dist/ir/handlers.js +398 -0
  185. package/dist/ir/handlers.js.map +1 -0
  186. package/dist/ir/number-ranges.d.ts +24 -0
  187. package/dist/ir/number-ranges.js +74 -0
  188. package/dist/ir/number-ranges.js.map +1 -0
  189. package/dist/ir/seed.d.ts +23 -0
  190. package/dist/ir/seed.js +78 -0
  191. package/dist/ir/seed.js.map +1 -0
  192. package/dist/ir/service.d.ts +21 -0
  193. package/dist/ir/service.js +96 -0
  194. package/dist/ir/service.js.map +1 -0
  195. package/dist/launchpad/config.d.ts +47 -0
  196. package/dist/launchpad/config.js +321 -0
  197. package/dist/launchpad/config.js.map +1 -0
  198. package/dist/launchpad/workspace.d.ts +48 -0
  199. package/dist/launchpad/workspace.js +166 -0
  200. package/dist/launchpad/workspace.js.map +1 -0
  201. package/dist/srvd/parser.d.ts +36 -0
  202. package/dist/srvd/parser.js +193 -0
  203. package/dist/srvd/parser.js.map +1 -0
  204. package/dist/standard/data.d.ts +18 -0
  205. package/dist/standard/data.js +534 -0
  206. package/dist/standard/data.js.map +1 -0
  207. package/dist/standard/index.d.ts +36 -0
  208. package/dist/standard/index.js +507 -0
  209. package/dist/standard/index.js.map +1 -0
  210. package/dist/version.d.ts +2 -0
  211. package/dist/version.js +4 -0
  212. package/dist/version.js.map +1 -0
  213. package/docs/AGENTS.md +79 -0
  214. package/docs/ANNOTATIONS.md +76 -0
  215. package/docs/DECISIONS.md +1526 -0
  216. package/docs/DEPLOYMENT.md +113 -0
  217. package/docs/DIAGNOSTICS.md +116 -0
  218. package/docs/FEATURES.md +287 -0
  219. package/docs/GUIDE.md +560 -0
  220. package/docs/KNOWN_GAPS.md +216 -0
  221. package/docs/MCP.md +84 -0
  222. package/docs/PLAN.md +690 -0
  223. package/docs/README.md +148 -0
  224. package/docs/REMOTE_APIS.md +121 -0
  225. package/docs/ROADMAP.md +35 -0
  226. package/docs/UTILITIES.md +95 -0
  227. package/package.json +49 -3
package/docs/GUIDE.md ADDED
@@ -0,0 +1,560 @@
1
+ # Open RAP Runtime guide
2
+
3
+ This guide describes everything Open RAP Runtime can do and how to use it. It is written for ABAP
4
+ developers and for AI agents who write a RAP business object (BO) with it: each section gives the
5
+ command, the file to write and the resulting behavior, with a link to the technical decision
6
+ (`Dxx`, in [DECISIONS.md](DECISIONS.md)) that gives the details.
7
+
8
+ - Status, feature by feature: [FEATURES.md](FEATURES.md)
9
+ - Diagnostic codes: [DIAGNOSTICS.md](DIAGNOSTICS.md)
10
+ - Known gaps: [KNOWN_GAPS.md](../KNOWN_GAPS.md) · Roadmap: [ROADMAP.md](ROADMAP.md)
11
+
12
+ ## 1. The principle
13
+
14
+ You write a RAP BO as in the ABAP Development Tools (ADT): tables, CDS views, metadata
15
+ extensions, behavior definition (BDEF), behavior pool in ABAP, service definition and binding.
16
+ Open RAP Runtime compiles these sources (abapGit format) into a standalone Node.js application:
17
+
18
+ - an **OData V4** service identical to the one of SAP (same paths, `$metadata`, `$batch`, ETags);
19
+ - the **RAP managed runtime**: locks, numbering, authorizations, feature control,
20
+ determinations, validations, actions, messages, EML;
21
+ - the **ABAP behavior pool transpiled** to JavaScript (abaplint), run as is;
22
+ - a **PostgreSQL** database (or embedded PGlite in development);
23
+ - an **OpenUI5 UI** List Report / Object Page generated from the `@UI` annotations;
24
+ - a **launchpad**, an **MCP server** for AI agents, **deployment** files.
25
+
26
+ The sources stay activatable on SAP: the same abapGit repository is imported into an ABAP Cloud
27
+ or S/4HANA system (in `standard` mode, see §4).
28
+
29
+ ## 2. Getting started
30
+
31
+ ### With VS Code (recommended)
32
+
33
+ Install the `open-rap-runtime-vscode.vsix` extension (it contains rapt, OpenUI5 and PGlite:
34
+ nothing else to install), then in the command palette (`Ctrl+Shift+P`):
35
+
36
+ | Command | Effect |
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 |
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
+ | *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
+ | *RAP: Show the intermediate representation* | `rapt ir`: the model (`model.json`) in an editor |
42
+ | *RAP: Build the launchpad (all the applications)…* | `rapt launchpad`: the launchpad of the workspace and all its applications ([D69](DECISIONS.md)) |
43
+ | *RAP: Start rapt dev* | builds, starts and opens the development launchpad; restarts on each save |
44
+ | *RAP: Check the BO* | `rapt check`: diagnostics in the Problems tab (also on each save) |
45
+ | *RAP: Build the application…* | either the **launchpad with all the applications** (`rapt launchpad`) or the **application alone** (`rapt build`, standalone) |
46
+ | *RAP: Generate the abapGit files* | `rapt abapgit`: the missing XML files for the import into SAP |
47
+ | *RAP: Generate the MCP server of the service* | `rapt mcp`: the tools for AI agents |
48
+ | *RAP: Choose the project mode* | `standard` or `enhanced` (`rapt/config.json`) |
49
+ | *RAP: Report a bug or request a feature…* | the feedback form of the website, with the version and the environment filled in ([D71](DECISIONS.md)) |
50
+
51
+ A right click on a folder of the explorer arranges these commands in three groups: **create**
52
+ (complete BO, object by object), **project** (check, abapGit), **application** (floorplan, rapt
53
+ dev, build). A command is greyed out as long as it is not possible: the project commands outside
54
+ an abapGit project, the application commands as long as the project has no service definition.
55
+ Before the application is built or started, the floorplan of each root entity must have been
56
+ chosen: the extension asks for it when it was not ([D66](DECISIONS.md)).
57
+
58
+ The **RAP Objects** view of the explorer arranges the objects of the project like the project
59
+ explorer of ADT (dictionary, data definitions, metadata extensions, access controls, behavior
60
+ definitions, services, classes); its title bar creates an object, checks the project and starts
61
+ `rapt dev` ([D61](DECISIONS.md)).
62
+
63
+ Syntax highlighting covers ABAP, CDS (DDLS, DDLX, DCL, SRVD, tables, types) and BDEF.
64
+
65
+ The integrated terminals of VS Code have the `rapt` command of the extension (setting
66
+ `rapt.terminal.addToPath`), and the agent mode of VS Code finds the MCP server of rapt (§13).
67
+
68
+ ### On the command line
69
+
70
+ ```sh
71
+ rapt new my-project Travel --prefix ZRT # a complete managed BO
72
+ rapt dev my-project # http://localhost:8080/: development launchpad
73
+ ```
74
+
75
+ Install it with `npm install -g open-rap-runtime` (Node.js 22): the package installs the `rapt`
76
+ command with everything it needs (runtime, OpenUI5, PGlite) ([D65](DECISIONS.md)). Without a
77
+ global installation: `npx open-rap-runtime <command>` (for example `npx open-rap-runtime check
78
+ my-project` in a CI), or `open-rap-runtime` as a `devDependency` of the project and `npx rapt …`.
79
+ The libraries `@open-rap/compiler`, `@open-rap/runtime` and `@open-rap/model`
80
+ are published separately too. From a clone of the repository: `pnpm install && pnpm build`,
81
+ then `node packages/compiler/dist/cli.js` instead of `rapt`.
82
+
83
+ ## 3. The project
84
+
85
+ ```
86
+ my-project/
87
+ .abapgit.xml folder of the sources (STARTING_FOLDER), written by rapt abapgit
88
+ src/ the objects, in abapGit format
89
+ zrt_travel.tabl.astabl table written as source (ADT "define table" syntax)
90
+ zrt_r_travel.ddls.asddls root CDS view
91
+ zrt_c_travel.ddls.asddls projection
92
+ zrt_c_travel.ddlx.asddlxs metadata extension (UI)
93
+ zrt_r_travel.bdef.asbdef behavior definition
94
+ zbp_rt_r_travel.clas.* behavior pool
95
+ zrt_ui_travel.srvd.srvdsrv service definition
96
+ *.xml abapGit metadata (generated by rapt abapgit)
97
+ rapt/ configuration of Open RAP Runtime (never imported into SAP)
98
+ config.json mode of the project (standard / enhanced)
99
+ seed.json, seed.sql initial data of rapt dev
100
+ authorizations.json roles → authorizations (authorization objects)
101
+ number-ranges.json number range intervals
102
+ mcp.json MCP tools and their descriptions
103
+ .rapt/ build of rapt dev (ignored by git)
104
+ ```
105
+
106
+ Tables are written as source (`.tabl.astabl`): `rapt abapgit` derives the XML abapGit expects
107
+ from them ([D42](DECISIONS.md)). The other XML files are generated when they are missing; an
108
+ existing XML file is never changed.
109
+
110
+ ## 4. `standard` and `enhanced` modes
111
+
112
+ `rapt/config.json` ([D45](DECISIONS.md)):
113
+
114
+ ```json
115
+ { "mode": "enhanced" }
116
+ ```
117
+
118
+ | | `standard` (default) | `enhanced` |
119
+ |---|---|---|
120
+ | Goal | As on SAP: what builds activates on SAP | Extensions of Open RAP Runtime |
121
+ | Managed BO + unmanaged save on a custom entity | refused (BDEF027) | allowed ([D43](DECISIONS.md)) |
122
+ | `field ( mandatory )` | a hint for the UI, as in RAP | checked on save, one message per field, without a validation to write |
123
+ | Exposed element of a CDS enumerated type | refused as on SAP (CDS021) | OData `EnumType`: `"Status": "OPEN"`, labels and choice list in the UI ([D55](DECISIONS.md)) |
124
+
125
+ `rapt check --mode enhanced` (or `build`, `dev`) overrides the mode of the file.
126
+
127
+ ## 5. Writing the objects
128
+
129
+ ### Creating an object: `rapt generate`
130
+
131
+ ```sh
132
+ rapt generate . table zshop_order
133
+ rapt generate . view ZR_ShopOrder --from zshop_order --root
134
+ rapt generate . projection ZC_ShopOrder --from ZR_ShopOrder
135
+ rapt generate . metadata ZC_ShopOrder
136
+ rapt generate . behavior ZR_ShopOrder # managed BDEF, with the compositions
137
+ rapt generate . pool ZBP_R_SHOPORDER # handlers of the BDEF that names the class
138
+ rapt generate . behavior ZC_ShopOrder # projection BDEF
139
+ rapt generate . access ZC_ShopOrder # DCL
140
+ rapt generate . service ZUI_SHOPORDER --expose ZC_ShopOrder,ZC_ShopItem
141
+ rapt generate . binding ZUI_SHOPORDER_O4 --for ZUI_SHOPORDER
142
+ rapt generate . dataelement ZSHOP_ORDER_NO --type abap.numc(8)
143
+ rapt generate . domain ZSHOP_STATUS --type abap.char(1)
144
+ rapt generate . tableentity ZSHOP_ITEM --root # table entity: table and entity in one object
145
+ rapt generate . type ZSHOP_NAME # CDS simple type
146
+ rapt generate . enum ZSHOP_STATUS # CDS enumerated type
147
+ ```
148
+
149
+ `rapt generate . ` without a type lists the types. Each object is derived from the previous one as
150
+ in the wizards of ADT; the abapGit XML is written with it ([D46](DECISIONS.md)).
151
+
152
+ ### CDS
153
+
154
+ - `define [root] view entity … as select from <table>`, `as projection on`, `provider contract
155
+ transactional_query`, `composition`, `association to parent`, associations, `redirected to`.
156
+ - Metadata extensions (`@Metadata.allowExtensions: true`) merged with the view.
157
+ - Abstract entities (action parameters), custom entities (`@ObjectModel.query.implementedBy`,
158
+ `if_rap_query_provider` class).
159
+ - Access controls (DCL): `grant select … where`, `aspect pfcg_auth`, `aspect user`
160
+ ([D35](DECISIONS.md)).
161
+ - Calculated elements in the select list ([D67](DECISIONS.md)): `CASE`, `CAST`, `+ - * /`,
162
+ literals, `$projection.Element`, `$session.system_date` and the common SQL functions
163
+ (`concat`, `concat_with_space`, `substring`, `upper`, `lower`, `length`, `left`, `right`,
164
+ `ltrim`, `rtrim`, `replace`, `coalesce`, `div`, `division`, `mod`, `abs`, `round`, `ceil`,
165
+ `floor`, `dats_days_between`, `dats_add_days`). PostgreSQL computes them in the view; they are
166
+ read-only (`Core.Computed`, ignored in the writes) and cannot be keys. A projection takes them
167
+ and can define its own:
168
+
169
+ ```cds
170
+ case overall_status when 'A' then 'Accepted' else 'Open' end as StatusText,
171
+ booking_fee + total_price as TotalWithFee,
172
+ cast( dats_days_between( begin_date, end_date ) as abap.int4 ) as Duration,
173
+ ```
174
+
175
+ Without a `CAST`, the type is derived from the operands; when it cannot be derived (`NULL`
176
+ alone, calculation on a string), CDS022 asks for a `CAST`. In a draft, the value is computed on
177
+ the values of the draft; read with EML in the behavior pool, it is the one of the last save.
178
+ - Still refused (CDS002): association paths (`_Agency.Name`), `$session.user`,
179
+ `$session.client`, `$session.system_language`, `BETWEEN`, aggregates, other SQL functions.
180
+
181
+ #### Table entities and CDS types ([D55](DECISIONS.md))
182
+
183
+ A table entity combines the table and the entity; a managed BO is written directly on it, without
184
+ a `persistent table`:
185
+
186
+ ```cds
187
+ @ClientHandling.type: #CLIENT_DEPENDENT
188
+ @AbapCatalog.deliveryClass: #APPLICATION_DATA
189
+ @AccessControl.authorizationCheck: #NOT_REQUIRED
190
+ @EndUserText.label: 'Orders'
191
+ define root table entity ZRT_ORDER
192
+ {
193
+ key OrderId : abap.numc(8);
194
+ Name : zrt_order_name; // CDS simple type
195
+ Status : zrt_order_status; // CDS enumerated type
196
+ Note : abap.string null;
197
+ }
198
+ ```
199
+
200
+ CDS types are `<name>.drty.acds` sources (AFF format of abapGit, metadata `<name>.drty.json`
201
+ written by `rapt abapgit`):
202
+
203
+ ```cds
204
+ @EndUserText.label: 'Order status'
205
+ define type ZRT_ORDER_STATUS : abap.char(1) enum
206
+ {
207
+ @EndUserText.label: 'New'
208
+ NEW = initial;
209
+ @EndUserText.label: 'Open'
210
+ OPEN = 'O';
211
+ }
212
+ ```
213
+
214
+ The database keeps the base value (`'O'`); the behavior pool writes the constants as on SAP
215
+ (`Status = zrt_order_status-open`). SAP does not expose enumerated types in a RAP OData service:
216
+ in `standard` mode, CDS021; in `enhanced` mode, the `$metadata` has an `EnumType`, the JSON
217
+ carries the name of the member (`"Status": "OPEN"`) and `$filter=Status eq 'OPEN'` works.
218
+ Complete example: `fixtures/table-entity`.
219
+
220
+ ### SAP standard views
221
+
222
+ `I_Currency`, `I_UnitOfMeasure`, `I_Country`, `I_Language`, `I_Region`, `I_TimeZone` and their
223
+ text views, `I_CalendarDate` (calendar 1990-2060), `I_BusinessUserBasic` (the users of the IdP,
224
+ recorded on their first request) and `I_ExchangeRate` (rates to load) exist as on SAP, with their
225
+ data: just name them ([D44](DECISIONS.md)).
226
+
227
+ ```cds
228
+ @Consumption.valueHelpDefinition: [{ entity: { name: 'I_Currency', element: 'Currency' } }]
229
+ CurrencyCode,
230
+ ```
231
+
232
+ The entity of the value help is exposed automatically (as in RAP); the UI opens a selection
233
+ dialog with the descriptions. `additionalBinding` (`#FILTER`, `#RESULT`),
234
+ `useForValidation: true` and an entity with `@ObjectModel.resultSet.sizeCategory: #XS`
235
+ (drop-down list) are supported ([D56](DECISIONS.md)).
236
+
237
+ ### Behavior definition
238
+
239
+ A complete managed RAP BO, with or without draft: `strict ( 2 )`, `lock master` / `dependent`,
240
+ `etag master` / `dependent`, `global` / `instance` authorizations, managed, external or early
241
+ numbering, `create`/`update`/`delete` (internal, `precheck`, `features`), `readonly`,
242
+ `mandatory`, `readonly : update`, `features : instance` fields, `on modify` / `on save`
243
+ determinations, validations, actions (instance, static, factory, internal, with parameters and
244
+ results), functions, `with additional save`, `with unmanaged save`, `with privileged mode`,
245
+ projections (`use …`), side effects. Details and exceptions: [FEATURES.md](FEATURES.md).
246
+
247
+ **Draft** ([D54](DECISIONS.md)): `with draft;`, one `draft table` per entity (BDEF028
248
+ otherwise), `total etag`, `draft action Edit; draft action Activate optimized; draft action
249
+ Discard; draft action Resume; draft determine action Prepare;`. The draft table does not have to
250
+ exist: it is generated. The service has the `IsActiveEntity` key, `HasDraftEntity`,
251
+ `DraftAdministrativeData` and the actions of SAP; determinations and validations run on
252
+ activation. The UI follows Fiori Elements: *Editing Status* filter, *Locked by X*,
253
+ "Draft updated", *Keep Draft* when leaving the page ([D58](DECISIONS.md)).
254
+
255
+ **Collaborative draft** ([D59](DECISIONS.md)): `with collaborative draft;` and `draft action
256
+ Share;`; several users edit the same draft (*Invite* button, or *Edit* on an instance already in
257
+ draft).
258
+
259
+ ### Behavior pool (ABAP)
260
+
261
+ The ABAP Cloud code of the handlers and of the saver is transpiled as is: complete EML
262
+ (`READ`/`MODIFY ENTITIES`, `IN LOCAL MODE`, `BY \_assoc`, `EXECUTE`), `failed`/`reported`/`mapped`,
263
+ messages (`new_message_with_text`, message classes, exception classes), `AUTHORITY-CHECK`, ABAP
264
+ SQL reads on the tables and entities of the project, writes in `save_modified`.
265
+
266
+ Available released classes: JSON (`/ui2/cl_json`, `xco_cp_json`), encodings, dates
267
+ (`cl_abap_tstmp`, `xco_cp_time`), numbering (`cl_numberrange_runtime`), application log
268
+ (`cl_bali_*`), hashing, random numbers, regular expressions, RTTS ([UTILITIES.md](UTILITIES.md)),
269
+ background processing (`cl_bgmc_process_factory`) and e-mail (`cl_bcs_mail_message`)
270
+ ([D41](DECISIONS.md)), HTTP client and OData client proxy ([REMOTE_APIS.md](REMOTE_APIS.md)).
271
+
272
+ ### The `rapt/` configuration
273
+
274
+ | File | Content | Decision |
275
+ |---|---|---|
276
+ | `config.json` | `{ "mode": "standard" \| "enhanced", "ui": { "floorplans": …, "overview": … } }` | [D45](DECISIONS.md), [D53](DECISIONS.md) |
277
+ | `seed.json` | `{ "table": [ { "field": "value" } ] }`: data loaded on the first start of `rapt dev` (`SEED=auto`); random UUID keys | [D42](DECISIONS.md) |
278
+ | `seed.sql` | data in SQL | [D42](DECISIONS.md) |
279
+ | `authorizations.json` | roles of the IdP → authorization objects and values (`{claim:agency}`: value read from the token) | [D34](DECISIONS.md) |
280
+ | `number-ranges.json` | intervals of `cl_numberrange_runtime` | [D40](DECISIONS.md) |
281
+ | `mcp.json` | MCP tools and their descriptions | [D47](DECISIONS.md) |
282
+
283
+ ## 6. The generated UI
284
+
285
+ The List Report and the Object Page follow the `@UI` annotations: `headerInfo`, `lineItem`
286
+ (columns and table actions), `selectionField`, `identification` (header fields and actions),
287
+ `fieldGroup`, `facet` (sections, tables of the compositions, header), `dataPoint`,
288
+ `presentationVariant` (sorting), `hidden`, `multiLineText`, `textArrangement`, criticality,
289
+ `@Consumption.filter`. The complete list, annotation by annotation: [ANNOTATIONS.md](ANNOTATIONS.md).
290
+
291
+ - **Filters**: conditions as in SAP Fiori, several per field:
292
+
293
+ | Input | Meaning |
294
+ |---|---|
295
+ | `Rome` | text: contains "Rome" (case-insensitive); other types: equal |
296
+ | `=Rome`, `!=Rome` | equal, not equal |
297
+ | `>100`, `>=100`, `<100`, `<=100` | comparisons |
298
+ | `1...5` | range (bounds included) |
299
+ | `Ro*`, `*me`, `*om*` | starts with, ends with, contains |
300
+ | `<empty>` | empty (text: `''` or `null`) |
301
+ | `!(*om*)`, `!(1...5)`, `!(<empty>)` | exclusions: does not contain, outside the range, not empty… |
302
+
303
+ A string of digits (NUMC) is entered without its leading zeros (`3` finds `00000003`); a single
304
+ value looks for equality for a key or a field with a value help. Dates are entered in the
305
+ format of the language or in ISO (`Jun 1, 2026 - Jul 31, 2026`, `2026-06-01...2026-07-31`).
306
+ The icon of the field opens the dialog of SAP Fiori elements ([D68](DECISIONS.md)): *Search
307
+ and Select* (values of the value help, when the field has one) and *Define Conditions*
308
+ (operator and values per row: *equal to*, *contains*, *between*, *greater than*, *empty*, their
309
+ exclusions…, according to the type of the field and `@Consumption.filter.selectionType`); the
310
+ included conditions of a field are combined with "or", the exclusions with "and not". *Adapt
311
+ Filters* adds the columns as filters; *Clear* empties everything.
312
+ - **User views** (variants): the title of the List Report opens the view management: save the
313
+ filters, the visible columns and the sorting under a name, choose the default view. They are
314
+ saved per user in the database of the application ([D51](DECISIONS.md)).
315
+ - **Table settings** (gear icon): visible columns, sorting.
316
+ - **Object Page**: edit, create, delete, actions (parameter dialog), editable tables of the
317
+ compositions, value helps, breadcrumbs, messages of the BO.
318
+ - The buttons follow the authorizations and the feature control of the user.
319
+ - **Draft**: Create and Edit open a draft, each field is saved in it, Save activates, Cancel
320
+ discards; the list shows the instances being edited.
321
+
322
+ **Floorplans** ([D53](DECISIONS.md)): the List Report is the default on the command line. To
323
+ choose one: *RAP: Choose the floorplan of the application…* in VS Code (each floorplan is
324
+ described with the annotations it reads; the extension also asks for it before building or
325
+ starting an application whose floorplan was not chosen), or `rapt floorplan . Travel worklist`;
326
+ without arguments, `rapt floorplan .` lists the entity sets, their floorplan and whether it was
327
+ chosen. Both write `rapt/config.json` (the List Report too, once chosen):
328
+
329
+ ```json
330
+ {
331
+ "ui": {
332
+ "floorplans": { "Travel": "analyticalListPage" },
333
+ "overview": {
334
+ "title": "Travel Overview",
335
+ "cards": [
336
+ { "type": "kpi", "entitySet": "Travel", "title": "Revenue", "measure": "TotalPrice" },
337
+ { "type": "list", "entitySet": "Travel", "title": "Open travels", "filter": "OverallStatus eq 'O'", "top": 4 },
338
+ { "type": "chart", "entitySet": "Travel", "title": "By currency", "chart": "ByCurrency" }
339
+ ]
340
+ }
341
+ }
342
+ }
343
+ ```
344
+
345
+ | Floorplan | Annotations read |
346
+ |---|---|
347
+ | `listReport` | `lineItem`, `selectionField`, `presentationVariant` |
348
+ | `worklist` | one tab per qualified `@UI.selectionVariant` (`filter: 'OverallStatus EQ ''O'''`) |
349
+ | `analyticalListPage` | the first `@UI.chart` (dimension, measures, `#COLUMN`, `#BAR`, `#LINE`, `#PIE`, `#DONUT`), read with `$apply` |
350
+ | `formEntry` | the Object Page, for creation only |
351
+ | `overview` | `kpi`, `list`, `table`, `chart` cards of `rapt/config.json` |
352
+
353
+ ## 7. Developing: `rapt dev`
354
+
355
+ ```sh
356
+ rapt dev my-project [--port 8080] [--host 0.0.0.0] [--mode enhanced]
357
+ ```
358
+
359
+ - Builds the application, starts it with an embedded PGlite database (`.rapt/dev/data`),
360
+ rebuilds it on each save; a build in error keeps the previous one running.
361
+ - `http://localhost:8080/`: the **development launchpad** — the application (with the number of
362
+ its instances), the **documentation** (this documentation, with search), the `$metadata` and,
363
+ with `rapt/mcp.json`, the MCP server ([D49](DECISIONS.md)).
364
+ - Data kept between builds; database reset when the schema changes.
365
+ - No sign-in (`AUTH_MODE=none`); `DEV_ROLES` and `DEV_ATTRIBUTES` simulate a user and their
366
+ authorizations.
367
+
368
+ ## 8. AI agents: MCP server
369
+
370
+ `rapt mcp` writes `rapt/mcp.json`; the application then serves `/mcp`: one tool per operation of
371
+ the service (list, read, create, update, delete, actions), run with the checks of the BO. Guide:
372
+ [MCP.md](MCP.md).
373
+
374
+ ## 9. Launchpad
375
+
376
+ `rapt launchpad launchpad.json --out out/launchpad` builds an OpenUI5 launchpad in front of
377
+ several applications: a single origin, a single OIDC sign-in, tiles by role, counters, intent
378
+ navigation ([D37](DECISIONS.md)).
379
+
380
+ **One launchpad per workspace** ([D69](DECISIONS.md)): `launchpad.json`, titled "Launchpad", is
381
+ created next to the projects with the first application, then each application is added to it
382
+ when it is created — `rapt new` (complete BO) and the choice of the floorplan
383
+ (`rapt floorplan <src> <Set> <floorplan>`), or on demand `rapt launchpad add <src>`. The CLI looks
384
+ for the file in the project then its parent folders (up to the root of the git repository), and
385
+ otherwise creates it in the parent folder of the project; `--launchpad <file>` designates
386
+ another one, `--no-launchpad` adds nothing. The VS Code extension puts it next to the
387
+ `.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.
389
+
390
+ ```
391
+ rap-apps/
392
+ launchpad.json the launchpad of the workspace
393
+ helpdesk-tickets/ an abapGit project
394
+ project-tracker/
395
+ ```
396
+
397
+ ```json
398
+ {
399
+ "title": "Launchpad",
400
+ "apps": [
401
+ { "id": "helpdesk-tickets", "source": "helpdesk-tickets", "url": "http://localhost:8081/" },
402
+ { "id": "project-tracker", "source": "project-tracker", "url": "http://localhost:8082/" }
403
+ ],
404
+ "groups": [{ "title": "Applications", "tiles": [
405
+ { "title": "Tickets", "app": "helpdesk-tickets", "intent": "Ticket-manage", "icon": "sap-icon://list", "count": "Ticket" }
406
+ ] }]
407
+ }
408
+ ```
409
+
410
+ An application referenced by its sources (`source`) is built with the launchpad, in
411
+ `out/launchpad/apps/<id>`; `build` rather designates the folder of a `rapt build` done
412
+ separately. The content is organized in groups, or in **spaces and pages** ([D48](DECISIONS.md)):
413
+
414
+ ```json
415
+ {
416
+ "title": "Travel Agency",
417
+ "apps": [{ "id": "travel", "build": "out/travel", "url": "http://localhost:8080/" }],
418
+ "spaces": [{
419
+ "title": "Travels", "roles": ["travel_agent"],
420
+ "pages": [{ "title": "Management", "sections": [{
421
+ "title": "Travel Management",
422
+ "tiles": [{ "title": "Manage Travels", "app": "travel", "intent": "Travel-manage",
423
+ "icon": "sap-icon://flight", "count": "Travel" }]
424
+ }] }]
425
+ }]
426
+ }
427
+ ```
428
+
429
+ ## 10. Shipping
430
+
431
+ Two ways to deploy ([D69](DECISIONS.md)):
432
+
433
+ - **the launchpad with all its applications**: `rapt launchpad launchpad.json --out
434
+ out/launchpad`; `docker compose up` in this folder starts the launchpad, each application and
435
+ their databases;
436
+ - **one application alone** (standalone, without a launchpad): `rapt build my-project --out
437
+ out/travel` (Node.js, Docker, Cloud Foundry).
438
+
439
+ In VS Code, *Build the application…* asks which one.
440
+
441
+ - `rapt abapgit my-project`: the XML files to import the repository into SAP with abapGit
442
+ (`--check` in CI).
443
+ - Deployment (Docker, SAP BTP Cloud Foundry, local network, HTTPS): [DEPLOYMENT.md](DEPLOYMENT.md).
444
+
445
+ The folder of a generated application:
446
+
447
+ ```
448
+ model/model.json intermediate representation read by the runtime
449
+ db/schema.sql PostgreSQL tables and views (reference data of the standard views included)
450
+ odata/metadata.xml $metadata (CSDL with the UI annotations)
451
+ abap/ transpiled behavior pool; abap/src/: the ABAP given to the transpiler
452
+ ui/ OpenUI5 UI (List Report, Object Pages)
453
+ mcp/tools.json MCP tools (with rapt/mcp.json)
454
+ package.json, server.mjs, vendor/ startup; vendor/ bundles the runtime
455
+ Dockerfile, docker-compose.yml, keycloak/, manifest.yml container, PostgreSQL, Keycloak, Cloud Foundry
456
+ ```
457
+
458
+ ## 11. CLI reference
459
+
460
+ `rapt` comes with the VS Code extension (on the PATH of its terminals) or from npm
461
+ (`npm install -g open-rap-runtime`, [D65](DECISIONS.md)).
462
+
463
+
464
+ | Command | Purpose |
465
+ |---|---|
466
+ | `rapt check <src>` | diagnostics (`file:line:column: severity CODE message`), exit code 1 on error |
467
+ | `rapt build <src> --out <dir>` | generated application |
468
+ | `rapt dev <src>` | development loop |
469
+ | `rapt new <src> <Entity> [--prefix ZRT] [--description …]` | complete BO, added to the launchpad of the workspace |
470
+ | `rapt generate <src> <type> <name> [--from X] [--for Y] [--expose A,B] [--root]` | one object |
471
+ | `rapt floorplan <src> [<EntitySet> <floorplan>]` | floorplan of a root entity set; the application is added to the launchpad |
472
+ | `rapt abapgit <src> [--check]` | missing abapGit XML files |
473
+ | `rapt mcp <src>` | MCP tools (`rapt/mcp.json`) |
474
+ | `rapt launchpad <launchpad.json> --out <dir>` | launchpad, and the applications of their sources (`source`) |
475
+ | `rapt launchpad add <src> [--launchpad f]` | adds the application to the launchpad of the workspace (created when missing) |
476
+ | `rapt ir <src> [--out f]` | intermediate representation (JSON) |
477
+ | `rapt agent [<workspace>]` | MCP server (stdio) of rapt for AI coding agents (§13) |
478
+
479
+ Common options: `--service <SRVD>` (several service definitions), `--mode`, `--json` (output for
480
+ tools: one JSON object; one event per line for `rapt dev`), `--warnings-as-errors`. `rapt new`
481
+ and `rapt floorplan`: `--launchpad <file>` (another launchpad) and `--no-launchpad` (add nothing).
482
+
483
+ ## 12. Environment variables of the application
484
+
485
+ | Variable | Default | Purpose |
486
+ |---|---|---|
487
+ | `PORT`, `HOST` | 8080, 0.0.0.0 | listening |
488
+ | `PUBLIC_URL` | `http://localhost:<PORT>/` | public address (OIDC); Cloud Foundry route |
489
+ | `DATABASE_URL`, `DATABASE_CA` | — | PostgreSQL and certificate; bound Cloud Foundry service |
490
+ | `PGLITE_DIR` | — | embedded database (development) |
491
+ | `SCHEMA` | `apply` | `skip`: schema managed separately |
492
+ | `SEED` | — | `auto`: initial data on the first start |
493
+ | `AUTH_MODE` | `none` | `oidc`: bearer tokens and browser sessions |
494
+ | `DEV_USER`, `DEV_ROLES`, `DEV_ATTRIBUTES` | — | development user |
495
+ | `DEV_OAUTH`, `DEV_OAUTH_CLIENTS` | `on` in `rapt dev` | development OAuth 2.0 server under `/oauth` (D60) |
496
+ | `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_AUDIENCE`, `OIDC_REQUIRED_ROLE` | — | identity provider |
497
+ | `SESSION_SECRET` | — | signature of the sessions (shared with the launchpad) |
498
+ | `AUTHORIZATIONS_FILE` | — | roles replacing `rapt/authorizations.json` |
499
+ | `DESTINATION_<NAME>_URL`, `_USER`, `_PASSWORD`, `_TOKEN`, `_HEADERS` | — | remote APIs |
500
+ | `MAIL_SMTP_URL`, `MAIL_FROM` | — | e-mails |
501
+ | `MCP` | — | `off`: no MCP server |
502
+ | `UI` | — | `off`: no UI |
503
+ | `LOG_LEVEL` | `info` | log |
504
+
505
+ ## 12b. Web APIs and OAuth 2.0
506
+
507
+ A service bound as *OData V4 - Web API* (`BINDING_TYPE_CATEGORY` 1 in the SRVB, or
508
+ `rapt generate . binding ZAPI_TRAVEL_O4 --for ZUI_TRAVEL --binding-type webapi`) has neither UI
509
+ nor UI annotations; a draft BO only exposes its active instances there ([D60](DECISIONS.md)).
510
+
511
+ In development, `rapt dev` serves an OAuth 2.0 server under `/oauth`:
512
+
513
+ ```sh
514
+ # client credentials (machine to machine)
515
+ curl -u rapt-client:rapt-secret -d grant_type=client_credentials http://localhost:8080/oauth/token
516
+ curl -H "Authorization: Bearer <access_token>" http://localhost:8080/sap/opu/odata4/…/Travel
517
+
518
+ # authorization code + PKCE (Postman, Bruno…): client rapt-pkce, without a secret
519
+ # Auth URL http://localhost:8080/oauth/authorize Token URL http://localhost:8080/oauth/token
520
+ # Code challenge method SHA-256; the sign-in page asks for the user and their roles
521
+ ```
522
+
523
+ In production (`AUTH_MODE=oidc`), the tokens come from the IdP, with either flow; a *client
524
+ credentials* token acts on behalf of its client (technical user), with the roles of the token
525
+ (`OIDC_ROLES_CLAIM=scope` to read the scopes).
526
+
527
+ ## 13. For an AI agent writing a BO
528
+
529
+ An agent uses rapt in either of two ways ([D64](DECISIONS.md)):
530
+
531
+ - **Commands**: `rapt check <src> --json` and the other commands of §11. In VS Code, `rapt` is on
532
+ the PATH of the integrated terminals; elsewhere, `npm install -g open-rap-runtime`.
533
+ - **MCP server** `rapt agent`: in VS Code, the agent mode finds it by itself (*Open RAP Runtime*
534
+ extension, setting `rapt.agent.enabled`). Other clients start it:
535
+ `claude mcp add rapt -- rapt agent .` (Claude Code), or in a `.mcp.json` file
536
+ `{ "mcpServers": { "rapt": { "command": "rapt", "args": ["agent", "."] } } }`.
537
+
538
+ | Tool | Purpose |
539
+ |---|---|
540
+ | `rapt_projects` | the RAP projects of the workspace |
541
+ | `rapt_check` | diagnostics of a project (compiled, nothing written) |
542
+ | `rapt_object_types` | the object types of `rapt_generate` and the floorplans |
543
+ | `rapt_generate`, `rapt_new_business_object` | create an object, or a complete business object |
544
+ | `rapt_floorplan`, `rapt_abapgit` | floorplan of the UI, abapGit XML files |
545
+ | `rapt_docs_search`, `rapt_docs_read` | the documentation of Open RAP Runtime (this guide, codes, annotations, known gaps…) |
546
+
547
+ Then:
548
+
549
+ 1. Read the project (`src/`, `rapt/`); `rapt check <src> --json` gives the diagnostics with
550
+ absolute paths, line and column.
551
+ 2. Write the sources as in ADT; for a new object, prefer `rapt generate` (right file names and
552
+ XML); for a new BO, `rapt new`.
553
+ 3. After each change: `rapt check` until there are zero errors; the codes are explained in
554
+ [DIAGNOSTICS.md](DIAGNOSTICS.md); what is not supported is in
555
+ [KNOWN_GAPS.md](../KNOWN_GAPS.md) with the workaround.
556
+ 4. Check the behavior: `rapt dev <src> --json` (`ready` event), then the OData
557
+ (`/sap/opu/odata4/…`) or the MCP server (`/mcp`).
558
+ 5. Stay in `standard` mode if the BO must activate on SAP; only switch to `enhanced` for its
559
+ extensions, explicitly.
560
+ 6. Never edit `.rapt/` nor the `<standard>/…` files (generated).