@linkup-ai/abap-ai 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 (119) hide show
  1. package/README.md +389 -0
  2. package/dist/adt-client.js +383 -0
  3. package/dist/cli/activate.js +127 -0
  4. package/dist/cli/init.js +559 -0
  5. package/dist/cli/link.js +148 -0
  6. package/dist/cli/remove.js +83 -0
  7. package/dist/cli/status.js +231 -0
  8. package/dist/cli/systems.js +72 -0
  9. package/dist/cli.js +92 -0
  10. package/dist/index.js +1442 -0
  11. package/dist/knowledge/abap/abap-dictionary.md +199 -0
  12. package/dist/knowledge/abap/abap-sql.md +296 -0
  13. package/dist/knowledge/abap/amdp.md +273 -0
  14. package/dist/knowledge/abap/clean-code.md +293 -0
  15. package/dist/knowledge/abap/cloud-background-processing.md +250 -0
  16. package/dist/knowledge/abap/cloud-communication.md +265 -0
  17. package/dist/knowledge/abap/cloud-development.md +176 -0
  18. package/dist/knowledge/abap/cloud-extensibility.md +252 -0
  19. package/dist/knowledge/abap/cloud-released-apis.md +261 -0
  20. package/dist/knowledge/abap/constructor-expressions.md +289 -0
  21. package/dist/knowledge/abap/enhancements.md +232 -0
  22. package/dist/knowledge/abap/exceptions.md +271 -0
  23. package/dist/knowledge/abap/internal-tables.md +205 -0
  24. package/dist/knowledge/abap/object-orientation.md +298 -0
  25. package/dist/knowledge/abap/performance.md +216 -0
  26. package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
  27. package/dist/knowledge/abap/rap-business-events.md +216 -0
  28. package/dist/knowledge/abap/rap-draft.md +191 -0
  29. package/dist/knowledge/abap/rap-eml.md +453 -0
  30. package/dist/knowledge/abap/rap-end-to-end.md +486 -0
  31. package/dist/knowledge/abap/rap-feature-control.md +185 -0
  32. package/dist/knowledge/abap/rap-numbering.md +280 -0
  33. package/dist/knowledge/abap/rap-service-exposure.md +163 -0
  34. package/dist/knowledge/abap/rap-unmanaged.md +468 -0
  35. package/dist/knowledge/abap/string-processing.md +180 -0
  36. package/dist/knowledge/abap/unit-testing.md +303 -0
  37. package/dist/knowledge/abap-cds/access-control.md +241 -0
  38. package/dist/knowledge/abap-cds/annotations.md +331 -0
  39. package/dist/knowledge/abap-cds/associations.md +254 -0
  40. package/dist/knowledge/abap-cds/expressions.md +230 -0
  41. package/dist/knowledge/abap-cds/functions.md +245 -0
  42. package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
  43. package/dist/knowledge/cap/authentication.md +278 -0
  44. package/dist/knowledge/cap/cdl-syntax.md +247 -0
  45. package/dist/knowledge/cap/cql-queries.md +266 -0
  46. package/dist/knowledge/cap/deployment.md +343 -0
  47. package/dist/knowledge/cap/event-handlers.md +287 -0
  48. package/dist/knowledge/cap/fiori-integration.md +303 -0
  49. package/dist/knowledge/cap/service-definitions.md +287 -0
  50. package/dist/knowledge/fiori/annotations.md +347 -0
  51. package/dist/knowledge/fiori/deployment.md +340 -0
  52. package/dist/knowledge/fiori/fiori-elements.md +332 -0
  53. package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
  54. package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
  55. package/dist/knowledge/fiori/ui5-controllers.md +358 -0
  56. package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
  57. package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
  58. package/dist/knowledge/fiori/ui5-manifest.md +411 -0
  59. package/dist/knowledge/fiori/ui5-routing.md +303 -0
  60. package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
  61. package/dist/license-guard.js +81 -0
  62. package/dist/logger.js +114 -0
  63. package/dist/postinstall.js +165 -0
  64. package/dist/security-audit.js +136 -0
  65. package/dist/security-policy.js +322 -0
  66. package/dist/system-profile.js +207 -0
  67. package/dist/tools/abap-doc.js +72 -0
  68. package/dist/tools/abapgit.js +161 -0
  69. package/dist/tools/activate.js +71 -0
  70. package/dist/tools/atc-check.js +117 -0
  71. package/dist/tools/auth-object.js +56 -0
  72. package/dist/tools/breakpoints.js +76 -0
  73. package/dist/tools/call-hierarchy.js +84 -0
  74. package/dist/tools/cds-annotations.js +98 -0
  75. package/dist/tools/cds-dependencies.js +65 -0
  76. package/dist/tools/check.js +47 -0
  77. package/dist/tools/code-completion.js +70 -0
  78. package/dist/tools/code-coverage.js +111 -0
  79. package/dist/tools/create-amdp.js +111 -0
  80. package/dist/tools/create-dcl.js +81 -0
  81. package/dist/tools/create-transport.js +38 -0
  82. package/dist/tools/create.js +285 -0
  83. package/dist/tools/data-preview.js +37 -0
  84. package/dist/tools/delete.js +45 -0
  85. package/dist/tools/deploy-bsp.js +298 -0
  86. package/dist/tools/discovery.js +59 -0
  87. package/dist/tools/element-info.js +93 -0
  88. package/dist/tools/enhancements.js +186 -0
  89. package/dist/tools/extract-method.js +44 -0
  90. package/dist/tools/function-group.js +59 -0
  91. package/dist/tools/knowledge.js +275 -0
  92. package/dist/tools/lock-object.js +75 -0
  93. package/dist/tools/message-class.js +67 -0
  94. package/dist/tools/navigate.js +80 -0
  95. package/dist/tools/number-range.js +57 -0
  96. package/dist/tools/object-documentation.js +43 -0
  97. package/dist/tools/object-structure.js +78 -0
  98. package/dist/tools/object-versions.js +57 -0
  99. package/dist/tools/package-contents.js +60 -0
  100. package/dist/tools/pretty-printer.js +35 -0
  101. package/dist/tools/publish-binding.js +49 -0
  102. package/dist/tools/quick-fix.js +69 -0
  103. package/dist/tools/read.js +172 -0
  104. package/dist/tools/refactor-rename.js +60 -0
  105. package/dist/tools/release-transport.js +24 -0
  106. package/dist/tools/released-apis.js +51 -0
  107. package/dist/tools/repository-tree.js +90 -0
  108. package/dist/tools/scaffold-rap.js +642 -0
  109. package/dist/tools/search.js +73 -0
  110. package/dist/tools/shared/data-format.js +101 -0
  111. package/dist/tools/sql-console.js +17 -0
  112. package/dist/tools/system-info.js +271 -0
  113. package/dist/tools/traces.js +66 -0
  114. package/dist/tools/transport-contents.js +83 -0
  115. package/dist/tools/transports.js +68 -0
  116. package/dist/tools/unit-test.js +135 -0
  117. package/dist/tools/where-used.js +59 -0
  118. package/dist/tools/write.js +120 -0
  119. package/package.json +50 -0
