abapgit-agent 1.4.0 → 1.5.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.
@@ -14,6 +14,8 @@ jobs:
14
14
  steps:
15
15
  - name: Checkout code
16
16
  uses: actions/checkout@v4
17
+ with:
18
+ fetch-depth: 0
17
19
 
18
20
  - name: Setup Node.js
19
21
  uses: actions/setup-node@v4
@@ -39,6 +41,7 @@ jobs:
39
41
  - name: Prepare release notes
40
42
  id: release_notes
41
43
  run: |
44
+ # Read release notes from file (generated by npm run release)
42
45
  if [ -f "RELEASE_NOTES.md" ]; then
43
46
  # Extract only the current release (first section until --- separator)
44
47
  content=$(awk '/^---$/{exit}1' RELEASE_NOTES.md)
@@ -46,7 +49,7 @@ jobs:
46
49
  echo "$content" >> $GITHUB_OUTPUT
47
50
  echo "EOF" >> $GITHUB_OUTPUT
48
51
  else
49
- echo "CONTENT=No release notes" >> $GITHUB_OUTPUT
52
+ echo "CONTENT=Release ${{ steps.get_tag.outputs.VERSION }}" >> $GITHUB_OUTPUT
50
53
  fi
51
54
 
52
55
  - name: Create GitHub Release
package/CLAUDE.md CHANGED
@@ -127,6 +127,7 @@ abapgit-agent health
127
127
  # Check configuration
128
128
  abapgit-agent status
129
129
  ```
130
+ Note: All ABAP commands automatically check CLI/ABAP API version compatibility.
130
131
 
131
132
  ## Pull Command
132
133
 
@@ -237,8 +238,21 @@ abapgit-agent inspect --files abap/zc_my_view.ddls.asddls
237
238
 
238
239
  # Inspect mixed file types (DDLS + CLAS)
239
240
  abapgit-agent inspect --files abap/zc_my_view.ddls.asddls,abap/zcl_my_class.clas.abap
241
+
242
+ # Inspect with specific Code Inspector variant
243
+ abapgit-agent inspect --files abap/zcl_my_class.clas.abap --variant ALL_CHECKS
244
+
245
+ # Inspect with no variant (uses default SAP standard checks)
246
+ abapgit-agent inspect --files abap/zcl_my_class.clas.abap --variant EMPTY
240
247
  ```
241
248
 
249
+ ### Parameters
250
+
251
+ | Parameter | Required | Description |
252
+ |-----------|----------|-------------|
253
+ | `--files` | Yes | Comma-separated list of ABAP files to inspect |
254
+ | `--variant` | No | Code Inspector variant name (e.g., `ALL_CHECKS`, `EMPTY`) |
255
+
242
256
  ### Supported Object Types
243
257
 
244
258
  | Type | Description | Validation Method |
@@ -809,6 +823,7 @@ Create `.abapGitAgent` in repository root:
809
823
  | `language` | SAP language | EN |
810
824
  | `gitUsername` | Git username/token | Optional |
811
825
  | `gitPassword` | Git password/token | Optional |
826
+ | `transport` | Default transport request for pull | Optional |
812
827
 
813
828
  ### Environment Variables
814
829
  ```bash
@@ -820,8 +835,20 @@ export ABAP_PASSWORD="your-password"
820
835
  export ABAP_LANGUAGE="EN"
821
836
  export GIT_USERNAME="git-username"
822
837
  export GIT_PASSWORD="git-token"
838
+ export ABAP_TRANSPORT="DEVK900001"
823
839
  ```
824
840
 
841
+ ### Transport Request Precedence
842
+
843
+ When running `pull` command, the transport request is determined in this order:
844
+
845
+ | Priority | Source | Example |
846
+ |----------|--------|---------|
847
+ | 1 | CLI `--transport` argument | `--transport DEVK900001` |
848
+ | 2 | Config file `transport` | `"transport": "DEVK900001"` |
849
+ | 3 | Environment variable `ABAP_TRANSPORT` | `export ABAP_TRANSPORT="DEVK900001"` |
850
+ | 4 (default) | Not set | abapGit creates/uses default |
851
+
825
852
  ## Troubleshooting
