abapgit-agent 1.7.2 → 1.8.1
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 +26 -8
- package/abap/CLAUDE.md +146 -26
- package/abap/guidelines/00_index.md +8 -0
- package/abap/guidelines/01_sql.md +28 -0
- package/abap/guidelines/02_exceptions.md +8 -0
- package/abap/guidelines/03_testing.md +8 -0
- package/abap/guidelines/04_cds.md +151 -36
- 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 +52 -3
- package/abap/guidelines/09_unit_testable_code.md +8 -0
- package/abap/guidelines/10_common_errors.md +95 -0
- package/bin/abapgit-agent +61 -2852
- package/package.json +21 -5
- package/src/agent.js +205 -16
- 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 +340 -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/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 -526
- /package/src/{ref-search.js → utils/abap-reference.js} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abapgit-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
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": [
|
|
@@ -19,11 +19,21 @@
|
|
|
19
19
|
"start": "node src/server.js",
|
|
20
20
|
"dev": "nodemon src/server.js",
|
|
21
21
|
"test": "jest",
|
|
22
|
-
"test:all": "node
|
|
22
|
+
"test:all": "node tests/run-all.js",
|
|
23
|
+
"test:unit": "jest",
|
|
23
24
|
"test:jest": "jest",
|
|
24
|
-
"test:
|
|
25
|
-
"test:
|
|
26
|
-
"test:cmd
|
|
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",
|
|
27
37
|
"pull": "node bin/abapgit-agent",
|
|
28
38
|
"release": "node scripts/release.js",
|
|
29
39
|
"unrelease": "node scripts/unrelease.js"
|
|
@@ -43,5 +53,11 @@
|
|
|
43
53
|
},
|
|
44
54
|
"engines": {
|
|
45
55
|
"node": ">=16.0.0"
|
|
56
|
+
},
|
|
57
|
+
"jest": {
|
|
58
|
+
"testMatch": [
|
|
59
|
+
"**/tests/unit/**/*.test.js"
|
|
60
|
+
],
|
|
61
|
+
"testEnvironment": "node"
|
|
46
62
|
}
|
|
47
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',
|
|
@@ -206,7 +324,27 @@ class ABAPGitAgent {
|
|
|
206
324
|
logger.info('Previewing data', { objects, type, limit, offset, where, columns });
|
|
207
325
|
|
|
208
326
|
try {
|
|
209
|
-
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 });
|
|
210
348
|
return {
|
|
211
349
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
212
350
|
command: result.COMMAND || result.command || 'PREVIEW',
|
|
@@ -222,6 +360,22 @@ class ABAPGitAgent {
|
|
|
222
360
|
}
|
|
223
361
|
}
|
|
224
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
|
+
|
|
225
379
|
/**
|
|
226
380
|
* List objects in an ABAP package
|
|
227
381
|
* @param {string} packageName - ABAP package name
|
|
@@ -235,7 +389,22 @@ class ABAPGitAgent {
|
|
|
235
389
|
logger.info('Listing objects', { package: packageName, type, name, limit, offset });
|
|
236
390
|
|
|
237
391
|
try {
|
|
238
|
-
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 });
|
|
239
408
|
|
|
240
409
|
// Normalize objects array to use lowercase keys
|
|
241
410
|
const rawObjects = result.OBJECTS || result.objects || [];
|
|
@@ -277,7 +446,16 @@ class ABAPGitAgent {
|
|
|
277
446
|
logger.info('Viewing objects', { objects, type });
|
|
278
447
|
|
|
279
448
|
try {
|
|
280
|
-
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 });
|
|
281
459
|
return {
|
|
282
460
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
283
461
|
command: result.COMMAND || result.command || 'VIEW',
|
|
@@ -302,7 +480,18 @@ class ABAPGitAgent {
|
|
|
302
480
|
logger.info('Finding where-used', { objects, type, limit, offset });
|
|
303
481
|
|
|
304
482
|
try {
|
|
305
|
-
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 });
|
|
306
495
|
return {
|
|
307
496
|
success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
|
|
308
497
|
command: result.COMMAND || result.command || 'WHERE',
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Help command - Display usage information
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'help',
|
|
7
|
+
description: 'Display usage information and available commands',
|
|
8
|
+
requiresAbapConfig: false,
|
|
9
|
+
requiresVersionCheck: false,
|
|
10
|
+
|
|
11
|
+
async execute(args, context) {
|
|
12
|
+
console.log(`
|
|
13
|
+
ABAP Git Agent
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
abapgit-agent <command> [options]
|
|
17
|
+
|
|
18
|
+
Commands:
|
|
19
|
+
init --folder <folder> --package <package>
|
|
20
|
+
Initialize local configuration for an existing git repository.
|
|
21
|
+
init --update
|
|
22
|
+
Update existing files (CLAUDE.md, copilot-instructions.md, guidelines) to latest version.
|
|
23
|
+
|
|
24
|
+
create
|
|
25
|
+
Create abapGit online repository in ABAP system.
|
|
26
|
+
Auto-detects URL from git remote and package from .abapGitAgent.
|
|
27
|
+
|
|
28
|
+
import [--message <message>]
|
|
29
|
+
Import existing objects from package to git repository.
|
|
30
|
+
Uses the git remote URL to find the abapGit online repository.
|
|
31
|
+
|
|
32
|
+
pull [--url <git-url>] [--branch <branch>] [--files <file1,file2,...>] [--transport <request>]
|
|
33
|
+
Pull and activate repository in ABAP system.
|
|
34
|
+
Auto-detects git remote and branch from current directory.
|
|
35
|
+
Use --files to pull only specific files.
|
|
36
|
+
Use --transport to specify a transport request.
|
|
37
|
+
|
|
38
|
+
inspect --files <file1>,<file2>,...
|
|
39
|
+
Inspect ABAP source file(s) for issues. Currently runs syntax check.
|
|
40
|
+
|
|
41
|
+
syntax --files <file1>,<file2>,... [--cloud] [--json]
|
|
42
|
+
Check syntax of ABAP source files WITHOUT pull/activation.
|
|
43
|
+
Reads source from local files and checks directly in ABAP system.
|
|
44
|
+
Use --cloud for ABAP Cloud (BTP) stricter syntax checking.
|
|
45
|
+
|
|
46
|
+
unit --files <file1>,<file2>,...
|
|
47
|
+
Run AUnit tests for ABAP test class files (.testclasses.abap)
|
|
48
|
+
|
|
49
|
+
tree --package <package> [--depth <n>] [--include-types] [--json]
|
|
50
|
+
Display package hierarchy tree from ABAP system
|
|
51
|
+
|
|
52
|
+
list --package <package> [--type <types>] [--name <pattern>] [--limit <n>] [--offset <n>] [--json]
|
|
53
|
+
List ABAP objects in a package with filtering and pagination
|
|
54
|
+
|
|
55
|
+
view --objects <obj1>,<obj2>,... [--type <type>] [--json]
|
|
56
|
+
View ABAP object definitions from the ABAP system
|
|
57
|
+
|
|
58
|
+
where --objects <obj1>,<obj2>,... [--type <type>] [--limit <n>] [--json]
|
|
59
|
+
Find where-used list for ABAP objects (classes, interfaces, programs)
|
|
60
|
+
|
|
61
|
+
ref <pattern> [--json]
|
|
62
|
+
Search ABAP reference repositories for patterns. Requires referenceFolder in .abapGitAgent.
|
|
63
|
+
|
|
64
|
+
ref --topic <topic> [--json]
|
|
65
|
+
View specific topic from cheat sheets (exceptions, sql, unit-tests, etc.)
|
|
66
|
+
|
|
67
|
+
ref --list-topics
|
|
68
|
+
List available topics for reference search
|
|
69
|
+
|
|
70
|
+
ref --list-repos
|
|
71
|
+
List all reference repositories in the reference folder
|
|
72
|
+
|
|
73
|
+
ref --clone <repo> [--name <folder>]
|
|
74
|
+
Clone a GitHub repository to the reference folder
|
|
75
|
+
- Use full URL: https://github.com/user/repo.git
|
|
76
|
+
- Or short name: user/repo or user/repo (assumes github.com)
|
|
77
|
+
|
|
78
|
+
health
|
|
79
|
+
Check if ABAP REST API is healthy
|
|
80
|
+
|
|
81
|
+
status
|
|
82
|
+
Check if ABAP integration is configured for this repo
|
|
83
|
+
|
|
84
|
+
Examples:
|
|
85
|
+
abapgit-agent init --folder /src --package ZMY_PACKAGE # Initialize
|
|
86
|
+
abapgit-agent init --update # Update files to latest
|
|
87
|
+
abapgit-agent create # Create repo
|
|
88
|
+
abapgit-agent delete # Delete repo
|
|
89
|
+
abapgit-agent import # Import objects to git
|
|
90
|
+
abapgit-agent import --message "Initial import" # Import with message
|
|
91
|
+
abapgit-agent pull # Auto-detect from git
|
|
92
|
+
abapgit-agent pull --branch develop # Specific branch
|
|
93
|
+
abapgit-agent pull --files src/zcl_my_class.clas.abap # Specific file
|
|
94
|
+
abapgit-agent pull --transport DEVK900001 # With transport
|
|
95
|
+
abapgit-agent inspect --files src/zcl_my_class.clas.abap # Syntax check
|
|
96
|
+
abapgit-agent syntax --files src/zcl_my_class.clas.abap # Check without pull
|
|
97
|
+
abapgit-agent syntax --files src/zmy_prog.prog.abap --cloud # ABAP Cloud check
|
|
98
|
+
abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap # Run unit tests
|
|
99
|
+
abapgit-agent tree --package $MY_PACKAGE # Display package tree
|
|
100
|
+
abapgit-agent list --package $MY_PACKAGE --type CLAS,INTF # List classes & interfaces
|
|
101
|
+
abapgit-agent view --objects ZCL_MY_CLASS # View class definition
|
|
102
|
+
abapgit-agent where --objects ZCL_MY_CLASS # Find where class is used
|
|
103
|
+
abapgit-agent ref "CORRESPONDING" # Search for pattern
|
|
104
|
+
abapgit-agent ref --topic exceptions # View exceptions topic
|
|
105
|
+
abapgit-agent health # Health check
|
|
106
|
+
abapgit-agent status # Configuration status
|
|
107
|
+
|
|
108
|
+
For more info: https://github.tools.sap/I045696/abapgit-agent
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
};
|