@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
@@ -0,0 +1,322 @@
1
+ /**
2
+ * The application around the generated artifacts (decision D15): package.json, server.mjs,
3
+ * Dockerfile, docker-compose (application + PostgreSQL, Keycloak in the `oidc` profile) and the
4
+ * runtime embedded in `vendor/` (no private registry needed).
5
+ */
6
+ import { CFIGNORE, cloudFoundryManifest, deploySection } from "../deploy.js";
7
+ import { readFileSync } from "node:fs";
8
+ import path from "node:path";
9
+ import { authorizationClaims, destinationKeys } from "@open-rap/model";
10
+ import { keycloakRealm } from "../keycloak.js";
11
+ import { packageDir, vendorPackage } from "../vendor.js";
12
+ /**
13
+ * The destinations the ABAP code names with literals: `create_by_cloud_destination( i_name = '…' )`
14
+ * and `create_by_comm_arrangement( comm_scenario = '…' service_id = '…' )` (`SCENARIO.SERVICE`).
15
+ * Names given by variables are not found; the application reports them at run time.
16
+ */
17
+ export function findDestinations(sources) {
18
+ const names = new Set();
19
+ const value = (call, parameter) => new RegExp(`\\b${parameter}\\s*=\\s*['\`]([^'\`]+)['\`]`, "i").exec(call)?.[1];
20
+ for (const { content } of sources) {
21
+ const code = content.replace(/^\*.*$/gm, "").replace(/"[^\n]*$/gm, "");
22
+ for (const match of code.matchAll(/\b(create_by_cloud_destination|create_by_comm_arrangement)\s*\(([^)]*)\)/gi)) {
23
+ const call = match[2] ?? "";
24
+ if ((match[1] ?? "").toLowerCase() === "create_by_cloud_destination") {
25
+ const name = value(call, "i_name");
26
+ if (name !== undefined) {
27
+ names.add(name);
28
+ }
29
+ }
30
+ else {
31
+ const scenario = value(call, "comm_scenario");
32
+ const service = value(call, "service_id");
33
+ if (scenario !== undefined) {
34
+ names.add(service === undefined ? scenario : `${scenario}.${service}`);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ return [...names].sort();
40
+ }
41
+ /** The lines of .env.example for the destinations. */
42
+ function destinationLines(destinations) {
43
+ if (destinations.length === 0) {
44
+ return "";
45
+ }
46
+ const lines = [
47
+ "# Destinations of the remote APIs called by the behavior pool: the URL, then basic",
48
+ "# authentication (_USER, _PASSWORD), a bearer token (_TOKEN) or further headers (_HEADERS, JSON).",
49
+ "# Behind an outbound proxy: HTTPS_PROXY=... and NODE_USE_ENV_PROXY=1.",
50
+ ];
51
+ for (const name of destinations) {
52
+ const [key = ""] = destinationKeys(name);
53
+ lines.push(`# ${name}${destinationKeys(name).length > 1 ? ` (or DESTINATION_${destinationKeys(name)[1]}_URL for the whole scenario)` : ""}`);
54
+ lines.push(`DESTINATION_${key}_URL=`, `# DESTINATION_${key}_USER=`, `# DESTINATION_${key}_PASSWORD=`, `# DESTINATION_${key}_TOKEN=`, `# DESTINATION_${key}_HEADERS={"APIKey":"..."}`);
55
+ }
56
+ return `${lines.join("\n")}\n`;
57
+ }
58
+ const SERVER = `#!/usr/bin/env node
59
+ // Generated by Open RAP Runtime: starts the OData V4 service, the managed RAP runtime and the UI.
60
+ // Configuration by environment variables: see README.md and .env.example.
61
+ import { fileURLToPath } from "node:url";
62
+ import { start } from "@open-rap/runtime";
63
+
64
+ const server = await start({ dir: fileURLToPath(new URL(".", import.meta.url)) });
65
+ console.log(\`Service ready at \${server.url}\`);
66
+ for (const signal of ["SIGINT", "SIGTERM"]) {
67
+ process.once(signal, () => {
68
+ server.close().then(() => process.exit(0), () => process.exit(1));
69
+ });
70
+ }
71
+ `;
72
+ const DOCKERFILE = `# syntax=docker/dockerfile:1
73
+ # Generated by Open RAP Runtime.
74
+ FROM node:22-alpine AS dependencies
75
+ WORKDIR /app
76
+ COPY package.json .npmrc ./
77
+ COPY vendor ./vendor
78
+ RUN npm install --omit=dev --omit=optional --no-audit --no-fund
79
+
80
+ FROM node:22-alpine
81
+ ENV NODE_ENV=production PORT=8080
82
+ WORKDIR /app
83
+ COPY --from=dependencies /app/node_modules ./node_modules
84
+ COPY . .
85
+ USER node
86
+ EXPOSE 8080
87
+ HEALTHCHECK --interval=10s --timeout=3s --retries=5 CMD wget -qO- http://127.0.0.1:8080/health || exit 1
88
+ CMD ["node", "server.mjs"]
89
+ `;
90
+ const DOCKERIGNORE = `node_modules
91
+ data
92
+ .env
93
+ `;
94
+ function compose(name) {
95
+ return `# Generated by Open RAP Runtime.
96
+ # docker compose up --build application + PostgreSQL, no login (AUTH_MODE=none)
97
+ # AUTH_MODE=oidc docker compose --profile oidc up --build
98
+ # with Keycloak (user alice / alice), see README.md
99
+ services:
100
+ db:
101
+ image: postgres:16-alpine
102
+ environment:
103
+ POSTGRES_DB: app
104
+ POSTGRES_USER: app
105
+ POSTGRES_PASSWORD: app
106
+ healthcheck:
107
+ test: ["CMD-SHELL", "pg_isready -U app -d app"]
108
+ interval: 5s
109
+ retries: 20
110
+ volumes:
111
+ - db-data:/var/lib/postgresql/data
112
+
113
+ app:
114
+ build: .
115
+ image: ${name}:latest
116
+ environment:
117
+ DATABASE_URL: postgres://app:app@db:5432/app
118
+ PUBLIC_URL: http://localhost:8080/
119
+ AUTH_MODE: \${AUTH_MODE:-none}
120
+ OIDC_ISSUER: http://localhost:8180/realms/rapt
121
+ OIDC_DISCOVERY_URL: http://keycloak:8080/realms/rapt/.well-known/openid-configuration
122
+ OIDC_CLIENT_ID: rapt-app
123
+ OIDC_CLIENT_SECRET: rapt-app-secret
124
+ SESSION_SECRET: \${SESSION_SECRET:-change-me-change-me-change-me-change-me}
125
+ ports:
126
+ - "8080:8080"
127
+ depends_on:
128
+ db:
129
+ condition: service_healthy
130
+
131
+ keycloak:
132
+ image: quay.io/keycloak/keycloak:26.0
133
+ profiles: ["oidc"]
134
+ command: start-dev --import-realm
135
+ environment:
136
+ KC_BOOTSTRAP_ADMIN_USERNAME: admin
137
+ KC_BOOTSTRAP_ADMIN_PASSWORD: admin
138
+ KC_HOSTNAME: http://localhost:8180
139
+ KC_HOSTNAME_BACKCHANNEL_DYNAMIC: "true"
140
+ volumes:
141
+ - ./keycloak:/opt/keycloak/data/import:ro
142
+ ports:
143
+ - "8180:8080"
144
+
145
+ volumes:
146
+ db-data:
147
+ `;
148
+ }
149
+ /** The realm of the Keycloak of docker-compose: the client rapt-app and the roles of the application. */
150
+ function realm(model) {
151
+ return keycloakRealm({
152
+ clientId: "rapt-app",
153
+ clientName: "Application generated by Open RAP Runtime",
154
+ secret: "rapt-app-secret",
155
+ url: "http://localhost:8080",
156
+ roles: model.authorizations?.roles ?? [],
157
+ claims: authorizationClaims(model.authorizations),
158
+ });
159
+ }
160
+ /** The mails of cl_bcs_mail_message (D41): without MAIL_SMTP_URL they stay in the table rapt_mail. */
161
+ const MAIL_LINES = `
162
+ # Mails of the behavior pool (cl_bcs_mail_message): SMTP server, e.g. smtp://user:password@smtp.example.com:587
163
+ # or smtps://…:465; without it, the mails stay in the table rapt_mail. MAIL_FROM: default sender.
164
+ MAIL_SMTP_URL=
165
+ MAIL_FROM=
166
+ `;
167
+ const ENV_EXAMPLE = `# Configuration of the generated application (all optional except the database).
168
+ PORT=8080
169
+ PUBLIC_URL=http://localhost:8080/
170
+ LOG_LEVEL=info
171
+ # PostgreSQL, or PGLITE_DIR=./data for an embedded database (development, npm install with optional dependencies)
172
+ DATABASE_URL=postgres://app:app@localhost:5432/app
173
+ # SCHEMA=skip to manage the schema yourself (db/schema.sql)
174
+ SCHEMA=apply
175
+ # auto: load db/seed.json and db/seed.sql (rapt/seed.json, rapt/seed.sql) when the tables are empty
176
+ # SEED=auto
177
+ # none (development user DEV_USER) or oidc
178
+ AUTH_MODE=none
179
+ DEV_USER=DEVELOPER
180
+ # roles of the development user (default: every authorization) and its claims, e.g. {"agency":["070001"]}
181
+ # DEV_ROLES=travel_agent
182
+ # DEV_ATTRIBUTES=
183
+ # roles replacing those of rapt/authorizations.json
184
+ # AUTHORIZATIONS_FILE=./authorizations.json
185
+ OIDC_ISSUER=http://localhost:8180/realms/rapt
186
+ OIDC_DISCOVERY_URL=
187
+ OIDC_AUDIENCE=
188
+ OIDC_CLIENT_ID=rapt-app
189
+ OIDC_CLIENT_SECRET=rapt-app-secret
190
+ OIDC_REQUIRED_ROLE=
191
+ SESSION_SECRET=change-me-change-me-change-me-change-me
192
+ `;
193
+ function authorizationsSection(model) {
194
+ const roles = model.authorizations?.roles ?? [];
195
+ if (roles.length === 0) {
196
+ return "";
197
+ }
198
+ const claims = authorizationClaims(model.authorizations);
199
+ return `
200
+ ## Authorizations
201
+
202
+ The behavior pool checks authorization objects (AUTHORITY-CHECK). The roles of the identity
203
+ provider give the authorizations of \`rapt/authorizations.json\` (in \`model/model.json\`; replace
204
+ them with \`AUTHORIZATIONS_FILE\`). In the Keycloak of docker-compose, \`alice\` has every role.
205
+
206
+ | Role | Description |
207
+ |---|---|
208
+ ${roles.map((r) => `| \`${r.name}\` | ${r.description ?? ""} |`).join("\n")}
209
+ ${claims.length === 0 ? "" : `
210
+ Values read from the token: ${claims.map((c) => `\`${c}\``).join(", ")} — in Keycloak, a user attribute of the same name (Users → user → Attributes).
211
+ `}`;
212
+ }
213
+ function destinationsSection(destinations) {
214
+ const rows = destinations.map((d) => `| \`${d}\` | ${destinationKeys(d).map((k) => `\`DESTINATION_${k}_URL\``).join(", then ")} |`);
215
+ return `
216
+ ## Remote APIs
217
+
218
+ The behavior pool calls remote APIs (HTTP client, OData client proxy). Each destination is
219
+ configured by environment variables: \`DESTINATION_<NAME>_URL\`, then \`_USER\` and \`_PASSWORD\`
220
+ (basic authentication), \`_TOKEN\` (bearer token) or \`_HEADERS\` (a JSON object of headers, an
221
+ API key for example). The credentials stay in the server: the ABAP code only sees the URL.
222
+ ${rows.length === 0 ? "" : `
223
+ | Destination in the ABAP code | Variable |
224
+ |---|---|
225
+ ${rows.join("\n")}
226
+ `}`;
227
+ }
228
+ function readme(model, name, destinations = []) {
229
+ return `# ${name}
230
+
231
+ Application generated by [Open RAP Runtime](https://clementringot.github.io/RAP-Transpiler) from the
232
+ RAP service definition \`${model.service.name}\`: an OData V4 service (\`${model.service.path}\`), the
233
+ managed RAP runtime with the transpiled behavior pool, and an OpenUI5 UI (List Report / Object
234
+ Page) at \`/ui/\`.
235
+
236
+ ## Run
237
+
238
+ With Docker:
239
+
240
+ \`\`\`sh
241
+ docker compose up --build # http://localhost:8080/ (no login)
242
+ \`\`\`
243
+
244
+ With Node.js 22 and a PostgreSQL database:
245
+
246
+ \`\`\`sh
247
+ npm install
248
+ DATABASE_URL=postgres://user:password@localhost:5432/app npm start
249
+ \`\`\`
250
+
251
+ For a quick try without PostgreSQL: \`npm install\` (with its optional dependencies) then
252
+ \`PGLITE_DIR=./data npm start\` (embedded PostgreSQL, development only).
253
+
254
+ ## Login (OIDC)
255
+
256
+ \`AUTH_MODE=oidc\` checks bearer tokens of API clients and opens browser sessions (authorization
257
+ code with PKCE). With the Keycloak of docker-compose (realm \`rapt\`, user \`alice\` / \`alice\`):
258
+
259
+ \`\`\`sh
260
+ AUTH_MODE=oidc docker compose --profile oidc up --build
261
+ \`\`\`
262
+
263
+ The variables are listed in \`.env.example\`.
264
+ ${authorizationsSection(model)}${destinations.length === 0 ? "" : destinationsSection(destinations)}${deploySection(name, "application")}
265
+ ## Content
266
+
267
+ | Folder | Content |
268
+ |---|---|
269
+ | \`model/model.json\` | intermediate representation read by the runtime |
270
+ | \`db/schema.sql\` | PostgreSQL tables and views (applied at start-up unless \`SCHEMA=skip\`) |
271
+ | \`odata/metadata.xml\` | \`$metadata\` of the service |
272
+ | \`abap/\` | transpiled behavior pool; \`abap/src/\` holds the ABAP given to the transpiler |
273
+ | \`ui/\` | OpenUI5 application |
274
+ | \`vendor/\` | the runtime of Open RAP Runtime (MIT) |
275
+ `;
276
+ }
277
+ export function generateScaffold(model, diagnostics, options = {}) {
278
+ const runtimeDir = packageDir("@open-rap/runtime", "runtime", options.runtimeDir);
279
+ const modelDir = packageDir("@open-rap/model", "model");
280
+ if (runtimeDir === undefined || modelDir === undefined) {
281
+ diagnostics.error("APP001", "the @open-rap/runtime and @open-rap/model packages (built: dist/) are needed to embed the runtime; give --runtime <dir> or run pnpm build");
282
+ return [];
283
+ }
284
+ const runtime = JSON.parse(readFileSync(path.join(runtimeDir, "package.json"), "utf8"));
285
+ const version = (name) => runtime.dependencies?.[name] ?? runtime.devDependencies?.[name] ?? "*";
286
+ const name = (model.service.binding || model.service.name).toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[._-]+/, "") || "rapt-app";
287
+ const openui5 = Object.keys(runtime.devDependencies ?? {}).filter((d) => d.startsWith("@openui5/"));
288
+ const pkg = {
289
+ name,
290
+ version: "1.0.0",
291
+ private: true,
292
+ description: `OData V4 service ${model.service.name}, generated by Open RAP Runtime`,
293
+ type: "module",
294
+ engines: { node: ">=22" },
295
+ scripts: { start: "node server.mjs" },
296
+ dependencies: {
297
+ "@open-rap/runtime": "file:vendor/open-rap-runtime",
298
+ "@open-rap/model": "file:vendor/open-rap-model",
299
+ "@abaplint/runtime": version("@abaplint/runtime"),
300
+ ...Object.fromEntries(openui5.map((d) => [d, version(d)])),
301
+ "less-openui5": version("less-openui5"),
302
+ },
303
+ optionalDependencies: { "@electric-sql/pglite": version("@electric-sql/pglite") },
304
+ overrides: { "@open-rap/model": "$@open-rap/model" },
305
+ };
306
+ return [
307
+ { path: "package.json", content: `${JSON.stringify(pkg, null, 2)}\n` },
308
+ { path: ".npmrc", content: "install-links=true\n" },
309
+ { path: "server.mjs", content: SERVER },
310
+ { path: "Dockerfile", content: DOCKERFILE },
311
+ { path: ".dockerignore", content: DOCKERIGNORE },
312
+ { path: "manifest.yml", content: cloudFoundryManifest(name, { database: true }) },
313
+ { path: ".cfignore", content: CFIGNORE },
314
+ { path: "docker-compose.yml", content: compose(name) },
315
+ { path: "keycloak/rapt-realm.json", content: `${JSON.stringify(realm(model), null, 2)}\n` },
316
+ { path: ".env.example", content: `${ENV_EXAMPLE}${destinationLines(options.destinations ?? [])}${model.services?.mail === true ? MAIL_LINES : ""}` },
317
+ { path: "README.md", content: readme(model, name, options.destinations ?? []) },
318
+ ...vendorPackage(modelDir, "open-rap-model", {}),
319
+ ...vendorPackage(runtimeDir, "open-rap-runtime", { "@open-rap/model": "file:../open-rap-model" }),
320
+ ];
321
+ }
322
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/gen/app/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * $metadata (CSDL XML, OData V4) of the service, with the UI, Common, Core, Capabilities and
3
+ * Measures annotations derived from the CDS annotations and the behavior (PLAN.md §6.5).
4
+ */
5
+ import { type AnnotationObject, type Model, type ODataService } from "@open-rap/model";
6
+ /**
7
+ * The AllowedExpressions of a filter field (FilterExpressionRestrictions) from
8
+ * `@Consumption.filter.selectionType` and `multipleSelections` (D57, D68); undefined: any condition.
9
+ */
10
+ export declare function allowedFilterExpressions(annotations: AnnotationObject): "SingleValue" | "SingleRange" | "MultiRange" | undefined;
11
+ export declare function generateCsdl(model: Model, service?: ODataService): string;