826
853
 
827
854
  **Pull fails with "Error updating where-used list":**
package/README.md CHANGED
@@ -124,6 +124,7 @@ abapgit-agent health
124
124
  # Check integration status
125
125
  abapgit-agent status
126
126
  ```
127
+ Note: All ABAP commands automatically check CLI/ABAP API version compatibility.
127
128
 
128
129
  ## Local Development
129
130
 
package/abap/CLAUDE.md CHANGED
@@ -788,6 +788,118 @@ ENDCLASS.
788
788
  - Syntax errors in one command don't affect others
789
789
  - Add new commands by updating the mapping table
790
790
 
791
+ ## Exception Handling in ABAP
792
+
793
+ ABAP has two different ways to handle exceptions. Understanding the difference is critical.
794
+
795
+ ### Classical ABAP Exceptions (EXCEPTIONS)
796
+
797
+ Used in older function modules and some OO classes. Defined in method signature using `EXCEPTIONS` keyword.
798
+
799
+ **Method Definition:**
800
+ ```abap
801
+ METHODS method_name
802
+ IMPORTING iv_param TYPE string
803
+ EXCEPTIONS
804
+ exc1 = 1
805
+ exc2 = 2
806
+ OTHERS = 3.
807
+ ```
808
+
809
+ **Method Call:**
810
+ ```abap
811
+ method_name(
812
+ EXPORTING iv_param = lv_value
813
+ EXCEPTIONS
814
+ exc1 = 1
815
+ exc2 = 2
816
+ OTHERS = 3 ).
817
+
818
+ IF sy-subrc <> 0.
819
+ " Handle error - check sy-subrc for exception number
820
+ ENDIF.
821
+ ```
822
+
823
+ **Characteristics:**
824
+ - Return code in `sy-subrc`
825
+ - No exception objects
826
+ - Legacy approach
827
+
828
+ ### Modern ABAP Exceptions (TRY-CATCH)
829
+
830
+ Used in modern OO ABAP (7.40+). Uses exception classes and RAISING clause.
831
+
832
+ **Exception Class:**
833
+ ```abap
834
+ CLASS cx_my_exception DEFINITION INHERITING FROM cx_dynamic_check.
835
+ PUBLIC SECTION.
836
+ METHODS constructor IMPORTING textid LIKE textid OPTIONAL.
837
+ ENDCLASS.
838
+ ```
839
+
840
+ **Method Definition:**
841
+ ```abap
842
+ METHODS method_name
843
+ IMPORTING iv_param TYPE string
844
+ RAISING cx_my_exception.
845
+ ```
846
+
847
+ **Method Call:**
848
+ ```abap
849
+ TRY.
850
+ method_name( iv_param = lv_value ).
851
+ CATCH cx_my_exception INTO lx_error.
852
+ lv_message = lx_error->get_text( ).
853
+ ENDTRY.
854
+ ```
855
+
856
+ ### How to Identify Which to Use
857
+
858
+ Look at the method signature:
859
+
860
+ | Syntax | Type |
861
+ |--------|------|
862
+ | `EXCEPTIONS exc1 = 1` | Classical |
863
+ | `RAISING cx_exception` | Modern (TRY-CATCH) |
864
+
865
+ ### Real Example: cl_ci_checkvariant=>get_ref
866
+
867
+ This method uses **classical exceptions**:
868
+
869
+ ```abap
870
+ " WRONG - using TRY-CATCH
871
+ TRY.
872
+ lo_variant = cl_ci_checkvariant=>get_ref(
873
+ p_user = ''
874
+ p_name = lv_variant ).
875
+ CATCH cx_root.
876
+ " This won't work!
877
+ ENDTRY.
878
+
879
+ " CORRECT - using EXCEPTIONS with EXPORTING and RECEIVING
880
+ cl_ci_checkvariant=>get_ref(
881
+ EXPORTING
882
+ p_user = ''
883
+ p_name = lv_variant
884
+ RECEIVING
885
+ p_ref = lo_variant
886
+ EXCEPTIONS
887
+ chkv_not_exists = 1
888
+ missing_parameter = 2
889
+ broken_variant = 3
890
+ OTHERS = 4 ).
891
+
892
+ IF sy-subrc <> 0.
893
+ " Handle error
894
+ ENDIF.
895
+ ```
896
+
897
+ **Key Points:**
898
+ 1. Use `EXPORTING` before importing parameters when using `EXCEPTIONS`
899
+ 2. Use `RECEIVING` for RETURNING parameters (not direct assignment)
900
+ 3. Check `sy-subrc` for exception codes
901
+ 4. Not all OO methods use TRY-CATCH - some still use classical exceptions
902
+
791
903
  ## Best Practices
792
904
 
793
905
  ### Always Return Interface Types, Not Class Types
@@ -44,6 +44,7 @@ CLASS zcl_abgagt_command_inspect DEFINITION PUBLIC FINAL CREATE PUBLIC.
44
44
 
45
45
  TYPES: BEGIN OF ty_inspect_params,
46
46
  files TYPE string_table,
47
+ variant TYPE string,
47
48
  END OF ty_inspect_params.
48
49
 
49
50
  TYPES ty_object_keys TYPE TABLE OF scir_objs WITH NON-UNIQUE DEFAULT KEY.
@@ -53,6 +54,7 @@ CLASS zcl_abgagt_command_inspect DEFINITION PUBLIC FINAL CREATE PUBLIC.
53
54
 
54
55
  METHODS run_syntax_check
55
56
  IMPORTING it_objects TYPE ty_object_keys
57
+ iv_variant TYPE string DEFAULT 'SYNTAX_CHECK'
56
58
  RETURNING VALUE(rt_results) TYPE ty_inspect_results.
57
59
 
58
60
  " Validate DDLS (CDS views)
@@ -120,7 +122,9 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
120
122
 
121
123
  " Run syntax check for non-DDLS objects
122
124
  IF lt_objects IS NOT INITIAL.
123
- DATA(lt_sci_results) = run_syntax_check( lt_objects ).
125
+ DATA(lt_sci_results) = run_syntax_check(
126
+ it_objects = lt_objects
127
+ iv_variant = ls_params-variant ).
124
128
  INSERT LINES OF lt_sci_results INTO TABLE lt_results.
125
129
  ENDIF.
126
130
 
@@ -300,6 +304,7 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
300
304
  lo_inspection TYPE REF TO cl_ci_inspection,
301
305
  lt_list TYPE scit_alvlist,
302
306
  ls_error TYPE ty_error,
307
+ ls_warning TYPE ty_warning,
303
308
  ls_list TYPE scir_alvlist,
304
309
  lx_error TYPE REF TO cx_root,
305
310
  ls_result TYPE ty_inspect_result.
@@ -315,10 +320,36 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
315
320
  p_name = lv_name
316
321
  p_objects = it_objects ).
317
322
 
318
- " Get check variant for syntax check
319
- lo_variant = cl_ci_checkvariant=>get_ref(
320
- p_user = ''
321
- p_name = 'SYNTAX_CHECK' ).
323
+ " Get check variant (default: SYNTAX_CHECK)
324
+ DATA lv_variant TYPE sci_chkv.
325
+ lv_variant = iv_variant.
326
+ IF lv_variant IS INITIAL.
327
+ lv_variant = 'SYNTAX_CHECK'.
328
+ ENDIF.
329
+
330
+ " Try to get the variant using EXCEPTIONS
331
+ cl_ci_checkvariant=>get_ref(
332
+ EXPORTING
333
+ p_user = ''
334
+ p_name = lv_variant
335
+ RECEIVING
336
+ p_ref = lo_variant
337
+ EXCEPTIONS
338
+ chkv_not_exists = 1
339
+ missing_parameter = 2
340
+ broken_variant = 3
341
+ OTHERS = 4 ).
342
+
343
+ IF sy-subrc <> 0.
344
+ " Variant not found, return error
345
+ ls_result-object_type = 'VARIANT'.
346
+ ls_result-object_name = lv_variant.
347
+ ls_result-success = abap_false.
348
+ ls_result-error_count = 1.
349
+ APPEND VALUE #( line = '0' column = '0' text = |Check variant "{ lv_variant }" not found (rc={ sy-subrc })| word = '' ) TO ls_result-errors.
350
+ APPEND ls_result TO rt_results.
351
+ RETURN.
352
+ ENDIF.
322
353
 
323
354
  " Create inspection
324
355
  cl_ci_inspection=>create(
@@ -355,14 +386,28 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
355
386
  ls_result-object_name = ls_obj-objname.
356
387
  ls_result-success = abap_true.
357
388
 
358
- " Get errors for this object
389
+ " Get errors and warnings for this object
359
390
  LOOP AT lt_list INTO ls_list WHERE objname = ls_obj-objname.
360
- CLEAR ls_error.
361
- ls_error-line = ls_list-line.
362
- ls_error-column = ls_list-col.
363
- ls_error-text = ls_list-text.
364
- ls_error-word = ls_list-code.
365
- APPEND ls_error TO ls_result-errors.
391
+ " Check severity - 'E' = Error, 'W' = Warning, 'I' = Info
392
+ IF ls_list-kind = 'E'.
393
+ " Error
394
+ CLEAR ls_error.
395
+ ls_error-line = ls_list-line.
396
+ ls_error-column = ls_list-col.
397
+ ls_error-text = ls_list-text.
398
+ ls_error-word = ls_list-code.
399
+ APPEND ls_error TO ls_result-errors.
400
+ ELSEIF ls_list-kind = 'W' OR ls_list-kind = 'I'.
401
+ " Warning or Info
402
+ CLEAR ls_warning.
403
+ ls_warning-line = ls_list-line.
404
+ ls_warning-column = ls_list-col.
405
+ ls_warning-severity = ls_list-kind.
406
+ ls_warning-message = ls_list-text.
407
+ ls_warning-object_type = ls_obj-objtype.
408
+ ls_warning-object_name = ls_obj-objname.
409
+ APPEND ls_warning TO ls_result-warnings.
410
+ ENDIF.
366
411
  ENDLOOP.
367
412
 
368
413
  ls_result-error_count = lines( ls_result-errors ).
@@ -14,7 +14,7 @@ CLASS zcl_abgagt_resource_health IMPLEMENTATION.
14
14
 
15
15
  METHOD if_rest_resource~get.
16
16
  DATA lv_json TYPE string.
17
- lv_json = '{"status":"OK","version":"1.0.0"}'.
17
+ lv_json = '{"status":"OK","version":"1.4.0"}'.
18
18
 
19
19
  DATA(lo_entity) = mo_response->create_entity( ).
20
20
  lo_entity->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json ).
@@ -19,6 +19,7 @@ CLASS zcl_abgagt_resource_inspect IMPLEMENTATION.
19
19
  " Parse JSON using /ui2/cl_json
20
20
  DATA: BEGIN OF ls_request,
21
21
  files TYPE string_table,
22
+ variant TYPE string,
22
23
  END OF ls_request.
23
24
 
24
25
  /ui2/cl_json=>deserialize(
package/bin/abapgit-agent CHANGED
@@ -23,6 +23,74 @@ const TERM_WIDTH = getTermWidth();
23
23
 
24
24
  const COOKIE_FILE = '.abapgit_agent_cookies.txt';
25
25
 
26
+ /**
27
+ * Get CLI version from package.json
28
+ */
29
+ function getCliVersion() {
30
+ const packageJsonPath = pathModule.join(__dirname, '..', 'package.json');
31
+ if (fs.existsSync(packageJsonPath)) {
32
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
33
+ return pkg.version || '1.0.0';
34
+ }
35
+ return '1.0.0';
36
+ }
37
+
38
+ /**
39
+ * Check version compatibility between CLI and ABAP API
40
+ */
41
+ async function checkVersionCompatibility() {
42
+ const cliVersion = getCliVersion();
43
+
44
+ try {
45
+ const config = loadConfig();
46
+ const https = require('https');
47
+ const url = new URL(`/sap/bc/z_abapgit_agent/health`, `https://${config.host}:${config.sapport}`);
48
+
49
+ return new Promise((resolve) => {
50
+ const options = {
51
+ hostname: url.hostname,
52
+ port: url.port,
53
+ path: url.pathname,
54
+ method: 'GET',
55
+ headers: {
56
+ 'Authorization': `Basic ${Buffer.from(`${config.user}:${config.password}`).toString('base64')}`,
57
+ 'sap-client': config.client,
58
+ 'sap-language': config.language || 'EN',
59
+ 'Content-Type': 'application/json'
60
+ },
61
+ agent: new https.Agent({ rejectUnauthorized: false })
62
+ };
63
+
64
+ const req = https.request(options, (res) => {
65
+ let body = '';
66
+ res.on('data', chunk => body += chunk);
67
+ res.on('end', () => {
68
+ try {
69
+ const result = JSON.parse(body);
70
+ const apiVersion = result.version || '1.0.0';
71
+
72
+ if (cliVersion !== apiVersion) {
73
+ console.log(`\n⚠️ Version mismatch: CLI ${cliVersion}, ABAP API ${apiVersion}`);
74
+ console.log(' Some commands may not work correctly.');
75
+ console.log(' Update ABAP code: abapgit-agent pull\n');
76
+ }
77
+ resolve({ cliVersion, apiVersion, compatible: cliVersion === apiVersion });
78
+ } catch (e) {
79
+ resolve({ cliVersion, apiVersion: null, compatible: false, error: e.message });
80
+ }
81
+ });
82
+ });
83
+
84
+ req.on('error', (e) => {
85
+ resolve({ cliVersion, apiVersion: null, compatible: false, error: e.message });
86
+ });
87
+ req.end();
88
+ });
89
+ } catch (error) {
90
+ return { cliVersion, apiVersion: null, compatible: false, error: error.message };
91
+ }
92
+ }
93
+
26
94
  /**
27
95
  * Load configuration from .abapGitAgent in current working directory
28
96
  */
