@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.
- package/README.md +389 -0
- package/dist/adt-client.js +383 -0
- package/dist/cli/activate.js +127 -0
- package/dist/cli/init.js +559 -0
- package/dist/cli/link.js +148 -0
- package/dist/cli/remove.js +83 -0
- package/dist/cli/status.js +231 -0
- package/dist/cli/systems.js +72 -0
- package/dist/cli.js +92 -0
- package/dist/index.js +1442 -0
- package/dist/knowledge/abap/abap-dictionary.md +199 -0
- package/dist/knowledge/abap/abap-sql.md +296 -0
- package/dist/knowledge/abap/amdp.md +273 -0
- package/dist/knowledge/abap/clean-code.md +293 -0
- package/dist/knowledge/abap/cloud-background-processing.md +250 -0
- package/dist/knowledge/abap/cloud-communication.md +265 -0
- package/dist/knowledge/abap/cloud-development.md +176 -0
- package/dist/knowledge/abap/cloud-extensibility.md +252 -0
- package/dist/knowledge/abap/cloud-released-apis.md +261 -0
- package/dist/knowledge/abap/constructor-expressions.md +289 -0
- package/dist/knowledge/abap/enhancements.md +232 -0
- package/dist/knowledge/abap/exceptions.md +271 -0
- package/dist/knowledge/abap/internal-tables.md +205 -0
- package/dist/knowledge/abap/object-orientation.md +298 -0
- package/dist/knowledge/abap/performance.md +216 -0
- package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
- package/dist/knowledge/abap/rap-business-events.md +216 -0
- package/dist/knowledge/abap/rap-draft.md +191 -0
- package/dist/knowledge/abap/rap-eml.md +453 -0
- package/dist/knowledge/abap/rap-end-to-end.md +486 -0
- package/dist/knowledge/abap/rap-feature-control.md +185 -0
- package/dist/knowledge/abap/rap-numbering.md +280 -0
- package/dist/knowledge/abap/rap-service-exposure.md +163 -0
- package/dist/knowledge/abap/rap-unmanaged.md +468 -0
- package/dist/knowledge/abap/string-processing.md +180 -0
- package/dist/knowledge/abap/unit-testing.md +303 -0
- package/dist/knowledge/abap-cds/access-control.md +241 -0
- package/dist/knowledge/abap-cds/annotations.md +331 -0
- package/dist/knowledge/abap-cds/associations.md +254 -0
- package/dist/knowledge/abap-cds/expressions.md +230 -0
- package/dist/knowledge/abap-cds/functions.md +245 -0
- package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
- package/dist/knowledge/cap/authentication.md +278 -0
- package/dist/knowledge/cap/cdl-syntax.md +247 -0
- package/dist/knowledge/cap/cql-queries.md +266 -0
- package/dist/knowledge/cap/deployment.md +343 -0
- package/dist/knowledge/cap/event-handlers.md +287 -0
- package/dist/knowledge/cap/fiori-integration.md +303 -0
- package/dist/knowledge/cap/service-definitions.md +287 -0
- package/dist/knowledge/fiori/annotations.md +347 -0
- package/dist/knowledge/fiori/deployment.md +340 -0
- package/dist/knowledge/fiori/fiori-elements.md +332 -0
- package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
- package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
- package/dist/knowledge/fiori/ui5-controllers.md +358 -0
- package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
- package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
- package/dist/knowledge/fiori/ui5-manifest.md +411 -0
- package/dist/knowledge/fiori/ui5-routing.md +303 -0
- package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
- package/dist/license-guard.js +81 -0
- package/dist/logger.js +114 -0
- package/dist/postinstall.js +165 -0
- package/dist/security-audit.js +136 -0
- package/dist/security-policy.js +322 -0
- package/dist/system-profile.js +207 -0
- package/dist/tools/abap-doc.js +72 -0
- package/dist/tools/abapgit.js +161 -0
- package/dist/tools/activate.js +71 -0
- package/dist/tools/atc-check.js +117 -0
- package/dist/tools/auth-object.js +56 -0
- package/dist/tools/breakpoints.js +76 -0
- package/dist/tools/call-hierarchy.js +84 -0
- package/dist/tools/cds-annotations.js +98 -0
- package/dist/tools/cds-dependencies.js +65 -0
- package/dist/tools/check.js +47 -0
- package/dist/tools/code-completion.js +70 -0
- package/dist/tools/code-coverage.js +111 -0
- package/dist/tools/create-amdp.js +111 -0
- package/dist/tools/create-dcl.js +81 -0
- package/dist/tools/create-transport.js +38 -0
- package/dist/tools/create.js +285 -0
- package/dist/tools/data-preview.js +37 -0
- package/dist/tools/delete.js +45 -0
- package/dist/tools/deploy-bsp.js +298 -0
- package/dist/tools/discovery.js +59 -0
- package/dist/tools/element-info.js +93 -0
- package/dist/tools/enhancements.js +186 -0
- package/dist/tools/extract-method.js +44 -0
- package/dist/tools/function-group.js +59 -0
- package/dist/tools/knowledge.js +275 -0
- package/dist/tools/lock-object.js +75 -0
- package/dist/tools/message-class.js +67 -0
- package/dist/tools/navigate.js +80 -0
- package/dist/tools/number-range.js +57 -0
- package/dist/tools/object-documentation.js +43 -0
- package/dist/tools/object-structure.js +78 -0
- package/dist/tools/object-versions.js +57 -0
- package/dist/tools/package-contents.js +60 -0
- package/dist/tools/pretty-printer.js +35 -0
- package/dist/tools/publish-binding.js +49 -0
- package/dist/tools/quick-fix.js +69 -0
- package/dist/tools/read.js +172 -0
- package/dist/tools/refactor-rename.js +60 -0
- package/dist/tools/release-transport.js +24 -0
- package/dist/tools/released-apis.js +51 -0
- package/dist/tools/repository-tree.js +90 -0
- package/dist/tools/scaffold-rap.js +642 -0
- package/dist/tools/search.js +73 -0
- package/dist/tools/shared/data-format.js +101 -0
- package/dist/tools/sql-console.js +17 -0
- package/dist/tools/system-info.js +271 -0
- package/dist/tools/traces.js +66 -0
- package/dist/tools/transport-contents.js +83 -0
- package/dist/tools/transports.js +68 -0
- package/dist/tools/unit-test.js +135 -0
- package/dist/tools/where-used.js +59 -0
- package/dist/tools/write.js +120 -0
- 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
|
+
}
|