abapgit-agent 1.7.1 ā 1.8.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/.abapGitAgent.example +11 -0
- package/README.md +7 -7
- package/abap/.github/copilot-instructions.md +254 -0
- package/abap/CLAUDE.md +432 -0
- package/abap/guidelines/00_index.md +8 -0
- package/abap/guidelines/01_sql.md +8 -0
- package/abap/guidelines/02_exceptions.md +8 -0
- package/abap/guidelines/03_testing.md +8 -0
- package/abap/guidelines/04_cds.md +8 -0
- package/abap/guidelines/05_classes.md +8 -0
- package/abap/guidelines/06_objects.md +8 -0
- package/abap/guidelines/07_json.md +8 -0
- package/abap/guidelines/08_abapgit.md +8 -0
- package/abap/guidelines/09_unit_testable_code.md +8 -0
- package/bin/abapgit-agent +61 -2789
- package/package.json +25 -5
- package/src/agent.js +213 -20
- package/src/commands/create.js +102 -0
- package/src/commands/delete.js +72 -0
- package/src/commands/health.js +24 -0
- package/src/commands/help.js +111 -0
- package/src/commands/import.js +99 -0
- package/src/commands/init.js +321 -0
- package/src/commands/inspect.js +184 -0
- package/src/commands/list.js +143 -0
- package/src/commands/preview.js +277 -0
- package/src/commands/pull.js +278 -0
- package/src/commands/ref.js +96 -0
- package/src/commands/status.js +52 -0
- package/src/commands/syntax.js +290 -0
- package/src/commands/tree.js +209 -0
- package/src/commands/unit.js +133 -0
- package/src/commands/view.js +215 -0
- package/src/commands/where.js +138 -0
- package/src/config.js +11 -1
- package/src/utils/abap-http.js +347 -0
- package/src/{ref-search.js ā utils/abap-reference.js} +119 -1
- package/src/utils/git-utils.js +58 -0
- package/src/utils/validators.js +72 -0
- package/src/utils/version-check.js +80 -0
- package/src/abap-client.js +0 -523
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abapgit-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "ABAP Git Agent - Pull and activate ABAP code via abapGit from any git repository",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"bin/",
|
|
8
8
|
"src/",
|
|
9
|
-
"abap/guidelines/"
|
|
9
|
+
"abap/guidelines/",
|
|
10
|
+
"abap/CLAUDE.md",
|
|
11
|
+
"abap/.github/copilot-instructions.md",
|
|
12
|
+
".abapGitAgent.example"
|
|
10
13
|
],
|
|
11
14
|
"bin": {
|
|
12
15
|
"abapgit-agent": "bin/abapgit-agent",
|
|
@@ -16,10 +19,21 @@
|
|
|
16
19
|
"start": "node src/server.js",
|
|
17
20
|
"dev": "nodemon src/server.js",
|
|
18
21
|
"test": "jest",
|
|
19
|
-
"test:all": "node
|
|
22
|
+
"test:all": "node tests/run-all.js",
|
|
23
|
+
"test:unit": "jest",
|
|
20
24
|
"test:jest": "jest",
|
|
21
|
-
"test:
|
|
22
|
-
"test:
|
|
25
|
+
"test:integration": "node tests/run-all.js --cmd",
|
|
26
|
+
"test:aunit": "node tests/run-all.js --aunit",
|
|
27
|
+
"test:cmd": "node tests/run-all.js --cmd",
|
|
28
|
+
"test:cmd:demo": "node tests/run-all.js --cmd --demo",
|
|
29
|
+
"test:cmd:syntax": "node tests/run-all.js --cmd --command=syntax",
|
|
30
|
+
"test:cmd:pull": "node tests/run-all.js --cmd --command=pull",
|
|
31
|
+
"test:cmd:inspect": "node tests/run-all.js --cmd --command=inspect",
|
|
32
|
+
"test:cmd:unit": "node tests/run-all.js --cmd --command=unit",
|
|
33
|
+
"test:cmd:view": "node tests/run-all.js --cmd --command=view",
|
|
34
|
+
"test:cmd:preview": "node tests/run-all.js --cmd --command=preview",
|
|
35
|
+
"test:cmd:tree": "node tests/run-all.js --cmd --command=tree",
|
|
36
|
+
"test:lifecycle": "node tests/run-all.js --lifecycle",
|
|
23
37
|
"pull": "node bin/abapgit-agent",
|
|
24
38
|
"release": "node scripts/release.js",
|
|
25
39
|
"unrelease": "node scripts/unrelease.js"
|
|
@@ -39,5 +53,11 @@
|
|
|
39
53
|
},
|
|
40
54
|
"engines": {
|
|
41
55
|
"node": ">=16.0.0"
|
|
56
|
+
},
|
|
57
|
+
"jest": {
|
|
58
|
+
"testMatch": [
|
|
59
|
+
"**/tests/unit/**/*.test.js"
|
|
60
|
+
],
|
|
61
|
+
"testEnvironment": "node"
|
|
42
62
|
}
|
|
43
63
|
}
|
package/src/agent.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ABAP Git Agent - Main agent class
|
|
3
|
+
* Uses AbapHttp for all ABAP communication
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
|
-
const {
|
|
6
|
+
const { AbapHttp } = require('./utils/abap-http');
|
|
7
|
+
const { getAbapConfig } = require('./config');
|
|
6
8
|
const logger = require('./logger');
|
|
7
9
|
|
|
8
10
|
class ABAPGitAgent {
|
|
9
11
|
constructor() {
|
|
10
|
-
this.
|
|
12
|
+
this.config = getAbapConfig();
|
|
13
|
+
this.http = new AbapHttp(this.config);
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
/**
|
|
@@ -17,13 +20,31 @@ class ABAPGitAgent {
|
|
|
17
20
|
* @param {string} username - Git username (optional)
|
|
18
21
|
* @param {string} password - Git password/token (optional)
|
|
19
22
|
* @param {Array} files - Specific files to pull (optional)
|
|
23
|
+
* @param {string} transportRequest - Transport request number (optional)
|
|
20
24
|
* @returns {object} Pull result with success, job_id, message, error_detail
|
|
21
25
|
*/
|
|
22
|
-
async pull(repoUrl, branch = 'main', username = null, password = null, files = null) {
|
|
23
|
-
logger.info('Starting pull operation', { repoUrl, branch, username: !!username, files });
|
|
26
|
+
async pull(repoUrl, branch = 'main', username = null, password = null, files = null, transportRequest = null) {
|
|
27
|
+
logger.info('Starting pull operation', { repoUrl, branch, username: !!username, files, transportRequest });
|
|
24
28
|
|
|
25
29
|
try {
|
|
26
|
-
const
|
|
30
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
31
|
+
|
|
32
|
+
const data = {
|
|
33
|
+
url: repoUrl,
|
|
34
|
+
branch: branch,
|
|
35
|
+
username: username || this.config.gitUsername,
|
|
36
|
+
password: password || this.config.gitPassword
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (files && files.length > 0) {
|
|
40
|
+
data.files = files;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (transportRequest) {
|
|
44
|
+
data.transport_request = transportRequest;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/pull', data, { csrfToken });
|
|
27
48
|
|
|
28
49
|
// Return the result directly from ABAP (handle uppercase keys from /UI2/CL_JSON)
|
|
29
50
|
return {
|
|
@@ -49,7 +70,7 @@ class ABAPGitAgent {
|
|
|
49
70
|
*/
|
|
50
71
|
async healthCheck() {
|
|
51
72
|
try {
|
|
52
|
-
const result = await this.
|
|
73
|
+
const result = await this.http.get('/sap/bc/z_abapgit_agent/health');
|
|
53
74
|
return {
|
|
54
75
|
status: 'healthy',
|
|
55
76
|
abap: 'connected',
|
|
@@ -65,7 +86,7 @@ class ABAPGitAgent {
|
|
|
65
86
|
}
|
|
66
87
|
|
|
67
88
|
/**
|
|
68
|
-
* Check syntax of an ABAP object
|
|
89
|
+
* Check syntax of an ABAP object (legacy - not used by CLI)
|
|
69
90
|
* @param {string} objectType - ABAP object type (e.g., 'CLAS', 'PROG', 'INTF')
|
|
70
91
|
* @param {string} objectName - ABAP object name
|
|
71
92
|
* @returns {object} Syntax check result with errors (if any)
|
|
@@ -74,7 +95,13 @@ class ABAPGitAgent {
|
|
|
74
95
|
logger.info('Starting syntax check', { objectType, objectName });
|
|
75
96
|
|
|
76
97
|
try {
|
|
77
|
-
const
|
|
98
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
99
|
+
const data = {
|
|
100
|
+
object_type: objectType,
|
|
101
|
+
object_name: objectName
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/syntax-check', data, { csrfToken });
|
|
78
105
|
return {
|
|
79
106
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
80
107
|
object_type: result.OBJECT_TYPE || result.object_type,
|
|
@@ -88,6 +115,51 @@ class ABAPGitAgent {
|
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Check syntax of ABAP source code directly (without pull/activation)
|
|
120
|
+
* Supported types: CLAS, INTF, PROG
|
|
121
|
+
* @param {Array} objects - Array of {type, name, source, locals_def?, locals_imp?}
|
|
122
|
+
* @param {string} uccheck - Unicode check mode ('X' for Standard, '5' for Cloud)
|
|
123
|
+
* @returns {object} Syntax check results with success, results array
|
|
124
|
+
*/
|
|
125
|
+
async syntaxCheckSource(objects, uccheck = 'X') {
|
|
126
|
+
logger.info('Starting source syntax check', { objectCount: objects.length, uccheck });
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
130
|
+
const data = {
|
|
131
|
+
objects: objects,
|
|
132
|
+
uccheck: uccheck
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/syntax', data, { csrfToken });
|
|
136
|
+
const success = result.SUCCESS === 'X' || result.SUCCESS === true ||
|
|
137
|
+
result.success === 'X' || result.success === true;
|
|
138
|
+
const results = result.RESULTS || result.results || [];
|
|
139
|
+
const message = result.MESSAGE || result.message || '';
|
|
140
|
+
|
|
141
|
+
// Normalize results
|
|
142
|
+
const normalizedResults = results.map(r => ({
|
|
143
|
+
object_type: r.OBJECT_TYPE || r.object_type,
|
|
144
|
+
object_name: r.OBJECT_NAME || r.object_name,
|
|
145
|
+
success: r.SUCCESS === 'X' || r.SUCCESS === true || r.success === 'X' || r.success === true,
|
|
146
|
+
error_count: r.ERROR_COUNT || r.error_count || 0,
|
|
147
|
+
errors: r.ERRORS || r.errors || [],
|
|
148
|
+
warnings: r.WARNINGS || r.warnings || [],
|
|
149
|
+
message: r.MESSAGE || r.message || ''
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
success,
|
|
154
|
+
message,
|
|
155
|
+
results: normalizedResults
|
|
156
|
+
};
|
|
157
|
+
} catch (error) {
|
|
158
|
+
logger.error('Source syntax check failed', { error: error.message });
|
|
159
|
+
throw new Error(`Source syntax check failed: ${error.message}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
91
163
|
/**
|
|
92
164
|
* Run unit tests for package or objects
|
|
93
165
|
* @param {string} packageName - Package name to run tests for (optional)
|
|
@@ -98,7 +170,18 @@ class ABAPGitAgent {
|
|
|
98
170
|
logger.info('Starting unit tests', { package: packageName, objects });
|
|
99
171
|
|
|
100
172
|
try {
|
|
101
|
-
const
|
|
173
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
174
|
+
const data = {};
|
|
175
|
+
|
|
176
|
+
if (packageName) {
|
|
177
|
+
data.package = packageName;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (objects && objects.length > 0) {
|
|
181
|
+
data.objects = objects;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/unit', data, { csrfToken });
|
|
102
185
|
return {
|
|
103
186
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
104
187
|
test_count: result.TEST_COUNT || result.test_count || 0,
|
|
@@ -127,7 +210,26 @@ class ABAPGitAgent {
|
|
|
127
210
|
logger.info('Creating repository', { repoUrl, packageName, branch });
|
|
128
211
|
|
|
129
212
|
try {
|
|
130
|
-
const
|
|
213
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
214
|
+
const data = {
|
|
215
|
+
url: repoUrl,
|
|
216
|
+
package: packageName,
|
|
217
|
+
branch: branch
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
if (displayName) {
|
|
221
|
+
data.display_name = displayName;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (name) {
|
|
225
|
+
data.name = name;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (folderLogic) {
|
|
229
|
+
data.folder_logic = folderLogic;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/create', data, { csrfToken });
|
|
131
233
|
return {
|
|
132
234
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
133
235
|
repo_key: result.REPO_KEY || result.repo_key,
|
|
@@ -151,7 +253,16 @@ class ABAPGitAgent {
|
|
|
151
253
|
logger.info('Starting import operation', { repoUrl, message });
|
|
152
254
|
|
|
153
255
|
try {
|
|
154
|
-
const
|
|
256
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
257
|
+
const data = {
|
|
258
|
+
url: repoUrl
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
if (message) {
|
|
262
|
+
data.message = message;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/import', data, { csrfToken });
|
|
155
266
|
return {
|
|
156
267
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
157
268
|
files_staged: result.FILES_STAGED || result.files_staged || 0,
|
|
@@ -176,7 +287,14 @@ class ABAPGitAgent {
|
|
|
176
287
|
logger.info('Getting package tree', { package: packageName, depth, includeObjects });
|
|
177
288
|
|
|
178
289
|
try {
|
|
179
|
-
const
|
|
290
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
291
|
+
const data = {
|
|
292
|
+
package: packageName,
|
|
293
|
+
depth: Math.min(Math.max(1, depth), 10),
|
|
294
|
+
include_objects: includeObjects
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/tree', data, { csrfToken });
|
|
180
298
|
return {
|
|
181
299
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
182
300
|
command: result.COMMAND || result.command || 'TREE',
|
|
@@ -197,21 +315,43 @@ class ABAPGitAgent {
|
|
|
197
315
|
* @param {Array} objects - Array of table/view names
|
|
198
316
|
* @param {string} type - Object type (TABL, DDLS, etc.)
|
|
199
317
|
* @param {number} limit - Maximum rows to return
|
|
318
|
+
* @param {number} offset - Number of rows to skip
|
|
200
319
|
* @param {string} where - WHERE clause filter
|
|
201
320
|
* @param {Array} columns - Array of column names to display
|
|
202
321
|
* @returns {object} Preview result with rows, fields, and metadata
|
|
203
322
|
*/
|
|
204
|
-
async preview(objects, type = null, limit =
|
|
205
|
-
logger.info('Previewing data', { objects, type, limit, where, columns });
|
|
323
|
+
async preview(objects, type = null, limit = 100, offset = 0, where = null, columns = null) {
|
|
324
|
+
logger.info('Previewing data', { objects, type, limit, offset, where, columns });
|
|
206
325
|
|
|
207
326
|
try {
|
|
208
|
-
const
|
|
327
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
328
|
+
const data = {
|
|
329
|
+
objects: objects,
|
|
330
|
+
limit: Math.min(Math.max(1, limit), 500),
|
|
331
|
+
offset: Math.max(0, offset)
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
if (type) {
|
|
335
|
+
data.type = type;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (where) {
|
|
339
|
+
// Convert ISO date format (YYYY-MM-DD) to ABAP DATS format (YYYYMMDD)
|
|
340
|
+
data.where = this.convertDatesInWhereClause(where);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (columns) {
|
|
344
|
+
data.columns = columns;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/preview', data, { csrfToken });
|
|
209
348
|
return {
|
|
210
349
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
211
350
|
command: result.COMMAND || result.command || 'PREVIEW',
|
|
212
351
|
message: result.MESSAGE || result.message || '',
|
|
213
352
|
objects: result.OBJECTS || result.objects || [],
|
|
214
353
|
summary: result.SUMMARY || result.summary || null,
|
|
354
|
+
pagination: result.PAGINATION || result.pagination || null,
|
|
215
355
|
error: result.ERROR || result.error || null
|
|
216
356
|
};
|
|
217
357
|
} catch (error) {
|
|
@@ -220,6 +360,22 @@ class ABAPGitAgent {
|
|
|
220
360
|
}
|
|
221
361
|
}
|
|
222
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Convert ISO date formats to ABAP DATS format in WHERE clause
|
|
365
|
+
* @param {string} whereClause - SQL WHERE clause
|
|
366
|
+
* @returns {string} - WHERE clause with dates converted to YYYYMMDD format
|
|
367
|
+
*/
|
|
368
|
+
convertDatesInWhereClause(whereClause) {
|
|
369
|
+
if (!whereClause) return whereClause;
|
|
370
|
+
|
|
371
|
+
const isoDatePattern = /'\\d{4}-\\d{2}-\\d{2}'/g;
|
|
372
|
+
return whereClause.replace(isoDatePattern, (match) => {
|
|
373
|
+
const dateContent = match.slice(1, -1);
|
|
374
|
+
const [year, month, day] = dateContent.split('-');
|
|
375
|
+
return `'${year}${month}${day}'`;
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
223
379
|
/**
|
|
224
380
|
* List objects in an ABAP package
|
|
225
381
|
* @param {string} packageName - ABAP package name
|
|
@@ -233,7 +389,22 @@ class ABAPGitAgent {
|
|
|
233
389
|
logger.info('Listing objects', { package: packageName, type, name, limit, offset });
|
|
234
390
|
|
|
235
391
|
try {
|
|
236
|
-
const
|
|
392
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
393
|
+
const data = {
|
|
394
|
+
package: packageName,
|
|
395
|
+
limit: Math.min(Math.max(1, limit), 1000),
|
|
396
|
+
offset: Math.max(0, offset)
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
if (type) {
|
|
400
|
+
data.type = type;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (name) {
|
|
404
|
+
data.name = name;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/list', data, { csrfToken });
|
|
237
408
|
|
|
238
409
|
// Normalize objects array to use lowercase keys
|
|
239
410
|
const rawObjects = result.OBJECTS || result.objects || [];
|
|
@@ -275,7 +446,16 @@ class ABAPGitAgent {
|
|
|
275
446
|
logger.info('Viewing objects', { objects, type });
|
|
276
447
|
|
|
277
448
|
try {
|
|
278
|
-
const
|
|
449
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
450
|
+
const data = {
|
|
451
|
+
objects: objects
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
if (type) {
|
|
455
|
+
data.type = type;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/view', data, { csrfToken });
|
|
279
459
|
return {
|
|
280
460
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
281
461
|
command: result.COMMAND || result.command || 'VIEW',
|
|
@@ -293,18 +473,31 @@ class ABAPGitAgent {
|
|
|
293
473
|
* @param {Array} objects - Array of object names to search
|
|
294
474
|
* @param {string} type - Object type (optional)
|
|
295
475
|
* @param {number} limit - Maximum results (default: 100, max: 500)
|
|
476
|
+
* @param {number} offset - Number of results to skip (default: 0)
|
|
296
477
|
* @returns {object} Where-used result with found objects
|
|
297
478
|
*/
|
|
298
|
-
async where(objects, type = null, limit = 100) {
|
|
299
|
-
logger.info('Finding where-used', { objects, type, limit });
|
|
479
|
+
async where(objects, type = null, limit = 100, offset = 0) {
|
|
480
|
+
logger.info('Finding where-used', { objects, type, limit, offset });
|
|
300
481
|
|
|
301
482
|
try {
|
|
302
|
-
const
|
|
483
|
+
const csrfToken = await this.http.fetchCsrfToken();
|
|
484
|
+
const data = {
|
|
485
|
+
objects: objects,
|
|
486
|
+
limit: Math.min(Math.max(1, limit), 500),
|
|
487
|
+
offset: Math.max(0, offset)
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
if (type) {
|
|
491
|
+
data.type = type;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const result = await this.http.post('/sap/bc/z_abapgit_agent/where-used', data, { csrfToken });
|
|
303
495
|
return {
|
|
304
496
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
305
497
|
command: result.COMMAND || result.command || 'WHERE',
|
|
306
498
|
objects: result.OBJECTS || result.objects || [],
|
|
307
499
|
message: result.MESSAGE || result.message || '',
|
|
500
|
+
pagination: result.PAGINATION || result.pagination || null,
|
|
308
501
|
error: result.ERROR || result.error || null
|
|
309
502
|
};
|
|
310
503
|
} catch (error) {
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create command - Create abapGit online repository in ABAP system
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'create',
|
|
7
|
+
description: 'Create abapGit online repository in ABAP system',
|
|
8
|
+
requiresAbapConfig: true,
|
|
9
|
+
requiresVersionCheck: true,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
const { loadConfig, gitUtils, AbapHttp } = context;
|
|
13
|
+
|
|
14
|
+
// Show help if requested
|
|
15
|
+
const helpIndex = args.findIndex(a => a === '--help' || a === '-h');
|
|
16
|
+
if (helpIndex !== -1) {
|
|
17
|
+
console.log(`
|
|
18
|
+
Usage:
|
|
19
|
+
abapgit-agent create
|
|
20
|
+
|
|
21
|
+
Description:
|
|
22
|
+
Create abapGit online repository in ABAP system.
|
|
23
|
+
Auto-detects URL from git remote and package from .abapGitAgent.
|
|
24
|
+
|
|
25
|
+
Prerequisites:
|
|
26
|
+
- Run "abapgit-agent init" first
|
|
27
|
+
- Edit .abapGitAgent with credentials (host, user, password)
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
abapgit-agent create # Create repo in ABAP
|
|
31
|
+
`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Get parameters from config
|
|
36
|
+
const config = loadConfig();
|
|
37
|
+
const repoUrl = gitUtils.getRemoteUrl();
|
|
38
|
+
|
|
39
|
+
if (!repoUrl) {
|
|
40
|
+
console.error('Error: No git remote configured. Please configure a remote origin.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!config.package) {
|
|
45
|
+
console.error('Error: Package not configured. Run "abapgit-agent init" first or set package in .abapGitAgent.');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const branch = gitUtils.getBranch();
|
|
50
|
+
|
|
51
|
+
// Extract repo name from git URL
|
|
52
|
+
const repoName = repoUrl.split('/').pop().replace('.git', '');
|
|
53
|
+
|
|
54
|
+
console.log(`\nš Creating online repository`);
|
|
55
|
+
console.log(` URL: ${repoUrl}`);
|
|
56
|
+
console.log(` Package: ${config.package}`);
|
|
57
|
+
console.log(` Folder: ${config.folder || '/src/'}`);
|
|
58
|
+
console.log(` Name: ${repoName}`);
|
|
59
|
+
console.log(` Branch: ${branch}`);
|
|
60
|
+
|
|
61
|
+
const http = new AbapHttp(config);
|
|
62
|
+
const csrfToken = await http.fetchCsrfToken();
|
|
63
|
+
|
|
64
|
+
const data = {
|
|
65
|
+
url: repoUrl,
|
|
66
|
+
package: config.package,
|
|
67
|
+
name: repoName,
|
|
68
|
+
branch: branch,
|
|
69
|
+
folder: config.folder || '/src/'
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (config.gitUsername) {
|
|
73
|
+
data.username = config.gitUsername;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (config.gitPassword) {
|
|
77
|
+
data.password = config.gitPassword;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const result = await http.post('/sap/bc/z_abapgit_agent/create', data, { csrfToken });
|
|
81
|
+
|
|
82
|
+
console.log('\n');
|
|
83
|
+
|
|
84
|
+
// Handle uppercase keys from ABAP
|
|
85
|
+
const success = result.SUCCESS || result.success;
|
|
86
|
+
const repoKey = result.REPO_KEY || result.repo_key;
|
|
87
|
+
const createdRepoName = result.REPO_NAME || result.repo_name;
|
|
88
|
+
const message = result.MESSAGE || result.message;
|
|
89
|
+
const error = result.ERROR || result.error;
|
|
90
|
+
|
|
91
|
+
if (success === 'X' || success === true) {
|
|
92
|
+
console.log(`ā
Repository created successfully!`);
|
|
93
|
+
console.log(` URL: ${repoUrl}`);
|
|
94
|
+
console.log(` Package: ${config.package}`);
|
|
95
|
+
console.log(` Name: ${createdRepoName || repoName}`);
|
|
96
|
+
} else {
|
|
97
|
+
console.log(`ā Failed to create repository`);
|
|
98
|
+
console.log(` Error: ${error || message || 'Unknown error'}`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete command - Delete abapGit online repository from ABAP system
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'delete',
|
|
7
|
+
description: 'Delete abapGit online repository from ABAP system',
|
|
8
|
+
requiresAbapConfig: true,
|
|
9
|
+
requiresVersionCheck: true,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
const { loadConfig, gitUtils, AbapHttp } = context;
|
|
13
|
+
|
|
14
|
+
// Show help if requested
|
|
15
|
+
const helpIndex = args.findIndex(a => a === '--help' || a === '-h');
|
|
16
|
+
if (helpIndex !== -1) {
|
|
17
|
+
console.log(`
|
|
18
|
+
Usage:
|
|
19
|
+
abapgit-agent delete
|
|
20
|
+
|
|
21
|
+
Description:
|
|
22
|
+
Delete abapGit online repository from ABAP system.
|
|
23
|
+
Auto-detects URL from git remote of current directory.
|
|
24
|
+
|
|
25
|
+
Prerequisites:
|
|
26
|
+
- Run "abapgit-agent create" first
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
abapgit-agent delete # Delete repo for current git remote
|
|
30
|
+
`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Get URL from current git remote
|
|
35
|
+
const config = loadConfig();
|
|
36
|
+
const repoUrl = gitUtils.getRemoteUrl();
|
|
37
|
+
|
|
38
|
+
if (!repoUrl) {
|
|
39
|
+
console.error('Error: No git remote configured. Please configure a remote origin.');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(`\nšļø Deleting online repository`);
|
|
44
|
+
console.log(` URL: ${repoUrl}`);
|
|
45
|
+
|
|
46
|
+
const http = new AbapHttp(config);
|
|
47
|
+
const csrfToken = await http.fetchCsrfToken();
|
|
48
|
+
|
|
49
|
+
const data = {
|
|
50
|
+
url: repoUrl
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const result = await http.post('/sap/bc/z_abapgit_agent/delete', data, { csrfToken });
|
|
54
|
+
|
|
55
|
+
console.log('\n');
|
|
56
|
+
|
|
57
|
+
// Handle uppercase keys from ABAP
|
|
58
|
+
const success = result.SUCCESS || result.success;
|
|
59
|
+
const repoKey = result.REPO_KEY || result.repo_key;
|
|
60
|
+
const message = result.MESSAGE || result.message;
|
|
61
|
+
const error = result.ERROR || result.error;
|
|
62
|
+
|
|
63
|
+
if (success === 'X' || success === true) {
|
|
64
|
+
console.log(`ā
Repository deleted successfully!`);
|
|
65
|
+
console.log(` Key: ${repoKey}`);
|
|
66
|
+
} else {
|
|
67
|
+
console.log(`ā Failed to delete repository`);
|
|
68
|
+
console.log(` Error: ${error || message || 'Unknown error'}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health command - Check ABAP REST API health
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'health',
|
|
7
|
+
description: 'Check if ABAP REST API is healthy',
|
|
8
|
+
requiresAbapConfig: true,
|
|
9
|
+
requiresVersionCheck: false,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
const { config, AbapHttp } = context;
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const http = new AbapHttp(config);
|
|
16
|
+
const result = await http.get('/sap/bc/z_abapgit_agent/health');
|
|
17
|
+
console.log(JSON.stringify(result, null, 2));
|
|
18
|
+
return result;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error(`Health check failed: ${error.message}`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|