abapgit-agent 1.15.3 → 1.16.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/abap/CLAUDE.md +61 -12
- package/abap/guidelines/abaplint.md +35 -0
- package/abap/guidelines/common-errors.md +78 -1
- package/abap/guidelines/string-template.md +84 -0
- package/package.json +2 -1
- package/src/commands/drop.js +171 -0
- package/src/commands/dump.js +30 -0
- package/src/commands/health.js +12 -0
- package/src/commands/help.js +32 -1
- package/src/commands/index.js +2 -1
- package/src/commands/inspect.js +23 -0
- package/src/commands/lint.js +26 -0
- package/src/commands/list.js +25 -0
- package/src/commands/preview.js +30 -0
- package/src/commands/pull.js +32 -0
- package/src/commands/run.js +21 -0
- package/src/commands/status.js +13 -0
- package/src/commands/syntax.js +143 -17
- package/src/commands/tree.js +22 -0
- package/src/commands/unit.js +23 -0
- package/src/commands/upgrade.js +28 -0
- package/src/commands/view.js +29 -0
- package/src/commands/where.js +24 -0
- package/src/utils/abap-reference.js +9 -10
package/src/commands/help.js
CHANGED
|
@@ -48,6 +48,24 @@ Commands:
|
|
|
48
48
|
unit --files <file1>,<file2>,...
|
|
49
49
|
Run AUnit tests for ABAP test class files (.testclasses.abap)
|
|
50
50
|
|
|
51
|
+
run --program <NAME> | --class <NAME>
|
|
52
|
+
Execute an ABAP program or class (IF_OO_ADT_CLASSRUN) and display its output.
|
|
53
|
+
|
|
54
|
+
drop --files <file> [--pull] [--transport <TRANSPORT>] [--conflict-mode <mode>]
|
|
55
|
+
Physically delete a single ABAP object from the ABAP system.
|
|
56
|
+
Use --pull to immediately re-activate from git after deletion.
|
|
57
|
+
|
|
58
|
+
lint [--files <file1,...>] [--base <branch>] [--config <file>]
|
|
59
|
+
Run abaplint static analysis on changed ABAP files. Requires .abaplint.json.
|
|
60
|
+
|
|
61
|
+
debug <subcommand> [options]
|
|
62
|
+
Manage ABAP debugger breakpoints and attach debug sessions.
|
|
63
|
+
Subcommands: set, list, delete, attach, step, vars, stack
|
|
64
|
+
|
|
65
|
+
transport <subcommand> [options]
|
|
66
|
+
List and manage SAP transport requests.
|
|
67
|
+
Subcommands: list, create, release
|
|
68
|
+
|
|
51
69
|
tree --package <package> [--depth <n>] [--include-types] [--json]
|
|
52
70
|
Display package hierarchy tree from ABAP system
|
|
53
71
|
|
|
@@ -57,6 +75,9 @@ Commands:
|
|
|
57
75
|
view --objects <obj1>,<obj2>,... [--type <type>] [--json]
|
|
58
76
|
View ABAP object definitions from the ABAP system
|
|
59
77
|
|
|
78
|
+
preview --objects <obj1>,... [--type <type>] [--limit <n>] [--where <cond>] [--json]
|
|
79
|
+
Preview data from ABAP tables or CDS views
|
|
80
|
+
|
|
60
81
|
where --objects <obj1>,<obj2>,... [--type <type>] [--limit <n>] [--json]
|
|
61
82
|
Find where-used list for ABAP objects (classes, interfaces, programs)
|
|
62
83
|
|
|
@@ -93,6 +114,9 @@ Commands:
|
|
|
93
114
|
- Use --dry-run to preview changes without applying them
|
|
94
115
|
- Use --yes to skip confirmation prompt
|
|
95
116
|
|
|
117
|
+
upgrade [--abap-only] [--cli-only] [--version <v>]
|
|
118
|
+
Upgrade CLI and/or ABAP backend to latest or specific version.
|
|
119
|
+
|
|
96
120
|
health
|
|
97
121
|
Check if ABAP REST API is healthy
|
|
98
122
|
|
|
@@ -114,9 +138,14 @@ Examples:
|
|
|
114
138
|
abapgit-agent syntax --files src/zcl_my_class.clas.abap # Check without pull
|
|
115
139
|
abapgit-agent syntax --files src/zmy_prog.prog.abap --cloud # ABAP Cloud check
|
|
116
140
|
abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap # Run unit tests
|
|
117
|
-
abapgit-agent
|
|
141
|
+
abapgit-agent run --program ZMY_REPORT # Execute report
|
|
142
|
+
abapgit-agent run --class ZCL_MY_RUNNER # Execute class
|
|
143
|
+
abapgit-agent drop --files src/zcl_foo.clas.abap --pull # Drop and re-activate
|
|
144
|
+
abapgit-agent lint # abaplint on changed files
|
|
145
|
+
abapgit-agent tree --package $MY_PACKAGE # Display package tree
|
|
118
146
|
abapgit-agent list --package $MY_PACKAGE --type CLAS,INTF # List classes & interfaces
|
|
119
147
|
abapgit-agent view --objects ZCL_MY_CLASS # View class definition
|
|
148
|
+
abapgit-agent preview --objects SFLIGHT # Preview table data
|
|
120
149
|
abapgit-agent where --objects ZCL_MY_CLASS # Find where class is used
|
|
121
150
|
abapgit-agent dump --date TODAY # Recent short dumps
|
|
122
151
|
abapgit-agent dump --user DEVELOPER --detail 1 # Full detail of first result
|
|
@@ -127,6 +156,8 @@ Examples:
|
|
|
127
156
|
abapgit-agent health # Health check
|
|
128
157
|
abapgit-agent status # Configuration status
|
|
129
158
|
|
|
159
|
+
Run "abapgit-agent <command> --help" for detailed usage of any command.
|
|
160
|
+
|
|
130
161
|
For more info: https://github.com/SylvosCai/abapgit-agent
|
|
131
162
|
`);
|
|
132
163
|
}
|
package/src/commands/index.js
CHANGED
package/src/commands/inspect.js
CHANGED
|
@@ -250,6 +250,29 @@ module.exports = {
|
|
|
250
250
|
async execute(args, context) {
|
|
251
251
|
const { loadConfig, AbapHttp } = context;
|
|
252
252
|
|
|
253
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
254
|
+
console.log(`
|
|
255
|
+
Usage:
|
|
256
|
+
abapgit-agent inspect --files <file1>,<file2>,... [--variant <check-variant>] [--junit-output <file>] [--json]
|
|
257
|
+
|
|
258
|
+
Description:
|
|
259
|
+
Run SAP Code Inspector checks on activated ABAP objects. Requires the objects
|
|
260
|
+
to be already active in the ABAP system (run pull first).
|
|
261
|
+
|
|
262
|
+
Parameters:
|
|
263
|
+
--files <file1,...> Comma-separated ABAP source files (required).
|
|
264
|
+
--variant <variant> Code Inspector variant (default: system default).
|
|
265
|
+
--junit-output <file> Write results as JUnit XML to this file.
|
|
266
|
+
--json Output as JSON.
|
|
267
|
+
|
|
268
|
+
Examples:
|
|
269
|
+
abapgit-agent inspect --files src/zcl_my_class.clas.abap
|
|
270
|
+
abapgit-agent inspect --files src/zcl_my_class.clas.abap --variant ALL_CHECKS
|
|
271
|
+
abapgit-agent inspect --files src/zcl_my_class.clas.abap --junit-output reports/inspect.xml
|
|
272
|
+
`);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
253
276
|
const jsonOutput = args.includes('--json');
|
|
254
277
|
const verbose = args.includes('--verbose');
|
|
255
278
|
const filesArgIndex = args.indexOf('--files');
|
package/src/commands/lint.js
CHANGED
|
@@ -24,6 +24,32 @@ module.exports = {
|
|
|
24
24
|
requiresAbapConfig: false,
|
|
25
25
|
|
|
26
26
|
execute(args) {
|
|
27
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
28
|
+
console.log(`
|
|
29
|
+
Usage:
|
|
30
|
+
abapgit-agent lint [--files <file1,...>] [--base <branch>] [--config <file>]
|
|
31
|
+
[--outformat <format>] [--outfile <file>]
|
|
32
|
+
|
|
33
|
+
Description:
|
|
34
|
+
Run abaplint static analysis on changed ABAP files. Requires .abaplint.json in repo root.
|
|
35
|
+
By default detects files changed vs HEAD~1 (or vs --base branch).
|
|
36
|
+
|
|
37
|
+
Parameters:
|
|
38
|
+
--files <file1,...> Check specific files instead of auto-detecting changed files.
|
|
39
|
+
--base <branch> Diff against this branch instead of HEAD~1 (e.g. main).
|
|
40
|
+
--config <file> abaplint config file (default: .abaplint.json).
|
|
41
|
+
--outformat <format> Output format: checkstyle (default: text).
|
|
42
|
+
--outfile <file> Write output to file instead of stdout.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
abapgit-agent lint
|
|
46
|
+
abapgit-agent lint --base main
|
|
47
|
+
abapgit-agent lint --files src/zcl_foo.clas.abap
|
|
48
|
+
abapgit-agent lint --outformat checkstyle --outfile reports/abaplint.xml
|
|
49
|
+
`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
27
53
|
const configPath = argValue(args, '--config') || '.abaplint.json';
|
|
28
54
|
const baseBranch = argValue(args, '--base');
|
|
29
55
|
const filesArg = argValue(args, '--files');
|
package/src/commands/list.js
CHANGED
|
@@ -11,6 +11,31 @@ module.exports = {
|
|
|
11
11
|
async execute(args, context) {
|
|
12
12
|
const { loadConfig, AbapHttp } = context;
|
|
13
13
|
|
|
14
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
15
|
+
console.log(`
|
|
16
|
+
Usage:
|
|
17
|
+
abapgit-agent list --package <package> [--type <types>] [--name <pattern>] [--limit <n>] [--offset <n>] [--json]
|
|
18
|
+
|
|
19
|
+
Description:
|
|
20
|
+
List ABAP objects in a package with optional filtering and pagination.
|
|
21
|
+
|
|
22
|
+
Parameters:
|
|
23
|
+
--package <package> Package to list (required). Enclose $-packages in quotes.
|
|
24
|
+
--type <types> Comma-separated object types to filter (e.g. CLAS,INTF).
|
|
25
|
+
--name <pattern> Filter by object name pattern (e.g. ZCL_MY*).
|
|
26
|
+
--limit <n> Maximum number of results (default: 100).
|
|
27
|
+
--offset <n> Skip first N results (for pagination).
|
|
28
|
+
--json Output as JSON.
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
abapgit-agent list --package ZMY_PACKAGE
|
|
32
|
+
abapgit-agent list --package ZMY_PACKAGE --type CLAS,INTF
|
|
33
|
+
abapgit-agent list --package ZMY_PACKAGE --name ZCL_MY*
|
|
34
|
+
abapgit-agent list --package ZMY_PACKAGE --limit 20 --offset 40
|
|
35
|
+
`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
14
39
|
const packageArgIndex = args.indexOf('--package');
|
|
15
40
|
if (packageArgIndex === -1) {
|
|
16
41
|
console.error('Error: --package parameter required');
|
package/src/commands/preview.js
CHANGED
|
@@ -11,6 +11,36 @@ module.exports = {
|
|
|
11
11
|
async execute(args, context) {
|
|
12
12
|
const { loadConfig, AbapHttp, validators } = context;
|
|
13
13
|
|
|
14
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
15
|
+
console.log(`
|
|
16
|
+
Usage:
|
|
17
|
+
abapgit-agent preview --objects <obj1>,... [--type <type>] [--limit <n>] [--offset <n>]
|
|
18
|
+
[--where <condition>] [--columns <cols>] [--vertical] [--compact] [--json]
|
|
19
|
+
|
|
20
|
+
Description:
|
|
21
|
+
Preview data from ABAP tables or CDS views.
|
|
22
|
+
|
|
23
|
+
Parameters:
|
|
24
|
+
--objects <obj1,...> Comma-separated table/view names (required).
|
|
25
|
+
--type <type> Object type: TABL, DDLS (auto-detected if omitted).
|
|
26
|
+
--limit <n> Maximum number of rows (default: 20).
|
|
27
|
+
--offset <n> Skip first N rows (for pagination).
|
|
28
|
+
--where <condition> WHERE clause filter (e.g. "CARRID = 'AA'").
|
|
29
|
+
--columns <cols> Comma-separated column names to display.
|
|
30
|
+
--vertical Display each row vertically (field: value).
|
|
31
|
+
--compact Compact output (no borders).
|
|
32
|
+
--json Output as JSON.
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
abapgit-agent preview --objects SFLIGHT
|
|
36
|
+
abapgit-agent preview --objects SFLIGHT --limit 5
|
|
37
|
+
abapgit-agent preview --objects SFLIGHT --where "CARRID = 'AA'"
|
|
38
|
+
abapgit-agent preview --objects ZC_MY_VIEW --type DDLS
|
|
39
|
+
abapgit-agent preview --objects SFLIGHT --offset 10 --limit 20
|
|
40
|
+
`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
14
44
|
const objectsArgIndex = args.indexOf('--objects');
|
|
15
45
|
if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
|
|
16
46
|
console.error('Error: --objects parameter required');
|
package/src/commands/pull.js
CHANGED
|
@@ -42,6 +42,38 @@ module.exports = {
|
|
|
42
42
|
|
|
43
43
|
async execute(args, context) {
|
|
44
44
|
const { loadConfig, AbapHttp, gitUtils, getTransport, getSafeguards, getConflictSettings, getTransportSettings } = context;
|
|
45
|
+
|
|
46
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
47
|
+
console.log(`
|
|
48
|
+
Usage:
|
|
49
|
+
abapgit-agent pull [--url <git-url>] [--branch <branch>] [--files <file1,file2,...>]
|
|
50
|
+
[--transport <TRANSPORT>] [--conflict-mode <mode>] [--sync-xml]
|
|
51
|
+
|
|
52
|
+
Description:
|
|
53
|
+
Pull and activate ABAP objects from a git repository into the ABAP system.
|
|
54
|
+
Auto-detects git remote URL and branch from the current directory.
|
|
55
|
+
|
|
56
|
+
Parameters:
|
|
57
|
+
--url <git-url> Git repository URL. Auto-detected from git remote if omitted.
|
|
58
|
+
--branch <branch> Branch to pull from. Auto-detected from current branch if omitted.
|
|
59
|
+
--files <file1,...> Comma-separated list of files to pull (selective activation).
|
|
60
|
+
--transport <TRANSPORT> Transport request (e.g. DEVK900001).
|
|
61
|
+
--conflict-mode <mode> Conflict handling: abort (default) or ignore.
|
|
62
|
+
--sync-xml Rewrite XML metadata files to match ABAP serializer output.
|
|
63
|
+
--verbose Show detailed activation output.
|
|
64
|
+
|
|
65
|
+
Examples:
|
|
66
|
+
abapgit-agent pull
|
|
67
|
+
abapgit-agent pull --branch develop
|
|
68
|
+
abapgit-agent pull --files src/zcl_my_class.clas.abap
|
|
69
|
+
abapgit-agent pull --files src/zcl_foo.clas.abap,src/zif_foo.intf.abap
|
|
70
|
+
abapgit-agent pull --transport DEVK900001
|
|
71
|
+
abapgit-agent pull --conflict-mode ignore
|
|
72
|
+
abapgit-agent pull --files src/zcl_foo.clas.abap --sync-xml
|
|
73
|
+
`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
45
77
|
const verbose = args.includes('--verbose');
|
|
46
78
|
const syncXml = args.includes('--sync-xml');
|
|
47
79
|
|
package/src/commands/run.js
CHANGED
|
@@ -33,6 +33,27 @@ module.exports = {
|
|
|
33
33
|
async execute(args, context) {
|
|
34
34
|
const { loadConfig, getSafeguards } = context;
|
|
35
35
|
|
|
36
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
37
|
+
console.log(`
|
|
38
|
+
Usage:
|
|
39
|
+
abapgit-agent run --program <NAME>
|
|
40
|
+
abapgit-agent run --class <NAME>
|
|
41
|
+
|
|
42
|
+
Description:
|
|
43
|
+
Execute an ABAP program or a class implementing IF_OO_ADT_CLASSRUN and display its output.
|
|
44
|
+
|
|
45
|
+
Parameters:
|
|
46
|
+
--program <NAME> Execute an ABAP report/program.
|
|
47
|
+
--class <NAME> Execute a class implementing IF_OO_ADT_CLASSRUN (run method).
|
|
48
|
+
--json Output as JSON.
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
abapgit-agent run --program ZMY_REPORT
|
|
52
|
+
abapgit-agent run --class ZCL_MY_RUNNER
|
|
53
|
+
`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
36
57
|
// Check project-level safeguards
|
|
37
58
|
const safeguards = getSafeguards();
|
|
38
59
|
if (safeguards.disableRun) {
|
package/src/commands/status.js
CHANGED
|
@@ -13,6 +13,19 @@ module.exports = {
|
|
|
13
13
|
async execute(args, context) {
|
|
14
14
|
const { gitUtils, isAbapIntegrationEnabled, AbapHttp, loadConfig } = context;
|
|
15
15
|
|
|
16
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
17
|
+
console.log(`
|
|
18
|
+
Usage:
|
|
19
|
+
abapgit-agent status
|
|
20
|
+
|
|
21
|
+
Description:
|
|
22
|
+
Check whether ABAP integration is configured for the current repository.
|
|
23
|
+
Shows the config location, SAP host, and whether the abapGit online repository
|
|
24
|
+
is registered in the ABAP system.
|
|
25
|
+
`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
if (isAbapIntegrationEnabled()) {
|
|
17
30
|
console.log('✅ ABAP Git Agent is ENABLED');
|
|
18
31
|
console.log(' Config location:', pathModule.join(process.cwd(), '.abapGitAgent'));
|
package/src/commands/syntax.js
CHANGED
|
@@ -14,6 +14,28 @@ module.exports = {
|
|
|
14
14
|
async execute(args, context) {
|
|
15
15
|
const { loadConfig, AbapHttp } = context;
|
|
16
16
|
|
|
17
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
18
|
+
console.log(`
|
|
19
|
+
Usage:
|
|
20
|
+
abapgit-agent syntax --files <file1>,<file2>,... [--cloud] [--json]
|
|
21
|
+
|
|
22
|
+
Description:
|
|
23
|
+
Check syntax of local ABAP source files WITHOUT pulling or activating them.
|
|
24
|
+
Reads source from local files and checks directly in the ABAP system.
|
|
25
|
+
|
|
26
|
+
Parameters:
|
|
27
|
+
--files <file1,...> Comma-separated ABAP source files (required). Accepts CLAS, INTF, PROG.
|
|
28
|
+
--cloud Use ABAP Cloud (BTP) stricter syntax check.
|
|
29
|
+
--json Output as JSON.
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
abapgit-agent syntax --files src/zcl_my_class.clas.abap
|
|
33
|
+
abapgit-agent syntax --files src/zcl_foo.clas.abap,src/zif_foo.intf.abap
|
|
34
|
+
abapgit-agent syntax --files src/zmy_prog.prog.abap --cloud
|
|
35
|
+
`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
17
39
|
const filesArgIndex = args.indexOf('--files');
|
|
18
40
|
if (filesArgIndex === -1 || filesArgIndex + 1 >= args.length) {
|
|
19
41
|
console.error('Error: --files parameter required');
|
|
@@ -48,6 +70,7 @@ module.exports = {
|
|
|
48
70
|
// Build objects array from files
|
|
49
71
|
// Group class files together (main + locals)
|
|
50
72
|
const classFilesMap = new Map(); // className -> { main, locals_def, locals_imp }
|
|
73
|
+
const fugrGroupMap = new Map(); // groupName -> { dir, fmFiles: Map<fmName, source> }
|
|
51
74
|
const objects = [];
|
|
52
75
|
|
|
53
76
|
for (const file of syntaxFiles) {
|
|
@@ -83,6 +106,35 @@ module.exports = {
|
|
|
83
106
|
objType = 'DDLS';
|
|
84
107
|
objName = baseName.split('.')[0].toUpperCase();
|
|
85
108
|
fileKind = 'main';
|
|
109
|
+
} else if (baseName.includes('.fugr.')) {
|
|
110
|
+
objType = 'FUGR';
|
|
111
|
+
const parts = baseName.split('.'); // e.g. ['zmy_fugr', 'fugr', 'zmy_my_function', 'abap']
|
|
112
|
+
objName = parts[0].toUpperCase(); // group name e.g. 'ZMY_FUGR'
|
|
113
|
+
const includeFile = parts[2] || ''; // e.g. 'zmy_my_function', 'lzmy_fugrtop', 'saplzmy_fugr'
|
|
114
|
+
const groupLower = parts[0].toLowerCase();
|
|
115
|
+
const isTopInclude = new RegExp(`^l${groupLower}top$`, 'i').test(includeFile);
|
|
116
|
+
const isUInclude = new RegExp(`^l${groupLower}u\\d+$`, 'i').test(includeFile);
|
|
117
|
+
const isSapl = includeFile.toLowerCase().startsWith('sapl');
|
|
118
|
+
const isFm = !isTopInclude && !isUInclude && !isSapl && includeFile !== '';
|
|
119
|
+
|
|
120
|
+
// Read source and store in fugrGroupMap
|
|
121
|
+
const filePath = pathModule.resolve(file);
|
|
122
|
+
if (!fs.existsSync(filePath)) {
|
|
123
|
+
console.error(` Error: File not found: ${file}`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const source = fs.readFileSync(filePath, 'utf8');
|
|
127
|
+
const dir = pathModule.dirname(filePath);
|
|
128
|
+
|
|
129
|
+
if (!fugrGroupMap.has(objName)) {
|
|
130
|
+
fugrGroupMap.set(objName, { dir, fmFiles: new Map() });
|
|
131
|
+
}
|
|
132
|
+
if (isFm) {
|
|
133
|
+
const fmName = includeFile.toUpperCase();
|
|
134
|
+
fugrGroupMap.get(objName).fmFiles.set(fmName, source);
|
|
135
|
+
}
|
|
136
|
+
// Skip adding to objects here — handled after auto-detection below
|
|
137
|
+
continue;
|
|
86
138
|
}
|
|
87
139
|
|
|
88
140
|
// Read source from file
|
|
@@ -236,12 +288,74 @@ module.exports = {
|
|
|
236
288
|
}
|
|
237
289
|
}
|
|
238
290
|
|
|
291
|
+
// Helper: read FIXPT from SAPL XML for a function group
|
|
292
|
+
function readFugrFixpt(dir, groupName) {
|
|
293
|
+
const xmlFile = pathModule.join(dir, `${groupName.toLowerCase()}.fugr.sapl${groupName.toLowerCase()}.xml`);
|
|
294
|
+
if (fs.existsSync(xmlFile)) {
|
|
295
|
+
const xmlContent = fs.readFileSync(xmlFile, 'utf8');
|
|
296
|
+
const fixptMatch = xmlContent.match(/<FIXPT>([^<]+)<\/FIXPT>/);
|
|
297
|
+
if (fixptMatch && fixptMatch[1] === 'X') return 'X';
|
|
298
|
+
}
|
|
299
|
+
return '';
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Helper: classify a FUGR include filename — returns fm name (uppercase) or null if not an FM file
|
|
303
|
+
function getFugrFmName(includeFile, groupLower) {
|
|
304
|
+
if (!includeFile) return null;
|
|
305
|
+
const isTopInclude = new RegExp(`^l${groupLower}top$`, 'i').test(includeFile);
|
|
306
|
+
const isUInclude = new RegExp(`^l${groupLower}u\\d+$`, 'i').test(includeFile);
|
|
307
|
+
const isSapl = includeFile.toLowerCase().startsWith('sapl');
|
|
308
|
+
if (isTopInclude || isUInclude || isSapl) return null;
|
|
309
|
+
return includeFile.toUpperCase();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Auto-detect all FM files for each function group and build objects
|
|
313
|
+
for (const [groupName, groupData] of fugrGroupMap) {
|
|
314
|
+
const { dir } = groupData;
|
|
315
|
+
const groupLower = groupName.toLowerCase();
|
|
316
|
+
const prefix = `${groupLower}.fugr.`;
|
|
317
|
+
|
|
318
|
+
// Scan directory for all FUGR files belonging to this group
|
|
319
|
+
let allFiles;
|
|
320
|
+
try {
|
|
321
|
+
allFiles = fs.readdirSync(dir);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
allFiles = [];
|
|
324
|
+
}
|
|
325
|
+
for (const f of allFiles) {
|
|
326
|
+
if (!f.toLowerCase().startsWith(prefix) || !f.toLowerCase().endsWith('.abap')) continue;
|
|
327
|
+
const parts = f.split('.');
|
|
328
|
+
const includeFile = parts[2] || '';
|
|
329
|
+
const fmName = getFugrFmName(includeFile, groupLower);
|
|
330
|
+
if (fmName && !groupData.fmFiles.has(fmName)) {
|
|
331
|
+
groupData.fmFiles.set(fmName, fs.readFileSync(pathModule.join(dir, f), 'utf8'));
|
|
332
|
+
if (!jsonOutput) console.log(` Auto-detected: ${f}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (groupData.fmFiles.size === 0) {
|
|
337
|
+
if (!jsonOutput) console.error(` Warning: No FM source files found for FUGR ${groupName}`);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const fixpt = readFugrFixpt(dir, groupName);
|
|
342
|
+
|
|
343
|
+
// Add one object per FM
|
|
344
|
+
for (const [fmName, source] of groupData.fmFiles) {
|
|
345
|
+
objects.push({
|
|
346
|
+
type: 'FUGR',
|
|
347
|
+
name: groupName,
|
|
348
|
+
source: source,
|
|
349
|
+
fugr_include_name: fmName,
|
|
350
|
+
fixpt: fixpt
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
239
355
|
if (objects.length === 0) {
|
|
240
356
|
console.error(' No valid files to check');
|
|
241
357
|
process.exit(1);
|
|
242
358
|
}
|
|
243
|
-
|
|
244
|
-
// Send request
|
|
245
359
|
const data = {
|
|
246
360
|
objects: objects,
|
|
247
361
|
uccheck: cloudMode ? '5' : 'X'
|
|
@@ -258,7 +372,8 @@ module.exports = {
|
|
|
258
372
|
console.log(JSON.stringify(result, null, 2));
|
|
259
373
|
} else {
|
|
260
374
|
// Display results for each object
|
|
261
|
-
for (
|
|
375
|
+
for (let i = 0; i < results.length; i++) {
|
|
376
|
+
const res = results[i];
|
|
262
377
|
const objSuccess = res.SUCCESS !== undefined ? res.SUCCESS : res.success;
|
|
263
378
|
const objType = res.OBJECT_TYPE || res.object_type || 'UNKNOWN';
|
|
264
379
|
const objName = res.OBJECT_NAME || res.object_name || 'UNKNOWN';
|
|
@@ -267,13 +382,18 @@ module.exports = {
|
|
|
267
382
|
const warnings = res.WARNINGS || res.warnings || [];
|
|
268
383
|
const objMessage = res.MESSAGE || res.message || '';
|
|
269
384
|
|
|
385
|
+
// For FUGR: show which FM was checked alongside the group name
|
|
386
|
+
const sentObj = objects[i] || {};
|
|
387
|
+
const fugrFmLabel = (objType === 'FUGR' && sentObj.fugr_include_name)
|
|
388
|
+
? ` (${sentObj.fugr_include_name})` : '';
|
|
389
|
+
|
|
270
390
|
if (objSuccess) {
|
|
271
|
-
console.log(`✅ ${objType} ${objName} - Syntax check passed`);
|
|
391
|
+
console.log(`✅ ${objType} ${objName}${fugrFmLabel} - Syntax check passed`);
|
|
272
392
|
if (warnings.length > 0) {
|
|
273
393
|
console.log(` (${warnings.length} warning(s))`);
|
|
274
394
|
}
|
|
275
395
|
} else {
|
|
276
|
-
console.log(`❌ ${objType} ${objName} - Syntax check failed (${errorCount} error(s))`);
|
|
396
|
+
console.log(`❌ ${objType} ${objName}${fugrFmLabel} - Syntax check failed (${errorCount} error(s))`);
|
|
277
397
|
console.log('');
|
|
278
398
|
console.log('Errors:');
|
|
279
399
|
console.log('─'.repeat(60));
|
|
@@ -287,19 +407,25 @@ module.exports = {
|
|
|
287
407
|
|
|
288
408
|
// Display which file/include the error is in
|
|
289
409
|
if (include) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
'testclasses': { display: 'Test classes', suffix: '.clas.testclasses.abap' }
|
|
295
|
-
};
|
|
296
|
-
const includeInfo = includeMap[include] || { display: include, suffix: '' };
|
|
297
|
-
|
|
298
|
-
// Show both display name and filename
|
|
299
|
-
if (includeInfo.suffix) {
|
|
300
|
-
console.log(` In: ${includeInfo.display} (${objName.toLowerCase()}${includeInfo.suffix})`);
|
|
410
|
+
// For FUGR: include = lowercase FM name → display as '<group>.fugr.<fm_name>.abap'
|
|
411
|
+
if (objType === 'FUGR') {
|
|
412
|
+
const fugrFile = `${objName.toLowerCase()}.fugr.${include}.abap`;
|
|
413
|
+
console.log(` In: Function module ${include.toUpperCase()} (${fugrFile})`);
|
|
301
414
|
} else {
|
|
302
|
-
|
|
415
|
+
const includeMap = {
|
|
416
|
+
'main': { display: 'Main class', suffix: '.clas.abap' },
|
|
417
|
+
'locals_def': { display: 'Local definitions', suffix: '.clas.locals_def.abap' },
|
|
418
|
+
'locals_imp': { display: 'Local implementations', suffix: '.clas.locals_imp.abap' },
|
|
419
|
+
'testclasses': { display: 'Test classes', suffix: '.clas.testclasses.abap' }
|
|
420
|
+
};
|
|
421
|
+
const includeInfo = includeMap[include] || { display: include, suffix: '' };
|
|
422
|
+
|
|
423
|
+
// Show both display name and filename
|
|
424
|
+
if (includeInfo.suffix) {
|
|
425
|
+
console.log(` In: ${includeInfo.display} (${objName.toLowerCase()}${includeInfo.suffix})`);
|
|
426
|
+
} else {
|
|
427
|
+
console.log(` In: ${includeInfo.display}`);
|
|
428
|
+
}
|
|
303
429
|
}
|
|
304
430
|
}
|
|
305
431
|
if (methodName) {
|
package/src/commands/tree.js
CHANGED
|
@@ -148,6 +148,28 @@ module.exports = {
|
|
|
148
148
|
async execute(args, context) {
|
|
149
149
|
const { loadConfig, AbapHttp } = context;
|
|
150
150
|
|
|
151
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
152
|
+
console.log(`
|
|
153
|
+
Usage:
|
|
154
|
+
abapgit-agent tree --package <package> [--depth <n>] [--include-types] [--json]
|
|
155
|
+
|
|
156
|
+
Description:
|
|
157
|
+
Display the package hierarchy tree from the ABAP system.
|
|
158
|
+
|
|
159
|
+
Parameters:
|
|
160
|
+
--package <package> Root package to display (required). Enclose $-packages in quotes.
|
|
161
|
+
--depth <n> Maximum depth to traverse (default: unlimited).
|
|
162
|
+
--include-types Show object type counts per package.
|
|
163
|
+
--json Output as JSON.
|
|
164
|
+
|
|
165
|
+
Examples:
|
|
166
|
+
abapgit-agent tree --package ZMY_PACKAGE
|
|
167
|
+
abapgit-agent tree --package '$MY_LOCAL_PKG'
|
|
168
|
+
abapgit-agent tree --package ZMY_PACKAGE --depth 2 --include-types
|
|
169
|
+
`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
151
173
|
const packageArgIndex = args.indexOf('--package');
|
|
152
174
|
if (packageArgIndex === -1) {
|
|
153
175
|
console.error('Error: --package parameter required');
|
package/src/commands/unit.js
CHANGED
|
@@ -232,6 +232,29 @@ module.exports = {
|
|
|
232
232
|
async execute(args, context) {
|
|
233
233
|
const { loadConfig, AbapHttp } = context;
|
|
234
234
|
|
|
235
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
236
|
+
console.log(`
|
|
237
|
+
Usage:
|
|
238
|
+
abapgit-agent unit --files <file1>,<file2>,... [--coverage] [--junit-output <file>] [--json]
|
|
239
|
+
|
|
240
|
+
Description:
|
|
241
|
+
Run AUnit tests for ABAP test class files (.testclasses.abap).
|
|
242
|
+
Objects must be already active in the ABAP system (run pull first).
|
|
243
|
+
|
|
244
|
+
Parameters:
|
|
245
|
+
--files <file1,...> Comma-separated .testclasses.abap files (required).
|
|
246
|
+
--coverage Include code coverage data in output.
|
|
247
|
+
--junit-output <file> Write results as JUnit XML to this file.
|
|
248
|
+
--json Output as JSON.
|
|
249
|
+
|
|
250
|
+
Examples:
|
|
251
|
+
abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap
|
|
252
|
+
abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap --coverage
|
|
253
|
+
abapgit-agent unit --files src/zcl_my_test.clas.testclasses.abap --junit-output reports/unit.xml
|
|
254
|
+
`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
235
258
|
const jsonOutput = args.includes('--json');
|
|
236
259
|
const verbose = args.includes('--verbose');
|
|
237
260
|
const filesArgIndex = args.indexOf('--files');
|
package/src/commands/upgrade.js
CHANGED
|
@@ -14,6 +14,34 @@ module.exports = {
|
|
|
14
14
|
async execute(args, context) {
|
|
15
15
|
const { versionCheck, loadConfig, isAbapIntegrationEnabled } = context;
|
|
16
16
|
|
|
17
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
18
|
+
console.log(`
|
|
19
|
+
Usage:
|
|
20
|
+
abapgit-agent upgrade [--abap-only] [--cli-only] [--version <v>] [--check] [--yes]
|
|
21
|
+
|
|
22
|
+
Description:
|
|
23
|
+
Upgrade the abapgit-agent CLI (npm package) and/or the ABAP backend to the latest
|
|
24
|
+
or a specific version.
|
|
25
|
+
|
|
26
|
+
Parameters:
|
|
27
|
+
--abap-only Upgrade only the ABAP backend (skip CLI npm upgrade).
|
|
28
|
+
--cli-only Upgrade only the CLI npm package (skip ABAP backend).
|
|
29
|
+
--version <v> Upgrade to a specific version (e.g. 1.15.0).
|
|
30
|
+
--check Check for available upgrades without installing.
|
|
31
|
+
--transport <T> Transport request for ABAP backend upgrade.
|
|
32
|
+
--yes, -y Skip confirmation prompt.
|
|
33
|
+
--dry-run Show what would be done without making changes.
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
abapgit-agent upgrade
|
|
37
|
+
abapgit-agent upgrade --check
|
|
38
|
+
abapgit-agent upgrade --cli-only
|
|
39
|
+
abapgit-agent upgrade --abap-only --transport DEVK900001
|
|
40
|
+
abapgit-agent upgrade --version 1.15.0
|
|
41
|
+
`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
17
45
|
// Parse flags
|
|
18
46
|
const flags = this.parseFlags(args);
|
|
19
47
|
|
package/src/commands/view.js
CHANGED
|
@@ -193,6 +193,35 @@ module.exports = {
|
|
|
193
193
|
async execute(args, context) {
|
|
194
194
|
const { loadConfig, AbapHttp } = context;
|
|
195
195
|
|
|
196
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
197
|
+
console.log(`
|
|
198
|
+
Usage:
|
|
199
|
+
abapgit-agent view --objects <obj1>,<obj2>,... [--type <type>] [--full] [--lines] [--json]
|
|
200
|
+
abapgit-agent view --objects <FUGR> --type FUGR [--full] [--fm <name>] [--lines]
|
|
201
|
+
|
|
202
|
+
Description:
|
|
203
|
+
View ABAP object definitions from the ABAP system.
|
|
204
|
+
|
|
205
|
+
Parameters:
|
|
206
|
+
--objects <obj1,...> Comma-separated object names (required).
|
|
207
|
+
--type <type> Object type: CLAS, INTF, PROG, TABL, STRU, DTEL, TTYP, DOMA,
|
|
208
|
+
DDLS, DCLS, MSAG, FUGR (auto-detected from TADIR if omitted).
|
|
209
|
+
--full Show full source including all method implementations.
|
|
210
|
+
--lines Show dual line numbers (G = global for debug set, [N] = include-local).
|
|
211
|
+
--fm <name> With --full: show only the specified function module (FUGR only).
|
|
212
|
+
--json Output as JSON.
|
|
213
|
+
|
|
214
|
+
Examples:
|
|
215
|
+
abapgit-agent view --objects ZCL_MY_CLASS
|
|
216
|
+
abapgit-agent view --objects ZCL_MY_CLASS --full
|
|
217
|
+
abapgit-agent view --objects ZCL_MY_CLASS --full --lines
|
|
218
|
+
abapgit-agent view --objects ZMY_TABLE --type TABL
|
|
219
|
+
abapgit-agent view --objects SUSR --type FUGR --full --fm AUTHORITY_CHECK --lines
|
|
220
|
+
abapgit-agent view --objects ZCL_FOO,ZIF_BAR
|
|
221
|
+
`);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
196
225
|
const objectsArgIndex = args.indexOf('--objects');
|
|
197
226
|
if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
|
|
198
227
|
console.error('Error: --objects parameter required');
|