@@ -42,10 +110,19 @@ function loadConfig() {
42
110
  password: process.env.ABAP_PASSWORD,
43
111
  language: process.env.ABAP_LANGUAGE || 'EN',
44
112
  gitUsername: process.env.GIT_USERNAME,
45
- gitPassword: process.env.GIT_PASSWORD
113
+ gitPassword: process.env.GIT_PASSWORD,
114
+ transport: process.env.ABAP_TRANSPORT
46
115
  };
47
116
  }
48
117
 
118
+ /**
119
+ * Get transport request from config or environment
120
+ */
121
+ function getTransport() {
122
+ const config = loadConfig();
123
+ return config.transport;
124
+ }
125
+
49
126
  /**
50
127
  * Check if ABAP integration is configured for this repo
51
128
  */
@@ -385,7 +462,7 @@ async function syntaxCheckSource(sourceFile, csrfToken, config) {
385
462
  /**
386
463
  * Inspect all files in one request
387
464
  */
388
- async function inspectAllFiles(files, csrfToken, config) {
465
+ async function inspectAllFiles(files, csrfToken, config, variant = null) {
389
466
  // Convert files to uppercase names (same as syntaxCheckSource does)
390
467
  const fileNames = files.map(f => {
391
468
  const baseName = pathModule.basename(f).toUpperCase();
@@ -398,6 +475,11 @@ async function inspectAllFiles(files, csrfToken, config) {
398
475
  files: fileNames
399
476
  };
400
477
 
478
+ // Add variant if specified
479
+ if (variant) {
480
+ data.variant = variant;
481
+ }
482
+
401
483
  const result = await request('POST', '/sap/bc/z_abapgit_agent/inspect', data, { csrfToken: csrfToken });
402
484
 
403
485
  // Handle both table result and old single result
@@ -1195,6 +1277,12 @@ To enable integration:
1195
1277
  }
1196
1278
  }
1197
1279
 
1280
+ // Version compatibility check for commands that interact with ABAP
1281
+ const abapCommands = ['create', 'import', 'pull', 'inspect', 'unit', 'tree', 'view', 'preview'];
1282
+ if (command && abapCommands.includes(command)) {
1283
+ await checkVersionCompatibility();
1284
+ }
1285
+
1198
1286
  try {
1199
1287
  switch (command) {
1200
1288
  case 'init':
@@ -1390,16 +1478,21 @@ Examples:
1390
1478
  let gitUrl = urlArgIndex !== -1 ? args[urlArgIndex + 1] : null;
1391
1479
  let branch = branchArgIndex !== -1 ? args[branchArgIndex + 1] : getGitBranch();
1392
1480
  let files = null;
1481
+
1482
+ // Transport: CLI arg takes priority, then config/environment, then null
1393
1483
  let transportRequest = null;
1484
+ if (transportArgIndex !== -1 && transportArgIndex + 1 < args.length) {
1485
+ // Explicit --transport argument
1486
+ transportRequest = args[transportArgIndex + 1];
1487
+ } else {
1488
+ // Fall back to config or environment variable
1489
+ transportRequest = getTransport();
1490
+ }
1394
1491
 
1395
1492
  if (filesArgIndex !== -1 && filesArgIndex + 1 < args.length) {
1396
1493
  files = args[filesArgIndex + 1].split(',').map(f => f.trim());
1397
1494
  }
1398
1495
 
1399
- if (transportArgIndex !== -1 && transportArgIndex + 1 < args.length) {
1400
- transportRequest = args[transportArgIndex + 1];
1401
- }
1402
-
1403
1496
  if (!gitUrl) {
1404
1497
  gitUrl = getGitRemoteUrl();
1405
1498
  if (!gitUrl) {
@@ -1427,31 +1520,32 @@ Examples:
1427
1520
  break;
1428
1521
 
1429
1522
  case 'inspect': {
1430
- // TODO: Implement full inspect feature with:
1431
- // - Syntax check (currently implemented via /inspect)
1432
- // - Code Inspector checks (SE51, SCI)
1433
- // - ATC checks (SATC)
1434
- // - Custom rule checks
1435
- // Add --check-type parameter to specify which check to run
1436
-
1437
1523
  const filesArgIndex = args.indexOf('--files');
1438
1524
  if (filesArgIndex === -1 || filesArgIndex + 1 >= args.length) {
1439
1525
  console.error('Error: --files parameter required');
1440
- console.error('Usage: abapgit-agent inspect --files <file1>,<file2>,...');
1526
+ console.error('Usage: abapgit-agent inspect --files <file1>,<file2>,... [--variant <check-variant>]');
1441
1527
  console.error('Example: abapgit-agent inspect --files zcl_my_class.clas.abap');
1528
+ console.error('Example: abapgit-agent inspect --files zcl_my_class.clas.abap --variant ALL_CHECKS');
1442
1529
  process.exit(1);
1443
1530
  }
1444
1531
 
1445
1532
  const filesSyntaxCheck = args[filesArgIndex + 1].split(',').map(f => f.trim());
1446
1533
 
1534
+ // Parse optional --variant parameter
1535
+ const variantArgIndex = args.indexOf('--variant');
1536
+ const variant = variantArgIndex !== -1 ? args[variantArgIndex + 1] : null;
1537
+
1447
1538
  console.log(`\n Inspect for ${filesSyntaxCheck.length} file(s)`);
1539
+ if (variant) {
1540
+ console.log(` Using variant: ${variant}`);
1541
+ }
1448
1542
  console.log('');
1449
1543
 
1450
1544
  const config = loadConfig();
1451
1545
  const csrfToken = await fetchCsrfToken(config);
1452
1546
 
1453
1547
  // Send all files in one request
1454
- const results = await inspectAllFiles(filesSyntaxCheck, csrfToken, config);
1548
+ const results = await inspectAllFiles(filesSyntaxCheck, csrfToken, config, variant);
1455
1549
 
1456
1550
  // Process results
1457
1551
  for (const result of results) {
@@ -1485,15 +1579,37 @@ Examples:
1485
1579
 
1486
1580
  case 'tree': {
1487
1581
  const packageArgIndex = args.indexOf('--package');
1488
- if (packageArgIndex === -1 || packageArgIndex + 1 >= args.length) {
1582
+ if (packageArgIndex === -1) {
1489
1583
  console.error('Error: --package parameter required');
1490
1584
  console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1491
- console.error('Example: abapgit-agent tree --package $ZMY_PACKAGE');
1585
+ console.error('Example: abapgit-agent tree --package ZMY_PACKAGE');
1586
+ process.exit(1);
1587
+ }
1588
+
1589
+ // Check if package value is missing (happens when shell variable expands to empty)
1590
+ if (packageArgIndex + 1 >= args.length) {
1591
+ console.error('Error: --package parameter value is missing');
1592
+ console.error('');
1593
+ console.error('Tip: If you are using a shell variable, make sure to quote it:');
1594
+ console.error(' abapgit-agent tree --package "$ZMY_PACKAGE"');
1595
+ console.error(' or escape the $ character:');
1596
+ console.error(' abapgit-agent tree --package \\$ZMY_PACKAGE');
1597
+ console.error('');
1598
+ console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1599
+ console.error('Example: abapgit-agent tree --package ZMY_PACKAGE');
1492
1600
  process.exit(1);
1493
1601
  }
1494
1602
 
1495
1603
  const packageName = args[packageArgIndex + 1];
1496
1604
 
1605
+ // Check for empty/whitespace-only package name
1606
+ if (!packageName || packageName.trim() === '') {
1607
+ console.error('Error: --package parameter cannot be empty');
1608
+ console.error('Usage: abapgit-agent tree --package <package> [--depth <n>] [--include-objects] [--json]');
1609
+ console.error('Example: abapgit-agent tree --package ZMY_PACKAGE');
1610
+ process.exit(1);
1611
+ }
1612
+
1497
1613
  // Optional depth parameter
1498
1614
  const depthArgIndex = args.indexOf('--depth');
1499
1615
  let depth = 3;
@@ -15,6 +15,12 @@ abapgit-agent inspect --files zcl_my_class.clas.abap,zcl_other.clas.abap
15
15
 
16
16
  # With path
17
17
  abapgit-agent inspect --files abap/zcl_my_class.clas.abap
18
+
19
+ # With Code Inspector variant
20
+ abapgit-agent inspect --files abap/zcl_my_class.clas.abap --variant ALL_CHECKS
21
+
22
+ # With no variant (uses default SAP standard checks)
23
+ abapgit-agent inspect --files abap/zcl_my_class.clas.abap --variant EMPTY
18
24
  ```
19
25
 
20
26
  ## Prerequisite
@@ -27,6 +33,7 @@ abapgit-agent inspect --files abap/zcl_my_class.clas.abap
27
33
  | Parameter | Required | Description |
28
34
  |-----------|----------|-------------|
29
35
  | `--files` | Yes | Comma-separated list of files to inspect |
36
+ | `--variant` | No | Code Inspector variant name (e.g., `ALL_CHECKS`, `EMPTY`) |
30
37
 
31
38
  ---
32
39
 
@@ -54,7 +61,8 @@ GET /health (with X-CSRF-Token: fetch)
54
61
  **Request Body:**
55
62
  ```json
56
63
  {
57
- "files": ["ZCL_MY_CLASS.CLASS.ABAP"]
64
+ "files": ["ZCL_MY_CLASS.CLASS.ABAP"],
65
+ "variant": "ALL_CHECKS"
58
66
  }
59
67
  ```
60
68
 
@@ -140,6 +148,9 @@ abapgit-agent inspect --files zcl_my_class.clas.abap
140
148
 
141
149
  # Multiple files
142
150
  abapgit-agent inspect --files abap/zcl_my_class.clas.abap,abap/zcl_other.clas.abap
151
+
152
+ # With Code Inspector variant
153
+ abapgit-agent inspect --files abap/zcl_my_class.clas.abap --variant ALL_CHECKS
143
154
  ```
144
155
 
145
156
  ## Use Case