@@ -0,0 +1,642 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.abapScaffoldRap = abapScaffoldRap;
4
+ const create_js_1 = require("./create.js");
5
+ const write_js_1 = require("./write.js");
6
+ const activate_js_1 = require("./activate.js");
7
+ const system_profile_js_1 = require("../system-profile.js");
8
+ // ---------------------------------------------------------------------------
9
+ // Step runner
10
+ // ---------------------------------------------------------------------------
11
+ async function run(steps, step, objectName, objectType, fn) {
12
+ try {
13
+ await fn();
14
+ steps.push({ step, object: objectName, type: objectType, status: "ok", message: "OK" });
15
+ return true;
16
+ }
17
+ catch (err) {
18
+ const message = err instanceof Error ? err.message : String(err);
19
+ steps.push({ step, object: objectName, type: objectType, status: "error", message });
20
+ return false;
21
+ }
22
+ }
23
+ function formatSummary(steps, success, warnings) {
24
+ const header = success
25
+ ? "✅ Stack RAP criado com sucesso!\n"
26
+ : "⚠️ Stack RAP criado parcialmente — verifique os erros abaixo:\n";
27
+ const rows = steps.map((s) => {
28
+ const icon = s.status === "ok" ? "✓" : "✗";
29
+ return ` ${icon} [${s.step.padEnd(8)}] ${s.type.padEnd(10)} ${s.object}${s.status === "error" ? ` ERRO: ${s.message}` : ""}`;
30
+ });
31
+ const warnBlock = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
32
+ return warnBlock + header + rows.join("\n");
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Helper: create + write + activate
36
+ // ---------------------------------------------------------------------------
37
+ async function createObject(steps, name, type, desc, pkg, tr, srvdName, bindingType) {
38
+ return run(steps, "create", name, type, () => (0, create_js_1.abapCreate)({ object_type: type, object_name: name, description: desc, package: pkg, transport_request: tr, srvd_name: srvdName, binding_type: bindingType }).then(() => undefined));
39
+ }
40
+ async function writeSource(steps, name, type, source) {
41
+ return run(steps, "write", name, type, () => (0, write_js_1.abapWrite)({ object_type: type, object_name: name, source }).then(() => undefined));
42
+ }
43
+ async function activateObject(steps, name, type) {
44
+ return run(steps, "activate", name, type, () => (0, activate_js_1.abapActivate)({ object_type: type, object_name: name }).then(() => undefined));
45
+ }
46
+ // Shortcut: create + write + activate
47
+ async function createWriteActivate(steps, name, type, desc, source, pkg, tr) {
48
+ if (!(await createObject(steps, name, type, desc, pkg, tr)))
49
+ return false;
50
+ if (!(await writeSource(steps, name, type, source)))
51
+ return false;
52
+ if (!(await activateObject(steps, name, type)))
53
+ return false;
54
+ return true;
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Templates
58
+ // ---------------------------------------------------------------------------
59
+ function tplCdsInterfaceRoot(name, desc, tableName, childEntities) {
60
+ const compositions = childEntities.map((c) => ` composition [0..*] of ${c} as _${aliasFrom(c)}`).join("\n");
61
+ const compFields = childEntities.map((c) => ` _${aliasFrom(c)}`).join(",\n");
62
+ return `@AccessControl.authorizationCheck: #CHECK
63
+ @Metadata.allowExtensions: true
64
+ @EndUserText.label: '${desc}'
65
+
66
+ define root view entity ${name}
67
+ as select from ${tableName.toLowerCase()}
68
+ ${compositions ? compositions + "\n" : ""}{
69
+ key key_field as KeyField
70
+ }`;
71
+ // NOTE: Este é um template mínimo ativável.
72
+ // O Claude deve usar abap_knowledge('rap-end-to-end') para gerar o CDS completo
73
+ // com os campos reais da tabela e depois sobrescrever com abap_write.
74
+ }
75
+ function tplCdsInterfaceChild(name, desc, tableName, parentName) {
76
+ return `@AccessControl.authorizationCheck: #CHECK
77
+ @Metadata.allowExtensions: true
78
+ @EndUserText.label: '${desc}'
79
+
80
+ define view entity ${name}
81
+ as select from ${tableName.toLowerCase()}
82
+ association to parent ${parentName} as _${aliasFrom(parentName)}
83
+ on $projection.ParentKey = _${aliasFrom(parentName)}.KeyField
84
+ {
85
+ key parent_key as ParentKey,
86
+ key item_key as ItemKey,
87
+ _${aliasFrom(parentName)}
88
+ }`;
89
+ }
90
+ function tplBdefManaged(rootCds, childCds, withDraft, withFeatureControl, events) {
91
+ const handlerClass = `zbp_${rootCds.toLowerCase()}`;
92
+ const lines = [];
93
+ lines.push(`managed implementation in class ${handlerClass} unique;`);
94
+ lines.push("strict ( 2 );");
95
+ if (withDraft)
96
+ lines.push("with draft;");
97
+ lines.push("");
98
+ // Root entity
99
+ lines.push(`define behavior for ${rootCds} alias ${aliasFrom(rootCds)}`);
100
+ lines.push(`persistent table ${rootCds.toLowerCase().replace(/^z[ic]_/, "ztab_")}`);
101
+ if (withDraft)
102
+ lines.push(`draft table ${rootCds.toLowerCase().replace(/^z[ic]_/, "ztab_")}_d`);
103
+ lines.push("etag master LocalLastChangedAt");
104
+ if (withDraft) {
105
+ lines.push("lock master total etag LastChangedAt");
106
+ }
107
+ else {
108
+ lines.push("lock master");
109
+ }
110
+ lines.push("authorization master ( global )");
111
+ lines.push("{");
112
+ lines.push(" field ( readonly ) KeyField;");
113
+ lines.push(" field ( readonly ) CreatedBy, CreatedAt, LastChangedBy, LastChangedAt, LocalLastChangedAt;");
114
+ lines.push("");
115
+ lines.push(" create;");
116
+ lines.push(" update;");
117
+ lines.push(" delete;");
118
+ if (withDraft) {
119
+ lines.push("");
120
+ lines.push(" draft action Edit;");
121
+ lines.push(" draft action Activate optimized;");
122
+ lines.push(" draft action Discard;");
123
+ lines.push(" draft action Resume;");
124
+ lines.push(" draft determine action Prepare { }");
125
+ }
126
+ if (withFeatureControl) {
127
+ lines.push("");
128
+ lines.push(" // Feature control — ajuste as actions e fields conforme necessário");
129
+ lines.push(" // action ( features : instance ) myAction result [1] $self;");
130
+ lines.push(" // field ( features : instance ) Status;");
131
+ }
132
+ if (events.length > 0) {
133
+ lines.push("");
134
+ for (const evt of events) {
135
+ lines.push(` event ${evt};`);
136
+ }
137
+ }
138
+ lines.push("");
139
+ lines.push(` mapping for ${rootCds.toLowerCase().replace(/^z[ic]_/, "ztab_")} corresponding;`);
140
+ for (const child of childCds) {
141
+ if (withDraft) {
142
+ lines.push(` association _${aliasFrom(child)} { create; with draft; }`);
143
+ }
144
+ else {
145
+ lines.push(` association _${aliasFrom(child)} { create; }`);
146
+ }
147
+ }
148
+ lines.push("}");
149
+ // Child entities
150
+ for (const child of childCds) {
151
+ lines.push("");
152
+ lines.push(`define behavior for ${child} alias ${aliasFrom(child)}`);
153
+ lines.push(`persistent table ${child.toLowerCase().replace(/^z[ic]_/, "ztab_")}`);
154
+ if (withDraft)
155
+ lines.push(`draft table ${child.toLowerCase().replace(/^z[ic]_/, "ztab_")}_d`);
156
+ lines.push("etag master LocalLastChangedAt");
157
+ lines.push(`lock dependent by _${aliasFrom(rootCds)}`);
158
+ lines.push(`authorization dependent by _${aliasFrom(rootCds)}`);
159
+ lines.push("{");
160
+ lines.push(" update;");
161
+ lines.push(" delete;");
162
+ lines.push("");
163
+ lines.push(` mapping for ${child.toLowerCase().replace(/^z[ic]_/, "ztab_")} corresponding;`);
164
+ if (withDraft) {
165
+ lines.push(` association _${aliasFrom(rootCds)} { with draft; }`);
166
+ }
167
+ else {
168
+ lines.push(` association _${aliasFrom(rootCds)};`);
169
+ }
170
+ lines.push("}");
171
+ }
172
+ return lines.join("\n");
173
+ }
174
+ function tplBdefUnmanaged(rootCds, childCds) {
175
+ const handlerClass = `zbp_${rootCds.toLowerCase()}`;
176
+ const lines = [];
177
+ lines.push(`unmanaged implementation in class ${handlerClass} unique;`);
178
+ lines.push("strict ( 2 );");
179
+ lines.push("");
180
+ lines.push(`define behavior for ${rootCds} alias ${aliasFrom(rootCds)}`);
181
+ lines.push("lock master");
182
+ lines.push("authorization master ( instance )");
183
+ lines.push("etag master LocalLastChangedAt");
184
+ lines.push("{");
185
+ lines.push(" create;");
186
+ lines.push(" update;");
187
+ lines.push(" delete;");
188
+ lines.push("");
189
+ lines.push(` mapping for ${rootCds.toLowerCase().replace(/^z[ic]_/, "ztab_")} corresponding;`);
190
+ for (const child of childCds) {
191
+ lines.push(` association _${aliasFrom(child)} { create; }`);
192
+ }
193
+ lines.push("}");
194
+ for (const child of childCds) {
195
+ lines.push("");
196
+ lines.push(`define behavior for ${child} alias ${aliasFrom(child)}`);
197
+ lines.push(`lock dependent by _${aliasFrom(rootCds)}`);
198
+ lines.push(`authorization dependent by _${aliasFrom(rootCds)}`);
199
+ lines.push("{");
200
+ lines.push(" update;");
201
+ lines.push(" delete;");
202
+ lines.push(` mapping for ${child.toLowerCase().replace(/^z[ic]_/, "ztab_")} corresponding;`);
203
+ lines.push(` association _${aliasFrom(rootCds)};`);
204
+ lines.push("}");
205
+ }
206
+ return lines.join("\n");
207
+ }
208
+ function tplHandlerClass(rootCds) {
209
+ const className = `zbp_${rootCds.toLowerCase()}`;
210
+ return `CLASS ${className} DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF ${rootCds}.
211
+ ENDCLASS.
212
+ CLASS ${className} IMPLEMENTATION.
213
+ ENDCLASS.`;
214
+ }
215
+ function tplHandlerClassUnmanaged(rootCds) {
216
+ const className = `zbp_${rootCds.toLowerCase()}`;
217
+ const alias = aliasFrom(rootCds);
218
+ return `CLASS ${className} DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF ${rootCds}.
219
+ PUBLIC SECTION.
220
+ " Buffer compartilhado entre handler e saver
221
+ CLASS-DATA: gt_create TYPE STANDARD TABLE OF ${rootCds.toLowerCase().replace(/^z[ic]_/, "zs_")}_create,
222
+ gt_update TYPE STANDARD TABLE OF ${rootCds.toLowerCase().replace(/^z[ic]_/, "zs_")}_update,
223
+ gt_delete TYPE STANDARD TABLE OF ${rootCds.toLowerCase().replace(/^z[ic]_/, "zs_")}_delete.
224
+ ENDCLASS.
225
+ CLASS ${className} IMPLEMENTATION.
226
+ ENDCLASS.`;
227
+ }
228
+ function tplCdsProjectionRoot(projName, interfaceName, desc, childProj, childIntf) {
229
+ const lines = [];
230
+ lines.push(`@AccessControl.authorizationCheck: #CHECK`);
231
+ lines.push(`@Metadata.allowExtensions: true`);
232
+ lines.push(`@Search.searchable: true`);
233
+ lines.push(`@EndUserText.label: '${desc}'`);
234
+ lines.push("");
235
+ lines.push(`define root view entity ${projName}`);
236
+ lines.push(` provider contract transactional_query`);
237
+ lines.push(` as projection on ${interfaceName}`);
238
+ lines.push("{");
239
+ lines.push(" key KeyField,");
240
+ // Redirect child compositions
241
+ for (let i = 0; i < childProj.length; i++) {
242
+ lines.push(` _${aliasFrom(childIntf[i])} : redirected to composition child ${childProj[i]},`);
243
+ }
244
+ lines.push(" CreatedBy, CreatedAt, LastChangedBy, LastChangedAt, LocalLastChangedAt");
245
+ lines.push("}");
246
+ return lines.join("\n");
247
+ }
248
+ function tplCdsProjectionChild(projName, interfaceName, desc, parentProj, parentIntf) {
249
+ return `@AccessControl.authorizationCheck: #CHECK
250
+ @Metadata.allowExtensions: true
251
+ @EndUserText.label: '${desc}'
252
+
253
+ define view entity ${projName}
254
+ as projection on ${interfaceName}
255
+ {
256
+ key ParentKey,
257
+ key ItemKey,
258
+ _${aliasFrom(parentIntf)} : redirected to parent ${parentProj},
259
+ LocalLastChangedAt
260
+ }`;
261
+ }
262
+ function tplProjectionBdef(projRoot, childProj, childIntf, withDraft) {
263
+ const lines = [];
264
+ lines.push("projection;");
265
+ lines.push("strict ( 2 );");
266
+ if (withDraft)
267
+ lines.push("use draft;");
268
+ lines.push("");
269
+ lines.push(`define behavior for ${projRoot} alias ${aliasFrom(projRoot)}`);
270
+ lines.push("use etag");
271
+ lines.push("{");
272
+ lines.push(" use create; use update; use delete;");
273
+ if (withDraft) {
274
+ lines.push(" use action Edit; use action Activate; use action Discard;");
275
+ lines.push(" use action Resume; use action Prepare;");
276
+ }
277
+ for (let i = 0; i < childProj.length; i++) {
278
+ if (withDraft) {
279
+ lines.push(` use association _${aliasFrom(childIntf[i])} { create; with draft; }`);
280
+ }
281
+ else {
282
+ lines.push(` use association _${aliasFrom(childIntf[i])} { create; }`);
283
+ }
284
+ }
285
+ lines.push("}");
286
+ for (let i = 0; i < childProj.length; i++) {
287
+ lines.push("");
288
+ lines.push(`define behavior for ${childProj[i]} alias ${aliasFrom(childProj[i])}`);
289
+ lines.push("use etag");
290
+ lines.push("{");
291
+ lines.push(" use update; use delete;");
292
+ if (withDraft) {
293
+ lines.push(` use association _${aliasFrom(projRoot.replace(/^zc_/i, "zi_"))} { with draft; }`);
294
+ }
295
+ else {
296
+ lines.push(` use association _${aliasFrom(projRoot.replace(/^zc_/i, "zi_"))};`);
297
+ }
298
+ lines.push("}");
299
+ }
300
+ return lines.join("\n");
301
+ }
302
+ function tplServiceDefinition(srvdName, desc, projRoot, childProj) {
303
+ const lines = [];
304
+ lines.push(`@EndUserText.label: '${desc}'`);
305
+ lines.push(`define service ${srvdName} {`);
306
+ lines.push(` expose ${projRoot} as ${aliasFrom(projRoot)};`);
307
+ for (const child of childProj) {
308
+ lines.push(` expose ${child} as ${aliasFrom(child)};`);
309
+ }
310
+ lines.push("}");
311
+ return lines.join("\n");
312
+ }
313
+ function tplMetadataExtension(ddlxName, projRoot) {
314
+ return `@Metadata.layer: #CORE
315
+ annotate entity ${projRoot} with
316
+ {
317
+ @UI.facet: [
318
+ { id: 'General', type: #IDENTIFICATION_REFERENCE, label: 'General', position: 10 }
319
+ ]
320
+
321
+ @UI.hidden: true
322
+ KeyField;
323
+ }`;
324
+ }
325
+ function tplCdsAbstractEntity(name, desc) {
326
+ return `@EndUserText.label: '${desc}'
327
+ define abstract entity ${name}
328
+ {
329
+ key_field : abap.char(40);
330
+ }`;
331
+ }
332
+ function tplCdsCustomEntity(name, desc, queryClass) {
333
+ return `@EndUserText.label: '${desc}'
334
+ @ObjectModel.query.implementedBy: 'ABAP:${queryClass.toUpperCase()}'
335
+ define custom entity ${name}
336
+ {
337
+ key KeyField : abap.char(40);
338
+ Value : abap.char(100);
339
+ }`;
340
+ }
341
+ function tplQueryClass(className) {
342
+ return `CLASS ${className.toLowerCase()} DEFINITION PUBLIC FINAL CREATE PUBLIC.
343
+ PUBLIC SECTION.
344
+ INTERFACES if_rap_query_provider.
345
+ ENDCLASS.
346
+
347
+ CLASS ${className.toLowerCase()} IMPLEMENTATION.
348
+ METHOD if_rap_query_provider~select.
349
+ DATA(lv_top) = io_request->get_paging( )->get_page_size( ).
350
+ DATA(lv_skip) = io_request->get_paging( )->get_offset( ).
351
+
352
+ " TODO: Implementar query — use abap_knowledge('abap/rap-unmanaged') como referência
353
+
354
+ io_response->set_data( VALUE #( ) ).
355
+ IF io_request->is_total_numb_of_rec_requested( ).
356
+ io_response->set_total_number_of_records( 0 ).
357
+ ENDIF.
358
+ ENDMETHOD.
359
+ ENDCLASS.`;
360
+ }
361
+ // Extract alias from CDS name: ZI_Travel → Travel, ZC_Booking → Booking
362
+ function aliasFrom(cdsName) {
363
+ // Remove prefix ZI_, ZC_, ZA_, ZCE_ etc.
364
+ return cdsName.replace(/^Z[A-Z]{0,2}_/i, "");
365
+ }
366
+ // ---------------------------------------------------------------------------
367
+ // Scenarios
368
+ // ---------------------------------------------------------------------------
369
+ async function scenarioManaged(input) {
370
+ const { base_name, description, package: pkg = "$TMP", binding_type = "ODATA;V4;UI", transport_request: tr } = input;
371
+ const name = base_name.toUpperCase();
372
+ const srvdName = `SRVD_${name}`;
373
+ const srvbName = `SRVB_${name}`;
374
+ const steps = [];
375
+ const warnings = collectWarnings(binding_type);
376
+ // CDS
377
+ const cdsSource = `@AbapCatalog.viewEnhancementCategory: [#NONE]
378
+ @AccessControl.authorizationCheck: #NOT_REQUIRED
379
+ @EndUserText.label: '${description}'
380
+ @Metadata.ignorePropagatedAnnotations: true
381
+ @Metadata.allowExtensions: true
382
+
383
+ define root view entity ${name}
384
+ as select from I_BusinessPartner
385
+ {
386
+ key BusinessPartner
387
+ }`;
388
+ if (!(await createWriteActivate(steps, name, "DDLS/DF", description, cdsSource, pkg, tr))) {
389
+ return formatSummary(steps, false, warnings);
390
+ }
391
+ // BDEF
392
+ const bdefSource = `managed implementation in class zbp_${name.toLowerCase()} unique;
393
+ strict ( 2 );
394
+
395
+ define behavior for ${name}
396
+ {
397
+ }`;
398
+ if (!(await createWriteActivate(steps, name, "BDEF/BDO", description, bdefSource, pkg, tr))) {
399
+ return formatSummary(steps, false, warnings);
400
+ }
401
+ // SRVD
402
+ if (!(await createObject(steps, srvdName, "SRVD/SRV", `${description} - Service Def`, pkg, tr))) {
403
+ return formatSummary(steps, false, warnings);
404
+ }
405
+ if (!(await activateObject(steps, srvdName, "SRVD/SRV"))) {
406
+ return formatSummary(steps, false, warnings);
407
+ }
408
+ // SRVB
409
+ if (!(await createObject(steps, srvbName, "SRVB/SVB", `${description} - Service Binding`, pkg, tr, srvdName, binding_type))) {
410
+ return formatSummary(steps, false, warnings);
411
+ }
412
+ await activateObject(steps, srvbName, "SRVB/SVB");
413
+ return formatSummary(steps, steps.every((s) => s.status === "ok"), warnings);
414
+ }
415
+ async function scenarioManagedDraft(input) {
416
+ const { base_name, description, child_entities = [], with_feature_control: wfc = false, with_business_events: events = [], package: pkg = "$TMP", binding_type = "ODATA;V4;UI", transport_request: tr, } = input;
417
+ const rootCds = base_name.toUpperCase();
418
+ const childCds = child_entities.map((c) => c.toUpperCase());
419
+ const rootProj = rootCds.replace(/^ZI_/i, "ZC_");
420
+ const childProj = childCds.map((c) => c.replace(/^ZI_/i, "ZC_"));
421
+ const srvdName = `SRVD_${rootCds.replace(/^ZI_/i, "")}`;
422
+ const srvbName = `SRVB_${rootCds.replace(/^ZI_/i, "")}`;
423
+ const ddlxName = `${rootProj}`;
424
+ const handlerClassName = `zbp_${rootCds.toLowerCase()}`;
425
+ const steps = [];
426
+ const warnings = collectWarnings(binding_type);
427
+ // 1. CDS Interface Root
428
+ const cdsRootSource = tplCdsInterfaceRoot(rootCds, description, rootCds.toLowerCase().replace(/^z[ic]_/, "ztab_"), childCds);
429
+ if (!(await createWriteActivate(steps, rootCds, "DDLS/DF", `${description} - Interface`, cdsRootSource, pkg, tr))) {
430
+ return formatSummary(steps, false, warnings);
431
+ }
432
+ // 2. CDS Interface Children
433
+ for (const child of childCds) {
434
+ const childTable = child.toLowerCase().replace(/^z[ic]_/, "ztab_");
435
+ const childSource = tplCdsInterfaceChild(child, `${description} - ${aliasFrom(child)}`, childTable, rootCds);
436
+ if (!(await createWriteActivate(steps, child, "DDLS/DF", `${description} - ${aliasFrom(child)}`, childSource, pkg, tr))) {
437
+ return formatSummary(steps, false, warnings);
438
+ }
439
+ }
440
+ // 3. BDEF Interface
441
+ const bdefSource = tplBdefManaged(rootCds, childCds, true, wfc, events);
442
+ if (!(await createWriteActivate(steps, rootCds, "BDEF/BDO", description, bdefSource, pkg, tr))) {
443
+ return formatSummary(steps, false, warnings);
444
+ }
445
+ // 4. Handler Class
446
+ const handlerSource = tplHandlerClass(rootCds);
447
+ if (!(await createWriteActivate(steps, handlerClassName.toUpperCase(), "CLAS/OC", `${description} - Handler`, handlerSource, pkg, tr))) {
448
+ return formatSummary(steps, false, warnings);
449
+ }
450
+ // 5. CDS Projection Root
451
+ const projRootSource = tplCdsProjectionRoot(rootProj, rootCds, `${description} - Projection`, childProj, childCds);
452
+ if (!(await createWriteActivate(steps, rootProj, "DDLS/DF", `${description} - Projection`, projRootSource, pkg, tr))) {
453
+ return formatSummary(steps, false, warnings);
454
+ }
455
+ // 6. CDS Projection Children
456
+ for (let i = 0; i < childCds.length; i++) {
457
+ const childProjSource = tplCdsProjectionChild(childProj[i], childCds[i], `${description} - ${aliasFrom(childProj[i])}`, rootProj, rootCds);
458
+ if (!(await createWriteActivate(steps, childProj[i], "DDLS/DF", `${description} - ${aliasFrom(childProj[i])}`, childProjSource, pkg, tr))) {
459
+ return formatSummary(steps, false, warnings);
460
+ }
461
+ }
462
+ // 7. Projection BDEF
463
+ const projBdefSource = tplProjectionBdef(rootProj, childProj, childCds, true);
464
+ if (!(await createWriteActivate(steps, rootProj, "BDEF/BDO", `${description} - Proj BDEF`, projBdefSource, pkg, tr))) {
465
+ return formatSummary(steps, false, warnings);
466
+ }
467
+ // 8. Service Definition
468
+ const srvdSource = tplServiceDefinition(srvdName, description, rootProj, childProj);
469
+ if (!(await createObject(steps, srvdName, "SRVD/SRV", `${description} - Service Def`, pkg, tr))) {
470
+ return formatSummary(steps, false, warnings);
471
+ }
472
+ // SRVD source is auto-generated, just activate
473
+ if (!(await activateObject(steps, srvdName, "SRVD/SRV"))) {
474
+ return formatSummary(steps, false, warnings);
475
+ }
476
+ // 9. Service Binding
477
+ if (!(await createObject(steps, srvbName, "SRVB/SVB", `${description} - Service Binding`, pkg, tr, srvdName, binding_type))) {
478
+ return formatSummary(steps, false, warnings);
479
+ }
480
+ await activateObject(steps, srvbName, "SRVB/SVB");
481
+ // 10. Metadata Extension
482
+ const ddlxSource = tplMetadataExtension(ddlxName, rootProj);
483
+ // DDLX uses the projection name
484
+ const ddlxObjName = `${rootProj}_MDE`;
485
+ if (!(await createWriteActivate(steps, ddlxObjName, "DDLX/MX", `${description} - UI Annotations`, ddlxSource, pkg, tr))) {
486
+ // DDLX failure is non-fatal
487
+ warnings.push("AVISO: Metadata Extension falhou — pode ser criada manualmente depois.");
488
+ }
489
+ const success = steps.filter((s) => s.status === "error").length === 0 ||
490
+ (steps.filter((s) => s.status === "error").length === 1 && steps[steps.length - 1]?.status === "error");
491
+ const summary = formatSummary(steps, steps.every((s) => s.status === "ok"), warnings);
492
+ // Add next steps guidance
493
+ const nextSteps = [
494
+ "",
495
+ "",
496
+ "📋 Próximos passos:",
497
+ " 1. Ajustar campos do CDS Interface com abap_write (use abap_knowledge action:'get' topics:['abap/rap-end-to-end'])",
498
+ " 2. Adicionar validations/determinations no BDEF",
499
+ " 3. Implementar handler class locals_def/locals_imp (use abap_knowledge action:'get' topics:['abap/rap-eml'])",
500
+ " 4. Ajustar Metadata Extension para UI (use abap_knowledge action:'get' topics:['abap-cds/metadata-extensions'])",
501
+ wfc ? " 5. Implementar get_instance_features (use abap_knowledge action:'get' topics:['abap/rap-feature-control'])" : "",
502
+ events.length > 0 ? " 6. Implementar RAISE ENTITY EVENT (use abap_knowledge action:'get' topics:['abap/rap-business-events'])" : "",
503
+ ].filter(Boolean);
504
+ return summary + nextSteps.join("\n");
505
+ }
506
+ async function scenarioUnmanaged(input) {
507
+ const { base_name, description, child_entities = [], package: pkg = "$TMP", binding_type = "ODATA;V4;UI", transport_request: tr, } = input;
508
+ const rootCds = base_name.toUpperCase();
509
+ const childCds = child_entities.map((c) => c.toUpperCase());
510
+ const rootProj = rootCds.replace(/^ZI_/i, "ZC_");
511
+ const childProj = childCds.map((c) => c.replace(/^ZI_/i, "ZC_"));
512
+ const srvdName = `SRVD_${rootCds.replace(/^ZI_/i, "")}`;
513
+ const srvbName = `SRVB_${rootCds.replace(/^ZI_/i, "")}`;
514
+ const handlerClassName = `zbp_${rootCds.toLowerCase()}`;
515
+ const steps = [];
516
+ const warnings = collectWarnings(binding_type);
517
+ // 1. CDS Interface Root
518
+ const cdsRootSource = tplCdsInterfaceRoot(rootCds, description, rootCds.toLowerCase().replace(/^z[ic]_/, "ztab_"), childCds);
519
+ if (!(await createWriteActivate(steps, rootCds, "DDLS/DF", `${description} - Interface`, cdsRootSource, pkg, tr))) {
520
+ return formatSummary(steps, false, warnings);
521
+ }
522
+ // 2. CDS Interface Children
523
+ for (const child of childCds) {
524
+ const childTable = child.toLowerCase().replace(/^z[ic]_/, "ztab_");
525
+ const childSource = tplCdsInterfaceChild(child, `${description} - ${aliasFrom(child)}`, childTable, rootCds);
526
+ if (!(await createWriteActivate(steps, child, "DDLS/DF", `${description} - ${aliasFrom(child)}`, childSource, pkg, tr))) {
527
+ return formatSummary(steps, false, warnings);
528
+ }
529
+ }
530
+ // 3. BDEF Unmanaged
531
+ const bdefSource = tplBdefUnmanaged(rootCds, childCds);
532
+ if (!(await createWriteActivate(steps, rootCds, "BDEF/BDO", description, bdefSource, pkg, tr))) {
533
+ return formatSummary(steps, false, warnings);
534
+ }
535
+ // 4. Handler Class (with buffer pattern)
536
+ const handlerSource = tplHandlerClassUnmanaged(rootCds);
537
+ if (!(await createWriteActivate(steps, handlerClassName.toUpperCase(), "CLAS/OC", `${description} - Handler`, handlerSource, pkg, tr))) {
538
+ return formatSummary(steps, false, warnings);
539
+ }
540
+ // 5. Projection CDS Root
541
+ const projRootSource = tplCdsProjectionRoot(rootProj, rootCds, `${description} - Projection`, childProj, childCds);
542
+ if (!(await createWriteActivate(steps, rootProj, "DDLS/DF", `${description} - Projection`, projRootSource, pkg, tr))) {
543
+ return formatSummary(steps, false, warnings);
544
+ }
545
+ // 6. Projection CDS Children
546
+ for (let i = 0; i < childCds.length; i++) {
547
+ const childProjSource = tplCdsProjectionChild(childProj[i], childCds[i], `${description} - ${aliasFrom(childProj[i])}`, rootProj, rootCds);
548
+ if (!(await createWriteActivate(steps, childProj[i], "DDLS/DF", `${description} - ${aliasFrom(childProj[i])}`, childProjSource, pkg, tr))) {
549
+ return formatSummary(steps, false, warnings);
550
+ }
551
+ }
552
+ // 7. Projection BDEF (no draft)
553
+ const projBdefSource = tplProjectionBdef(rootProj, childProj, childCds, false);
554
+ if (!(await createWriteActivate(steps, rootProj, "BDEF/BDO", `${description} - Proj BDEF`, projBdefSource, pkg, tr))) {
555
+ return formatSummary(steps, false, warnings);
556
+ }
557
+ // 8. Service Definition + Binding
558
+ if (!(await createObject(steps, srvdName, "SRVD/SRV", `${description} - Service Def`, pkg, tr))) {
559
+ return formatSummary(steps, false, warnings);
560
+ }
561
+ if (!(await activateObject(steps, srvdName, "SRVD/SRV"))) {
562
+ return formatSummary(steps, false, warnings);
563
+ }
564
+ if (!(await createObject(steps, srvbName, "SRVB/SVB", `${description} - Binding`, pkg, tr, srvdName, binding_type))) {
565
+ return formatSummary(steps, false, warnings);
566
+ }
567
+ await activateObject(steps, srvbName, "SRVB/SVB");
568
+ const summary = formatSummary(steps, steps.every((s) => s.status === "ok"), warnings);
569
+ const nextSteps = [
570
+ "",
571
+ "",
572
+ "📋 Próximos passos (OBRIGATÓRIOS para unmanaged):",
573
+ " 1. Implementar handler methods: create, update, delete, read, lock",
574
+ " → abap_knowledge(action:'get', topics:['abap/rap-unmanaged'])",
575
+ " 2. Implementar saver class: finalize, check_before_save, save, cleanup",
576
+ " 3. Se wrapping BAPI: BAPI calls vão no saver save(), NÃO no handler",
577
+ " 4. Ajustar campos CDS + projection com abap_write",
578
+ ];
579
+ return summary + nextSteps.join("\n");
580
+ }
581
+ async function scenarioQuery(input) {
582
+ const { base_name, description, package: pkg = "$TMP", transport_request: tr } = input;
583
+ const entityName = base_name.toUpperCase();
584
+ const queryClassName = `ZCL_${entityName.replace(/^Z(CE_|A_)?/i, "")}_QUERY`;
585
+ const steps = [];
586
+ const warnings = [];
587
+ // 1. Custom Entity CDS
588
+ const cdsSource = tplCdsCustomEntity(entityName, description, queryClassName);
589
+ if (!(await createWriteActivate(steps, entityName, "DDLS/DF", description, cdsSource, pkg, tr))) {
590
+ return formatSummary(steps, false, warnings);
591
+ }
592
+ // 2. Query Implementation Class
593
+ const classSource = tplQueryClass(queryClassName);
594
+ if (!(await createWriteActivate(steps, queryClassName.toUpperCase(), "CLAS/OC", `${description} - Query`, classSource, pkg, tr))) {
595
+ return formatSummary(steps, false, warnings);
596
+ }
597
+ const summary = formatSummary(steps, steps.every((s) => s.status === "ok"), warnings);
598
+ const nextSteps = [
599
+ "",
600
+ "",
601
+ "📋 Próximos passos:",
602
+ " 1. Ajustar campos do custom entity com abap_write",
603
+ " 2. Implementar if_rap_query_provider~select na classe",
604
+ " → abap_knowledge(action:'get', topics:['abap/rap-unmanaged']) seção 'Unmanaged Query'",
605
+ " 3. Pode ser exposto diretamente em Service Definition (sem BDEF)",
606
+ ];
607
+ return summary + nextSteps.join("\n");
608
+ }
609
+ // ---------------------------------------------------------------------------
610
+ // Shared helpers
611
+ // ---------------------------------------------------------------------------
612
+ function collectWarnings(bindingType) {
613
+ const warnings = [];
614
+ const profile = (0, system_profile_js_1.getProfile)();
615
+ if (!profile.capabilities.cdsViewEntity) {
616
+ warnings.push(`⚠️ O sistema ${profile.system.systemId || profile.system.type} (BASIS ${profile.system.sapBasisVersion}) pode não suportar 'define view entity'. Scaffold RAP requer S/4HANA 2020+ (BASIS 756+).`);
617
+ }
618
+ if (bindingType.includes("V4") && profile.quirks.conversionExitFields.length > 0) {
619
+ warnings.push(`⚠️ Em OData V4, campos com conversion exit causam erro em runtime. ` +
620
+ `Campos conhecidos: ${profile.quirks.conversionExitFields.join(", ")}. ` +
621
+ `Use cast( campo as abap.char(n) ) na CDS para evitar problemas.`);
622
+ }
623
+ return warnings;
624
+ }
625
+ // ---------------------------------------------------------------------------
626
+ // Main entry point
627
+ // ---------------------------------------------------------------------------
628
+ async function abapScaffoldRap(input) {
629
+ const scenario = input.scenario || "managed";
630
+ switch (scenario) {
631
+ case "managed":
632
+ return scenarioManaged(input);
633
+ case "managed_draft":
634
+ return scenarioManagedDraft(input);
635
+ case "unmanaged":
636
+ return scenarioUnmanaged(input);
637
+ case "query":
638
+ return scenarioQuery(input);
639
+ default:
640
+ return `Scenario "${scenario}" inválido. Use: managed, managed_draft, unmanaged ou query.`;
641
+ }
642
+ }