abapgit-agent 1.7.0 → 1.7.2

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.
@@ -0,0 +1,11 @@
1
+ {
2
+ "host": "your-sap-system.com",
3
+ "sapport": 443,
4
+ "client": "100",
5
+ "user": "TECH_USER",
6
+ "password": "your-password",
7
+ "language": "EN",
8
+ "gitUsername": "github-username",
9
+ "gitPassword": "github-token",
10
+ "referenceFolder": "~/abap-reference"
11
+ }
package/README.md CHANGED
@@ -52,6 +52,9 @@ abapgit-agent init --folder /abap/ --package ZMY_PACKAGE
52
52
  # Create online repository in ABAP
53
53
  abapgit-agent create
54
54
 
55
+ # Delete online repository from ABAP (keeps local files)
56
+ abapgit-agent delete
57
+
55
58
  # Import objects from ABAP package to git
56
59
  abapgit-agent import
57
60
  ```
@@ -113,6 +116,11 @@ abapgit-agent preview --objects SFLIGHT --where "CARRID = 'AA'"
113
116
  abapgit-agent preview --objects SFLIGHT --columns CARRID,CONNID,PRICE
114
117
  abapgit-agent preview --objects SFLIGHT --vertical
115
118
  abapgit-agent preview --objects SFLIGHT --compact
119
+
120
+ # Find where-used (objects using a specific object)
121
+ abapgit-agent where --objects ZCL_MY_CLASS
122
+ abapgit-agent where --objects ZIF_MY_INTERFACE
123
+ abapgit-agent where --objects ZCL_MY_CLASS --type CLAS
116
124
  ```
117
125
 
118
126
  ### Utility Commands
@@ -147,6 +155,7 @@ npm run pull -- --url <git-url> --branch main
147
155
  | Installation & Setup | [INSTALL.md](INSTALL.md) |
148
156
  | init Command | [docs/init-command.md](docs/init-command.md) |
149
157
  | create Command | [docs/create-command.md](docs/create-command.md) |
158
+ | delete Command | [docs/delete-command.md](docs/delete-command.md) |
150
159
  | import Command | [docs/import-command.md](docs/import-command.md) |
151
160
  | pull Command | [docs/pull-command.md](docs/pull-command.md) |
152
161
  | inspect Command | [docs/inspect-command.md](docs/inspect-command.md) |
@@ -154,6 +163,7 @@ npm run pull -- --url <git-url> --branch main
154
163
  | tree Command | [docs/tree-command.md](docs/tree-command.md) |
155
164
  | view Command | [docs/view-command.md](docs/view-command.md) |
156
165
  | preview Command | [docs/preview-command.md](docs/preview-command.md) |
166
+ | where Command | [docs/where-command.md](docs/where-command.md) |
157
167
  | ref Command | [docs/ref-command.md](docs/ref-command.md) |
158
168
  | REST API Reference | [API.md](API.md) |
159
169
  | Error Handling | [ERROR_HANDLING.md](ERROR_HANDLING.md) |
@@ -0,0 +1,254 @@
1
+ # ABAP Development with abapGit
2
+
3
+ You are working on an ABAP project using abapGit for version control.
4
+
5
+ ---
6
+
7
+ ## Critical Rules
8
+
9
+ ### 1. Use `ref` Command for Unfamiliar Topics
10
+
11
+ **When starting to work on ANY unfamiliar ABAP topic, syntax, or pattern, you MUST use the `ref` command BEFORE writing any code.**
12
+
13
+ ```
14
+ ❌ WRONG: Start writing code immediately based on assumptions
15
+ ✅ CORRECT: Run ref command first to look up the correct pattern
16
+ ```
17
+
18
+ **Why**: ABAP syntax is strict. Guessing leads to activation errors that waste time.
19
+
20
+ | Scenario | Example |
21
+ |----------|---------|
22
+ | Implementing new ABAP feature | "How do I use FILTER operator?" |
23
+ | Unfamiliar pattern | "What's the correct VALUE #() syntax?" |
24
+ | SQL operations | "How to write a proper SELECT with JOIN?" |
25
+ | CDS views | "How to define CDS view with associations?" |
26
+ | Getting syntax errors | Check reference before trying approaches |
27
+
28
+ ```bash
29
+ # For CDS topics
30
+ abapgit-agent ref --topic cds
31
+ abapgit-agent ref "CDS view"
32
+ abapgit-agent ref "association"
33
+ ```
34
+
35
+ ```bash
36
+ # Search for a pattern
37
+ abapgit-agent ref "CORRESPONDING"
38
+ abapgit-agent ref "FILTER #"
39
+
40
+ # Browse by topic
41
+ abapgit-agent ref --topic exceptions
42
+ abapgit-agent ref --topic sql
43
+
44
+ # List all topics
45
+ abapgit-agent ref --list-topics
46
+ ```
47
+
48
+ ### 2. Read `.abapGitAgent` for Folder Location
49
+
50
+ **Before creating ANY ABAP object file, you MUST read `.abapGitAgent` to determine the correct folder.**
51
+
52
+ ```
53
+ ❌ WRONG: Assume files go in "abap/" folder
54
+ ✅ CORRECT: Read .abapGitAgent to get the "folder" property value
55
+ ```
56
+
57
+ The folder is configured in `.abapGitAgent` (property: `folder`):
58
+ - If `folder` is `/src/` → files go in `src/` (e.g., `src/zcl_my_class.clas.abap`)
59
+ - If `folder` is `/abap/` → files go in `abap/` (e.g., `abap/zcl_my_class.clas.abap`)
60
+
61
+ ### 3. Create XML Metadata for Each ABAP Object
62
+
63
+ **Each ABAP object requires an XML metadata file for abapGit to understand how to handle it.**
64
+
65
+ | Object Type | ABAP File (if folder=/src/) | XML File |
66
+ |-------------|------------------------------|----------|
67
+ | Class | `src/zcl_*.clas.abap` | `src/zcl_*.clas.xml` |
68
+ | Interface | `src/zif_*.intf.abap` | `src/zif_*.intf.xml` |
69
+ | Program | `src/z*.prog.abap` | `src/z*.prog.xml` |
70
+ | Table | `src/z*.tabl.abap` | `src/z*.tabl.xml` |
71
+ | CDS View | `src/zc_*.ddls.asddls` | `src/zc_*.ddls.xml` |
72
+
73
+ **Use `ref --topic abapgit` for complete XML templates.**
74
+
75
+ ### 4. Use `unit` Command for Unit Tests
76
+
77
+ **Use `abapgit-agent unit` to run ABAP unit tests (AUnit).**
78
+
79
+ ```
80
+ ❌ WRONG: Try to use SE24 or other transaction codes
81
+ ✅ CORRECT: Use abapgit-agent unit --files src/zcl_test.clas.testclasses.abap
82
+ ```
83
+
84
+ ```bash
85
+ # Run unit tests (after pulling to ABAP)
86
+ abapgit-agent unit --files src/zcl_test.clas.testclasses.abap
87
+ ```
88
+
89
+ ### 5. Use CDS Test Double Framework for CDS View Tests
90
+
91
+ **When creating unit tests for CDS views, use the CDS Test Double Framework (`CL_CDS_TEST_ENVIRONMENT`).**
92
+
93
+ ```
94
+ ❌ WRONG: Use regular AUnit test class without test doubles
95
+ ✅ CORRECT: Use CL_CDS_TEST_ENVIRONMENT to create test doubles for CDS views
96
+ ```
97
+
98
+ **Why**: CDS views read from database tables. Using test doubles allows:
99
+ - Injecting test data without affecting production data
100
+ - Testing specific scenarios that may not exist in production
101
+ - Fast, isolated tests that don't depend on database state
102
+
103
+ See `../guidelines/03_testing.md` for code examples.
104
+
105
+ ---
106
+
107
+ ## Development Workflow
108
+
109
+ ```
110
+ 1. Read .abapGitAgent → get folder value
111
+
112
+
113
+ 2. Research → use ref command for unfamiliar topics
114
+
115
+
116
+ 3. Write code → place in correct folder (e.g., src/zcl_*.clas.abap)
117
+
118
+
119
+ 4. Commit and push → git add . && git commit && git push
120
+
121
+
122
+ 5. Activate → abapgit-agent pull --files src/file.clas.abap
123
+
124
+
125
+ 6. Verify → Check pull output
126
+ - **Do NOT run inspect before commit/push/pull** - ABAP validates on pull
127
+ - **Do NOT run unit before pull** - Tests run against ABAP system, code must be activated first
128
+ - Objects NOT in "Activated Objects" but in "Failed Objects Log" → Syntax error (check inspect)
129
+ - Objects NOT appearing at all → XML metadata issue
130
+
131
+
132
+ 7. (Optional) Run unit tests → abapgit-agent unit --files src/zcl_test.clas.testclasses.abap (ONLY if test file exists, AFTER successful pull)
133
+
134
+
135
+ 8. If needed → Use inspect to check syntax (runs against ABAP system)
136
+ ```
137
+
138
+ **IMPORTANT**:
139
+ - **ALWAYS push to git BEFORE running pull** - abapGit reads from git
140
+ - **Use inspect AFTER pull** to check syntax on objects already in ABAP
141
+ - **Check pull output**:
142
+ - In "Failed Objects Log" → Syntax error (use inspect for details)
143
+ - Not appearing at all → XML metadata is wrong
144
+
145
+ **When to use inspect vs view**:
146
+ - **inspect**: Use when there are SYNTAX ERRORS (to find line numbers and details)
147
+ - **view**: Use when you need to understand an object STRUCTURE (table fields, class methods)
148
+ - Do NOT use view to debug syntax errors - view shows definitions, not errors
149
+
150
+ ### Commands
151
+
152
+ ```bash
153
+ # 1. Pull/activate after pushing to git (abapGit reads from git!)
154
+ abapgit-agent pull --files src/zcl_class1.clas.abap,src/zcl_class2.clas.abap
155
+
156
+ # 2. Inspect AFTER pull to check syntax (runs against ABAP system)
157
+ abapgit-agent inspect --files src/zcl_class1.clas.abap,src/zif_interface1.intf.abap
158
+
159
+ # Run unit tests (multiple test classes)
160
+ abapgit-agent unit --files src/zcl_test1.clas.testclasses.abap,src/zcl_test2.clas.testclasses.abap
161
+
162
+ # View object definitions (multiple objects)
163
+ abapgit-agent view --objects ZCL_CLASS1,ZCL_CLASS2,ZIF_INTERFACE
164
+
165
+ # Preview table data (multiple tables/views)
166
+ abapgit-agent preview --objects ZTABLE1,ZTABLE2
167
+
168
+ # Explore table structures
169
+ abapgit-agent view --objects ZTABLE --type TABL
170
+
171
+ # Display package tree
172
+ abapgit-agent tree --package \$MY_PACKAGE
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Explore Unknown Objects
178
+
179
+ **Before working with unfamiliar objects, use `view` command:**
180
+
181
+ ```bash
182
+ # Check table structure
183
+ abapgit-agent view --objects ZMY_TABLE --type TABL
184
+
185
+ # Check class definition
186
+ abapgit-agent view --objects ZCL_UNKNOWN_CLASS
187
+
188
+ # Check interface
189
+ abapgit-agent view --objects ZIF_UNKNOWN_INTERFACE
190
+
191
+ # Check data element
192
+ abapgit-agent view --objects ZMY_DTEL --type DTEL
193
+ ```
194
+
195
+ AI assistant SHOULD call `view` command when:
196
+ - User asks to "check", "look up", or "explore" an unfamiliar object
197
+ - Working with a table/structure and you don't know the fields
198
+ - Calling a class/interface method and you don't know the parameters
199
+
200
+ ---
201
+
202
+ ## Key ABAP Rules
203
+
204
+ 1. **Global classes MUST use `PUBLIC`**:
205
+ ```abap
206
+ CLASS zcl_my_class DEFINITION PUBLIC. " <- REQUIRED
207
+ ```
208
+
209
+ 2. **Use `/ui2/cl_json` for JSON**:
210
+ ```abap
211
+ DATA ls_data TYPE ty_request.
212
+ ls_data = /ui2/cl_json=>deserialize( json = lv_json ).
213
+ lv_json = /ui2/cl_json=>serialize( data = ls_response ).
214
+ ```
215
+
216
+ 3. **Test class name max 30 chars**: `ltcl_util` (not `ltcl_abgagt_util_test`)
217
+
218
+ 4. **Interface method implementation**: Use prefix `zif_interface~method_name`
219
+
220
+ ---
221
+
222
+ ## Error Handling
223
+
224
+ - **"Error updating where-used list"** → This is a **SYNTAX ERROR** (not a warning!)
225
+ - Use `abapgit-agent inspect --files <file>` for detailed error messages with line numbers
226
+
227
+ ---
228
+
229
+ ## Guidelines Index
230
+
231
+ Detailed guidelines are available in the `guidelines/` folder:
232
+
233
+ | File | Topic |
234
+ |------|-------|
235
+ | `../guidelines/01_sql.md` | ABAP SQL Best Practices |
236
+ | `../guidelines/02_exceptions.md` | Exception Handling |
237
+ | `../guidelines/03_testing.md` | Unit Testing (including CDS) |
238
+ | `../guidelines/04_cds.md` | CDS Views |
239
+ | `../guidelines/05_classes.md` | ABAP Classes and Objects |
240
+ | `../guidelines/06_objects.md` | Object Naming Conventions |
241
+ | `../guidelines/07_json.md` | JSON Handling |
242
+ | `../guidelines/08_abapgit.md` | abapGit XML Metadata Templates |
243
+
244
+ These guidelines are automatically searched by the `ref` command.
245
+
246
+ ---
247
+
248
+ ## Object Naming
249
+
250
+ | Pattern | Type |
251
+ |---------|------|
252
+ | `ZCL_*` | Class |
253
+ | `ZIF_*` | Interface |
254
+ | `Z*` | Other objects |
package/abap/CLAUDE.md ADDED
@@ -0,0 +1,313 @@
1
+ # ABAP Project Guidelines - Template
2
+
3
+ This file provides guidelines for **generating ABAP code** in abapGit repositories.
4
+
5
+ **Use this file as a template**: Copy it to your ABAP repository root when setting up new projects with Claude Code.
6
+
7
+ ---
8
+
9
+ ## Critical Rules
10
+
11
+ ### 1. Use `ref` Command for Unfamiliar Topics
12
+
13
+ **When starting to work on ANY unfamiliar ABAP topic, syntax, or pattern, you MUST use the `ref` command BEFORE writing any code.**
14
+
15
+ ```
16
+ ❌ WRONG: Start writing code immediately based on assumptions
17
+ ✅ CORRECT: Run ref command first to look up the correct pattern
18
+ ```
19
+
20
+ **Why**: ABAP syntax is strict. Guessing leads to activation errors that waste time.
21
+
22
+ | Scenario | Example |
23
+ |----------|---------|
24
+ | Implementing new ABAP feature | "How do I use FILTER operator?" |
25
+ | Unfamiliar pattern | "What's the correct VALUE #() syntax?" |
26
+ | SQL operations | "How to write a proper SELECT with JOIN?" |
27
+ | CDS views | "How to define CDS view with associations?" |
28
+ | Getting syntax errors | Check reference before trying approaches |
29
+
30
+ ```bash
31
+ # For CDS topics
32
+ abapgit-agent ref --topic cds
33
+ abapgit-agent ref "CDS view"
34
+ abapgit-agent ref "association"
35
+ ```
36
+
37
+ ```bash
38
+ # Search for a pattern
39
+ abapgit-agent ref "CORRESPONDING"
40
+ abapgit-agent ref "FILTER #"
41
+
42
+ # Browse by topic
43
+ abapgit-agent ref --topic exceptions
44
+ abapgit-agent ref --topic sql
45
+
46
+ # List all topics
47
+ abapgit-agent ref --list-topics
48
+ ```
49
+
50
+ ### 2. Read `.abapGitAgent` for Folder Location
51
+
52
+ **Before creating ANY ABAP object file, you MUST read `.abapGitAgent` to determine the correct folder.**
53
+
54
+ ```
55
+ ❌ WRONG: Assume files go in "abap/" folder
56
+ ✅ CORRECT: Read .abapGitAgent to get the "folder" property value
57
+ ```
58
+
59
+ The folder is configured in `.abapGitAgent` (property: `folder`):
60
+ - If `folder` is `/src/` → files go in `src/` (e.g., `src/zcl_my_class.clas.abap`)
61
+ - If `folder` is `/abap/` → files go in `abap/` (e.g., `abap/zcl_my_class.clas.abap`)
62
+
63
+ ---
64
+
65
+ ### 3. Create XML Metadata for Each ABAP Object
66
+
67
+ **Each ABAP object requires an XML metadata file for abapGit to understand how to handle it.**
68
+
69
+ | Object Type | ABAP File (if folder=/src/) | XML File |
70
+ |-------------|------------------------------|----------|
71
+ | Class | `src/zcl_*.clas.abap` | `src/zcl_*.clas.xml` |
72
+ | Interface | `src/zif_*.intf.abap` | `src/zif_*.intf.xml` |
73
+ | Program | `src/z*.prog.abap` | `src/z*.prog.xml` |
74
+ | Table | `src/z*.tabl.abap` | `src/z*.tabl.xml` |
75
+ | CDS View | `src/zc_*.ddls.asddls` | `src/zc_*.ddls.xml` |
76
+
77
+ **Use `ref --topic abapgit` for complete XML templates.**
78
+
79
+ ---
80
+
81
+ ### 4. NEVER Run Inspect Before Push/Pull (MOST IMPORTANT!)
82
+
83
+ ```
84
+ ❌ WRONG: Make changes → Run inspect → Check errors → Repeat
85
+ ✅ CORRECT: Make changes → Commit → Push → Run pull → Then inspect ONLY if pull fails
86
+ ```
87
+
88
+ **Why**: Inspect runs against the ABAP system, not git. The code must be in git and pulled to ABAP first.
89
+
90
+ ---
91
+
92
+ ### 5. Local Classes (Test Doubles, Helpers)
93
+
94
+ When a class needs local helper classes or test doubles, use separate files:
95
+
96
+ | File | Purpose |
97
+ |------|---------|
98
+ | `zcl_xxx.clas.locals_def.abap` | Local class definitions |
99
+ | `zcl_xxx.clas.locals_imp.abap` | Local class implementations |
100
+
101
+ **XML Configuration**: Add `<CLSCCINCL>X</CLSCCINCL>` to the class XML to include local class definitions:
102
+
103
+ ```xml
104
+ <VSEOCLASS>
105
+ <CLSNAME>ZCL_XXX</CLSNAME>
106
+ ...
107
+ <CLSCCINCL>X</CLSCCINCL>
108
+ </VSEOCLASS>
109
+ ```
110
+
111
+ ### 6. Use `ref`, `view` and `where` Commands to Learn About Unknown Classes/Methods
112
+
113
+ **When working with unfamiliar ABAP classes or methods, follow this priority:**
114
+
115
+ ```
116
+ 1. First: Check local git repo for usage examples
117
+ 2. Second: Check ABAP reference/cheat sheets
118
+ 3. Third: Use view/where commands to query ABAP system (if needed)
119
+ ```
120
+
121
+ #### Priority 1: Check Local Git Repository
122
+
123
+ **Look for usage examples in your local ABAP project first:**
124
+ - Search for class/interface names in your codebase
125
+ - Check how similar classes are implemented
126
+ - This gives the most relevant context for your project
127
+
128
+ #### Priority 2: Check ABAP References
129
+
130
+ ```bash
131
+ # Search in ABAP cheat sheets and guidelines
132
+ abapgit-agent ref "CLASS"
133
+ abapgit-agent ref "INTERFACE"
134
+ abapgit-agent ref --topic classes
135
+ ```
136
+
137
+ #### Priority 3: Use `where` and `view` Commands (Query ABAP System)
138
+
139
+ **If local/references don't have the answer, query the ABAP system:**
140
+
141
+ ```bash
142
+ # Find where a class/interface is USED (where command)
143
+ abapgit-agent where --objects ZIF_UNKNOWN_INTERFACE
144
+
145
+ # With pagination (default limit: 50, offset: 0)
146
+ abapgit-agent where --objects ZIF_UNKNOWN_INTERFACE --limit 20
147
+ abapgit-agent where --objects ZIF_UNKNOWN_INTERFACE --offset 50 --limit 20
148
+
149
+ # View CLASS DEFINITION (view command)
150
+ abapgit-agent view --objects ZCL_UNKNOWN_CLASS
151
+
152
+ # View specific METHOD implementation
153
+ abapgit-agent view --objects ZCL_UNKNOWN_CLASS=============CM001
154
+ ```
155
+
156
+ **Example workflow for AI:**
157
+ ```
158
+ User: "How do I use ZCL_ABGAGT_AGENT?"
159
+
160
+ AI thought process:
161
+ 1. Search local repo for ZCL_ABGAGT_AGENT usage
162
+ 2. Found: It's instantiated in several places with ->pull() method
163
+ 3. Still unclear about parameters? Check view command
164
+ 4. View: abapgit-agent view --objects ZCL_ABGAGT_AGENT
165
+ ```
166
+
167
+ **Key differences:**
168
+ - `where`: Shows WHERE an object is USED (references)
169
+ - `view`: Shows what an object DEFINES (structure, methods, source)
170
+
171
+ ---
172
+
173
+ ### 7. Use CDS Test Double Framework for CDS View Tests
174
+
175
+ **When creating unit tests for CDS views, use the CDS Test Double Framework (`CL_CDS_TEST_ENVIRONMENT`).**
176
+
177
+ ```
178
+ ❌ WRONG: Use regular AUnit test class without test doubles
179
+ ✅ CORRECT: Use CL_CDS_TEST_ENVIRONMENT to create test doubles for CDS views
180
+ ```
181
+
182
+ **Why**: CDS views read from database tables. Using test doubles allows:
183
+ - Injecting test data without affecting production data
184
+ - Testing specific scenarios that may not exist in production
185
+ - Fast, isolated tests that don't depend on database state
186
+
187
+ See `guidelines/03_testing.md` for code examples.
188
+
189
+ ---
190
+
191
+ ### 8. Use `unit` Command for Unit Tests
192
+
193
+ **Use `abapgit-agent unit` to run ABAP unit tests (AUnit).**
194
+
195
+ ```
196
+ ❌ WRONG: Try to use SE24, SE37, or other transaction codes
197
+ ✅ CORRECT: Use abapgit-agent unit --files src/zcl_test.clas.testclasses.abap
198
+ ```
199
+
200
+ ```bash
201
+ # Run unit tests (after pulling to ABAP)
202
+ abapgit-agent unit --files src/zcl_test.clas.testclasses.abap
203
+
204
+ # Multiple test classes
205
+ abapgit-agent unit --files src/zcl_test1.clas.testclasses.abap,src/zcl_test2.clas.testclasses.abap
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Development Workflow
211
+
212
+ ```
213
+ 1. Read .abapGitAgent → get folder value
214
+
215
+
216
+ 2. Research → use ref command for unfamiliar topics
217
+
218
+
219
+ 3. Write code → place in correct folder (e.g., src/zcl_*.clas.abap)
220
+
221
+
222
+ 4. Commit and push → git add . && git commit && git push
223
+
224
+
225
+ 5. Activate → abapgit-agent pull --files src/file.clas.abap
226
+
227
+
228
+ 6. Verify → Check pull output
229
+ - **Do NOT run inspect before commit/push/pull** - ABAP validates on pull
230
+ - **Do NOT run unit before pull** - Tests run against ABAP system, code must be activated first
231
+ - **"Error updating where-used list"** → This is a **SYNTAX ERROR** (check inspect for details)
232
+ - Objects NOT in "Activated Objects" but in "Failed Objects Log" → Syntax error (check inspect)
233
+ - Objects NOT appearing at all → XML metadata issue (check XML format in 08_abapgit.md)
234
+
235
+
236
+ 7. (Optional) Run unit tests → abapgit-agent unit --files src/zcl_test.clas.testclasses.abap (ONLY if test file exists, AFTER successful pull)
237
+
238
+
239
+ 8. If needed → Use inspect to check syntax (runs against ABAP system)
240
+ ```
241
+
242
+ **IMPORTANT**:
243
+ - **ALWAYS push to git BEFORE running pull** - abapGit reads from git
244
+ - **Use inspect AFTER pull** to check syntax on objects already in ABAP
245
+ - **Check pull output**:
246
+ - In "Failed Objects Log" → Syntax error (use inspect for details)
247
+ - Not appearing at all → XML metadata is wrong
248
+
249
+ **When to use inspect vs view**:
250
+ - **inspect**: Use when there are SYNTAX ERRORS (to find line numbers and details)
251
+ - **view**: Use when you need to understand an object STRUCTURE (table fields, class methods)
252
+ - Do NOT use view to debug syntax errors - view shows definitions, not errors
253
+
254
+ ### Commands
255
+
256
+ ```bash
257
+ # 1. Pull/activate after pushing to git (abapGit reads from git!)
258
+ abapgit-agent pull --files src/zcl_class1.clas.abap,src/zcl_class2.clas.abap
259
+
260
+ # 2. Inspect AFTER pull to check syntax (runs against ABAP system)
261
+ abapgit-agent inspect --files src/zcl_class1.clas.abap
262
+
263
+ # Run unit tests (multiple test classes)
264
+ abapgit-agent unit --files src/zcl_test1.clas.testclasses.abap,src/zcl_test2.clas.testclasses.abap
265
+
266
+ # View object definitions (multiple objects)
267
+ abapgit-agent view --objects ZCL_CLASS1,ZCL_CLASS2,ZIF_INTERFACE
268
+
269
+ # Preview table data (multiple tables/views)
270
+ abapgit-agent preview --objects ZTABLE1,ZTABLE2
271
+
272
+ # Explore table structures
273
+ abapgit-agent view --objects ZTABLE --type TABL
274
+
275
+ # Display package tree
276
+ abapgit-agent tree --package \$MY_PACKAGE
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Guidelines Index
282
+
283
+ Detailed guidelines are available in the `guidelines/` folder:
284
+
285
+ | File | Topic |
286
+ |------|-------|
287
+ | `guidelines/01_sql.md` | ABAP SQL Best Practices |
288
+ | `guidelines/02_exceptions.md` | Exception Handling |
289
+ | `guidelines/03_testing.md` | Unit Testing (including CDS) |
290
+ | `guidelines/04_cds.md` | CDS Views |
291
+ | `guidelines/05_classes.md` | ABAP Classes and Objects |
292
+ | `guidelines/06_objects.md` | Object Naming Conventions |
293
+ | `guidelines/07_json.md` | JSON Handling |
294
+ | `guidelines/08_abapgit.md` | abapGit XML Metadata Templates |
295
+
296
+ These guidelines are automatically searched by the `ref` command.
297
+
298
+ ---
299
+
300
+ ## Custom Guidelines
301
+
302
+ You can add your own guidelines:
303
+
304
+ 1. Create `.md` files in `guidelines/` folder
305
+ 2. Export to reference folder: `abapgit-agent ref export`
306
+ 3. The `ref` command will search both cheat sheets and your custom guidelines
307
+
308
+ ---
309
+
310
+ ## For More Information
311
+
312
+ - [SAP ABAP Cheat Sheets](https://github.com/SAP-samples/abap-cheat-sheets)
313
+ - [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm)
package/bin/abapgit-agent CHANGED
@@ -6,6 +6,7 @@
6
6
  * abapgit-agent init --folder <folder> --package <package> # Initialize: copies config, CLAUDE.md, guidelines
7
7
  * abapgit-agent init --update # Update existing files to latest version
8
8
  * abapgit-agent create
9
+ * abapgit-agent delete
9
10
  * abapgit-agent import [--message <message>]
10
11
  * abapgit-agent pull [--branch <branch>]
11
12
  * abapgit-agent pull --url <git-url> [--branch <branch>]
@@ -1228,10 +1229,19 @@ async function runInit(args) {
1228
1229
  const updateMode = args.includes('--update');
1229
1230
 
1230
1231
  // Get parameters
1231
- const folder = folderArgIndex !== -1 && folderArgIndex + 1 < args.length
1232
+ let folder = folderArgIndex !== -1 && folderArgIndex + 1 < args.length
1232
1233
  ? args[folderArgIndex + 1]
1233
1234
  : '/src/';
1234
1235
 
1236
+ // Normalize folder path: ensure it starts with / and ends with /
1237
+ folder = folder.trim();
1238
+ if (!folder.startsWith('/')) {
1239
+ folder = '/' + folder;
1240
+ }
1241
+ if (!folder.endsWith('/')) {
1242
+ folder = folder + '/';
1243
+ }
1244
+
1235
1245
  const packageName = packageArgIndex !== -1 && packageArgIndex + 1 < args.length
1236
1246
  ? args[packageArgIndex + 1]
1237
1247
  : null;
@@ -1503,7 +1513,7 @@ To enable integration:
1503
1513
  }
1504
1514
 
1505
1515
  // Version compatibility check for commands that interact with ABAP
1506
- const abapCommands = ['create', 'import', 'pull', 'inspect', 'unit', 'tree', 'view', 'preview', 'list'];
1516
+ const abapCommands = ['create', 'delete', 'import', 'pull', 'inspect', 'unit', 'tree', 'view', 'preview', 'list'];
1507
1517
  if (command && abapCommands.includes(command)) {
1508
1518
  await checkVersionCompatibility();
1509
1519
  }
@@ -1605,6 +1615,67 @@ Examples:
1605
1615
  break;
1606
1616
  }
1607
1617
 
1618
+ case 'delete': {
1619
+ const helpIndex = args.findIndex(a => a === '--help' || a === '-h');
1620
+
1621
+ // Show help if requested
1622
+ if (helpIndex !== -1) {
1623
+ console.log(`
1624
+ Usage:
1625
+ abapgit-agent delete
1626
+
1627
+ Description:
1628
+ Delete abapGit online repository from ABAP system.
1629
+ Auto-detects URL from git remote of current directory.
1630
+
1631
+ Prerequisites:
1632
+ - Run "abapgit-agent create" first
1633
+
1634
+ Examples:
1635
+ abapgit-agent delete # Delete repo for current git remote
1636
+ `);
1637
+ return;
1638
+ }
1639
+
1640
+ // Get URL from current git remote
1641
+ const config = loadConfig();
1642
+ const repoUrl = getGitRemoteUrl();
1643
+
1644
+ if (!repoUrl) {
1645
+ console.error('Error: No git remote configured. Please configure a remote origin.');
1646
+ process.exit(1);
1647
+ }
1648
+
1649
+ console.log(`\n🗑️ Deleting online repository`);
1650
+ console.log(` URL: ${repoUrl}`);
1651
+
1652
+ const csrfToken = await fetchCsrfToken(config);
1653
+
1654
+ const data = {
1655
+ url: repoUrl
1656
+ };
1657
+
1658
+ const result = await request('POST', '/sap/bc/z_abapgit_agent/delete', data, { csrfToken });
1659
+
1660
+ console.log('\n');
1661
+
1662
+ // Handle uppercase keys from ABAP
1663
+ const success = result.SUCCESS || result.success;
1664
+ const repoKey = result.REPO_KEY || result.repo_key;
1665
+ const message = result.MESSAGE || result.message;
1666
+ const error = result.ERROR || result.error;
1667
+
1668
+ if (success === 'X' || success === true) {
1669
+ console.log(`✅ Repository deleted successfully!`);
1670
+ console.log(` Key: ${repoKey}`);
1671
+ } else {
1672
+ console.log(`❌ Failed to delete repository`);
1673
+ console.log(` Error: ${error || message || 'Unknown error'}`);
1674
+ process.exit(1);
1675
+ }
1676
+ break;
1677
+ }
1678
+
1608
1679
  case 'import': {
1609
1680
  const helpIndex = args.findIndex(a => a === '--help' || a === '-h');
1610
1681
 
@@ -1739,6 +1810,34 @@ Examples:
1739
1810
  if (isAbapIntegrationEnabled()) {
1740
1811
  console.log('✅ ABAP Git Agent is ENABLED');
1741
1812
  console.log(' Config location:', pathModule.join(process.cwd(), '.abapGitAgent'));
1813
+
1814
+ // Check if repo exists in ABAP
1815
+ const config = loadConfig();
1816
+ const repoUrl = getGitRemoteUrl();
1817
+
1818
+ if (repoUrl) {
1819
+ try {
1820
+ const csrfToken = await fetchCsrfToken(config);
1821
+ const result = await request('POST', '/sap/bc/z_abapgit_agent/status', { url: repoUrl }, { csrfToken });
1822
+
1823
+ const status = result.status || result.STATUS || result.SUCCESS;
1824
+ if (status === 'Found' || status === 'X' || status === true) {
1825
+ console.log(' Repository: ✅ Created');
1826
+ console.log(` Package: ${result.PACKAGE || result.package}`);
1827
+ console.log(` URL: ${repoUrl}`);
1828
+ console.log(` Key: ${result.REPO_KEY || result.repo_key}`);
1829
+ } else {
1830
+ console.log(' Repository: ❌ Not created in ABAP system');
1831
+ console.log(` URL: ${repoUrl}`);
1832
+ console.log(' Run "abapgit-agent create" to create repository');
1833
+ }
1834
+ } catch (err) {
1835
+ console.log(' Repository: ⚠️ Unable to check status');
1836
+ console.log(' Error:', err.message);
1837
+ }
1838
+ } else {
1839
+ console.log(' No git remote configured');
1840
+ }
1742
1841
  } else {
1743
1842
  console.log('❌ ABAP Git Agent is NOT configured');
1744
1843
  }
@@ -2206,10 +2305,11 @@ Examples:
2206
2305
  const objectsArgIndex = args.indexOf('--objects');
2207
2306
  if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
2208
2307
  console.error('Error: --objects parameter required');
2209
- console.error('Usage: abapgit-agent preview --objects <table1>,<view1>,... [--type <type>] [--limit <n>] [--where <condition>] [--columns <cols>] [--vertical] [--compact] [--json]');
2308
+ console.error('Usage: abapgit-agent preview --objects <table1>,<view1>,... [--type <type>] [--limit <n>] [--offset <n>] [--where <condition>] [--columns <cols>] [--vertical] [--compact] [--json]');
2210
2309
  console.error('Example: abapgit-agent preview --objects SFLIGHT');
2211
2310
  console.error('Example: abapgit-agent preview --objects ZC_MY_CDS_VIEW --type DDLS');
2212
2311
  console.error('Example: abapgit-agent preview --objects SFLIGHT --where "CARRID = \'AA\'"');
2312
+ console.error('Example: abapgit-agent preview --objects SFLIGHT --offset 10 --limit 20');
2213
2313
  process.exit(1);
2214
2314
  }
2215
2315
 
@@ -2217,7 +2317,13 @@ Examples:
2217
2317
  const typeArg = args.indexOf('--type');
2218
2318
  const type = typeArg !== -1 ? args[typeArg + 1].toUpperCase() : null;
2219
2319
  const limitArg = args.indexOf('--limit');
2220
- const limit = limitArg !== -1 ? parseInt(args[limitArg + 1], 10) : 10;
2320
+ const limitRaw = limitArg !== -1 ? args[limitArg + 1] : null;
2321
+ const limitParsed = parseInt(limitRaw, 10);
2322
+ const limit = limitRaw && !limitRaw.startsWith('--') && !isNaN(limitParsed) ? Math.max(1, limitParsed) : 100;
2323
+ const offsetArg = args.indexOf('--offset');
2324
+ const offsetRaw = offsetArg !== -1 ? args[offsetArg + 1] : null;
2325
+ const offsetParsed = parseInt(offsetRaw, 10);
2326
+ const offset = offsetRaw && !offsetRaw.startsWith('--') && !isNaN(offsetParsed) ? Math.max(0, offsetParsed) : 0;
2221
2327
  const whereArg = args.indexOf('--where');
2222
2328
  const where = whereArg !== -1 ? args[whereArg + 1] : null;
2223
2329
  const columnsArg = args.indexOf('--columns');
@@ -2233,7 +2339,8 @@ Examples:
2233
2339
 
2234
2340
  const data = {
2235
2341
  objects: objects,
2236
- limit: Math.min(Math.max(1, limit), 100)
2342
+ limit: Math.min(Math.max(1, limit), 500),
2343
+ offset: Math.max(0, offset)
2237
2344
  };
2238
2345
 
2239
2346
  if (type) {
@@ -2261,10 +2368,30 @@ Examples:
2261
2368
  break;
2262
2369
  }
2263
2370
 
2371
+ const pagination = result.PAGINATION || result.pagination || null;
2372
+
2264
2373
  if (jsonOutput) {
2265
2374
  console.log(JSON.stringify(result, null, 2));
2266
2375
  } else {
2267
- console.log(`\n ${message}`);
2376
+ // Build pagination message
2377
+ let paginationMsg = '';
2378
+ const paginationTotal = pagination ? (pagination.TOTAL || pagination.total || 0) : 0;
2379
+ const paginationHasMore = pagination ? (pagination.HAS_MORE || pagination.has_more || false) : false;
2380
+ if (pagination && paginationTotal > 0) {
2381
+ // Handle case where offset exceeds total
2382
+ if (offset >= paginationTotal) {
2383
+ paginationMsg = ` (Offset ${offset} exceeds total ${paginationTotal})`;
2384
+ } else {
2385
+ const start = offset + 1;
2386
+ const end = Math.min(offset + limit, paginationTotal);
2387
+ paginationMsg = ` (Showing ${start}-${end} of ${paginationTotal})`;
2388
+ if (paginationHasMore) {
2389
+ paginationMsg += ` — Use --offset ${offset + limit} to see more`;
2390
+ }
2391
+ }
2392
+ }
2393
+
2394
+ console.log(`\n ${message}${paginationMsg}`);
2268
2395
  console.log('');
2269
2396
 
2270
2397
  // Track if columns were explicitly specified
@@ -2443,10 +2570,11 @@ Examples:
2443
2570
  const objectsArgIndex = args.indexOf('--objects');
2444
2571
  if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
2445
2572
  console.error('Error: --objects parameter required');
2446
- console.error('Usage: abapgit-agent where --objects <obj1>,<obj2>,... [--type <type>] [--limit <n>] [--json]');
2573
+ console.error('Usage: abapgit-agent where --objects <obj1>,<obj2>,... [--type <type>] [--limit <n>] [--offset <n>] [--json]');
2447
2574
  console.error('Example: abapgit-agent where --objects ZCL_MY_CLASS');
2448
2575
  console.error('Example: abapgit-agent where --objects ZIF_MY_INTERFACE');
2449
2576
  console.error('Example: abapgit-agent where --objects CL_SUT_AUNIT_RUNNER --limit 20');
2577
+ console.error('Example: abapgit-agent where --objects CL_SUT_AUNIT_RUNNER --offset 100');
2450
2578
  process.exit(1);
2451
2579
  }
2452
2580
 
@@ -2454,7 +2582,13 @@ Examples:
2454
2582
  const typeArg = args.indexOf('--type');
2455
2583
  const type = typeArg !== -1 ? args[typeArg + 1].toUpperCase() : null;
2456
2584
  const limitArg = args.indexOf('--limit');
2457
- const limit = limitArg !== -1 ? parseInt(args[limitArg + 1], 10) : 100;
2585
+ const limitRaw = limitArg !== -1 ? args[limitArg + 1] : null;
2586
+ const limitParsed = parseInt(limitRaw, 10);
2587
+ const limit = limitRaw && !limitRaw.startsWith('--') && !isNaN(limitParsed) ? Math.max(1, limitParsed) : 100;
2588
+ const offsetArg = args.indexOf('--offset');
2589
+ const offsetRaw = offsetArg !== -1 ? args[offsetArg + 1] : null;
2590
+ const offsetParsed = parseInt(offsetRaw, 10);
2591
+ const offset = offsetRaw && !offsetRaw.startsWith('--') && !isNaN(offsetParsed) ? Math.max(0, offsetParsed) : 0;
2458
2592
  const jsonOutput = args.includes('--json');
2459
2593
 
2460
2594
  console.log(`\n Where-used list for ${objects.length} object(s)`);
@@ -2464,7 +2598,8 @@ Examples:
2464
2598
 
2465
2599
  const data = {
2466
2600
  objects: objects,
2467
- limit: Math.min(Math.max(1, limit), 500)
2601
+ limit: Math.min(Math.max(1, limit), 500),
2602
+ offset: Math.max(0, offset)
2468
2603
  };
2469
2604
 
2470
2605
  if (type) {
@@ -2478,6 +2613,7 @@ Examples:
2478
2613
  const whereObjects = result.OBJECTS || result.objects || [];
2479
2614
  const message = result.MESSAGE || result.message || '';
2480
2615
  const error = result.ERROR || result.error;
2616
+ const pagination = result.PAGINATION || result.pagination || null;
2481
2617
 
2482
2618
  if (!success || error) {
2483
2619
  console.error(`\n Error: ${error || 'Failed to get where-used list'}`);
@@ -2487,7 +2623,25 @@ Examples:
2487
2623
  if (jsonOutput) {
2488
2624
  console.log(JSON.stringify(result, null, 2));
2489
2625
  } else {
2490
- console.log(`\n ${message}`);
2626
+ // Build pagination message
2627
+ let paginationMsg = '';
2628
+ const paginationTotal = pagination.TOTAL || pagination.total || 0;
2629
+ const paginationHasMore = pagination.HAS_MORE || pagination.has_more || false;
2630
+ if (pagination && paginationTotal > 0) {
2631
+ // Handle case where offset exceeds total
2632
+ if (offset >= paginationTotal) {
2633
+ paginationMsg = ` (Offset ${offset} exceeds total ${paginationTotal})`;
2634
+ } else {
2635
+ const start = offset + 1;
2636
+ const end = Math.min(offset + limit, paginationTotal);
2637
+ paginationMsg = ` (Showing ${start}-${end} of ${paginationTotal})`;
2638
+ if (paginationHasMore) {
2639
+ paginationMsg += ` — Use --offset ${offset + limit} to see more`;
2640
+ }
2641
+ }
2642
+ }
2643
+
2644
+ console.log(`\n ${message}${paginationMsg}`);
2491
2645
  console.log('');
2492
2646
 
2493
2647
  for (let i = 0; i < whereObjects.length; i++) {
@@ -2541,17 +2695,21 @@ Examples:
2541
2695
  case 'ref': {
2542
2696
  const refSearch = require('../src/ref-search');
2543
2697
  const topicIndex = args.indexOf('--topic');
2698
+ const cloneIndex = args.indexOf('--clone');
2699
+ const nameIndex = args.indexOf('--name');
2544
2700
  const listTopics = args.includes('--list-topics') || args.includes('-l');
2545
2701
  const listRepos = args.includes('--list-repos') || args.includes('-r');
2546
- const exportGuidelines = args.includes('--export') || args.includes('-e');
2547
2702
  const jsonOutput = args.includes('--json');
2548
2703
 
2549
- if (exportGuidelines) {
2550
- const result = await refSearch.exportGuidelines();
2704
+ // Handle --clone option
2705
+ if (cloneIndex !== -1 && cloneIndex + 1 < args.length) {
2706
+ const repoUrl = args[cloneIndex + 1];
2707
+ const name = nameIndex !== -1 && nameIndex + 1 < args.length ? args[nameIndex + 1] : null;
2708
+ const result = refSearch.cloneRepository(repoUrl, name);
2551
2709
  if (jsonOutput) {
2552
2710
  console.log(JSON.stringify(result, null, 2));
2553
2711
  } else {
2554
- refSearch.displayExportResult(result);
2712
+ refSearch.displayCloneResult(result);
2555
2713
  }
2556
2714
  break;
2557
2715
  }
@@ -2596,15 +2754,16 @@ Examples:
2596
2754
  console.error(' abapgit-agent ref <pattern> Search for pattern');
2597
2755
  console.error(' abapgit-agent ref --topic <name> View specific topic');
2598
2756
  console.error(' abapgit-agent ref --list-topics List available topics');
2599
- console.error(' abapgit-agent ref --list-repos List reference repositories');
2600
- console.error(' abapgit-agent ref --export Export local guidelines to reference folder');
2757
+ console.error(' abapgit-agent ref --list-repos List reference repositories');
2758
+ console.error(' abapgit-agent ref --clone <repo> Clone a repository');
2601
2759
  console.error('');
2602
2760
  console.error('Examples:');
2603
2761
  console.error(' abapgit-agent ref "CORRESPONDING"');
2604
2762
  console.error(' abapgit-agent ref --topic exceptions');
2605
2763
  console.error(' abapgit-agent ref --list-topics');
2606
2764
  console.error(' abapgit-agent ref --list-repos');
2607
- console.error(' abapgit-agent ref --export');
2765
+ console.error(' abapgit-agent ref --clone SAP-samples/abap-cheat-sheets');
2766
+ console.error(' abapgit-agent ref --clone https://github.com/abapGit/abapGit.git');
2608
2767
  process.exit(1);
2609
2768
  }
2610
2769
 
@@ -2678,8 +2837,10 @@ Commands:
2678
2837
  ref --list-repos
2679
2838
  List all reference repositories in the reference folder
2680
2839
 
2681
- ref --export
2682
- Export custom guidelines (abap/guidelines/) to reference folder
2840
+ ref --clone <repo> [--name <folder>]
2841
+ Clone a GitHub repository to the reference folder
2842
+ - Use full URL: https://github.com/user/repo.git
2843
+ - Or short name: user/repo or user/repo (assumes github.com)
2683
2844
 
2684
2845
  health
2685
2846
  Check if ABAP REST API is healthy
@@ -2691,6 +2852,7 @@ Examples:
2691
2852
  abapgit-agent init --folder /src --package ZMY_PACKAGE # Initialize
2692
2853
  abapgit-agent init --update # Update files to latest
2693
2854
  abapgit-agent create # Create repo
2855
+ abapgit-agent delete # Delete repo
2694
2856
  abapgit-agent import # Import objects to git
2695
2857
  abapgit-agent import --message "Initial import" # Import with message
2696
2858
  abapgit-agent pull # Auto-detect from git
@@ -2723,7 +2885,8 @@ Examples:
2723
2885
  abapgit-agent ref --topic unit-tests # View unit test topic
2724
2886
  abapgit-agent ref --list-topics # List all topics
2725
2887
  abapgit-agent ref --list-repos # List reference repositories
2726
- abapgit-agent ref --export # Export custom guidelines
2888
+ abapgit-agent ref --clone SAP-samples/abap-cheat-sheets # Clone repo to reference folder
2889
+ abapgit-agent ref --clone https://github.com/user/repo.git # Clone from URL
2727
2890
  abapgit-agent health
2728
2891
  abapgit-agent status
2729
2892
  `);
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "abapgit-agent",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
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",
@@ -18,8 +21,9 @@
18
21
  "test": "jest",
19
22
  "test:all": "node scripts/test-all.js",
20
23
  "test:jest": "jest",
21
- "test:aunit": "node scripts/test-all.js --jest --cmd",
22
- "test:cmd": "node scripts/test-all.js --jest --aunit",
24
+ "test:aunit": "node scripts/test-all.js --aunit",
25
+ "test:cmd": "node scripts/test-all.js --cmd",
26
+ "test:cmd:demo": "node scripts/test-all.js --cmd --demo",
23
27
  "pull": "node bin/abapgit-agent",
24
28
  "release": "node scripts/release.js",
25
29
  "unrelease": "node scripts/unrelease.js"
@@ -379,13 +379,14 @@ class ABAPClient {
379
379
  return await this.request('POST', '/tree', data, { csrfToken: this.csrfToken });
380
380
  }
381
381
 
382
- async preview(objects, type = null, limit = 10, where = null, columns = null) {
382
+ async preview(objects, type = null, limit = 100, offset = 0, where = null, columns = null) {
383
383
  // Fetch CSRF token first
384
384
  await this.fetchCsrfToken();
385
385
 
386
386
  const data = {
387
387
  objects: objects,
388
- limit: Math.min(Math.max(1, limit), 100)
388
+ limit: Math.min(Math.max(1, limit), 500),
389
+ offset: Math.max(0, offset)
389
390
  };
390
391
 
391
392
  if (type) {
@@ -402,7 +403,7 @@ class ABAPClient {
402
403
  data.columns = columns;
403
404
  }
404
405
 
405
- logger.info('Previewing data', { objects, type, limit: data.limit, where: data.where, service: 'abapgit-agent' });
406
+ logger.info('Previewing data', { objects, type, limit: data.limit, offset: data.offset, where: data.where, service: 'abapgit-agent' });
406
407
 
407
408
  return await this.request('POST', '/preview', data, { csrfToken: this.csrfToken });
408
409
  }
@@ -487,21 +488,23 @@ class ABAPClient {
487
488
  * @param {Array} objects - Array of object names to search
488
489
  * @param {string} type - Object type (optional)
489
490
  * @param {number} limit - Maximum results (default: 100, max: 500)
491
+ * @param {number} offset - Number of results to skip (default: 0)
490
492
  * @returns {object} Where-used result with found objects
491
493
  */
492
- async where(objects, type = null, limit = 100) {
494
+ async where(objects, type = null, limit = 100, offset = 0) {
493
495
  await this.fetchCsrfToken();
494
496
 
495
497
  const data = {
496
498
  objects: objects,
497
- limit: Math.min(Math.max(1, limit), 500)
499
+ limit: Math.min(Math.max(1, limit), 500),
500
+ offset: Math.max(0, offset)
498
501
  };
499
502
 
500
503
  if (type) {
501
504
  data.type = type;
502
505
  }
503
506
 
504
- logger.info('Finding where-used', { objects, type, limit: data.limit, service: 'abapgit-agent' });
507
+ logger.info('Finding where-used', { objects, type, limit: data.limit, offset: data.offset, service: 'abapgit-agent' });
505
508
 
506
509
  return await this.request('POST', '/where', data, { csrfToken: this.csrfToken });
507
510
  }
package/src/agent.js CHANGED
@@ -197,21 +197,23 @@ class ABAPGitAgent {
197
197
  * @param {Array} objects - Array of table/view names
198
198
  * @param {string} type - Object type (TABL, DDLS, etc.)
199
199
  * @param {number} limit - Maximum rows to return
200
+ * @param {number} offset - Number of rows to skip
200
201
  * @param {string} where - WHERE clause filter
201
202
  * @param {Array} columns - Array of column names to display
202
203
  * @returns {object} Preview result with rows, fields, and metadata
203
204
  */
204
- async preview(objects, type = null, limit = 10, where = null, columns = null) {
205
- logger.info('Previewing data', { objects, type, limit, where, columns });
205
+ async preview(objects, type = null, limit = 100, offset = 0, where = null, columns = null) {
206
+ logger.info('Previewing data', { objects, type, limit, offset, where, columns });
206
207
 
207
208
  try {
208
- const result = await this.abap.preview(objects, type, limit, where, columns);
209
+ const result = await this.abap.preview(objects, type, limit, offset, where, columns);
209
210
  return {
210
211
  success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
211
212
  command: result.COMMAND || result.command || 'PREVIEW',
212
213
  message: result.MESSAGE || result.message || '',
213
214
  objects: result.OBJECTS || result.objects || [],
214
215
  summary: result.SUMMARY || result.summary || null,
216
+ pagination: result.PAGINATION || result.pagination || null,
215
217
  error: result.ERROR || result.error || null
216
218
  };
217
219
  } catch (error) {
@@ -293,18 +295,20 @@ class ABAPGitAgent {
293
295
  * @param {Array} objects - Array of object names to search
294
296
  * @param {string} type - Object type (optional)
295
297
  * @param {number} limit - Maximum results (default: 100, max: 500)
298
+ * @param {number} offset - Number of results to skip (default: 0)
296
299
  * @returns {object} Where-used result with found objects
297
300
  */
298
- async where(objects, type = null, limit = 100) {
299
- logger.info('Finding where-used', { objects, type, limit });
301
+ async where(objects, type = null, limit = 100, offset = 0) {
302
+ logger.info('Finding where-used', { objects, type, limit, offset });
300
303
 
301
304
  try {
302
- const result = await this.abap.where(objects, type, limit);
305
+ const result = await this.abap.where(objects, type, limit, offset);
303
306
  return {
304
307
  success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
305
308
  command: result.COMMAND || result.command || 'WHERE',
306
309
  objects: result.OBJECTS || result.objects || [],
307
310
  message: result.MESSAGE || result.message || '',
311
+ pagination: result.PAGINATION || result.pagination || null,
308
312
  error: result.ERROR || result.error || null
309
313
  };
310
314
  } catch (error) {
package/src/ref-search.js CHANGED
@@ -8,6 +8,7 @@
8
8
  const fs = require('fs');
9
9
  const path = require('path');
10
10
  const { promisify } = require('util');
11
+ const { execSync } = require('child_process');
11
12
  const readdir = promisify(fs.readdir);
12
13
  const readFile = promisify(fs.readFile);
13
14
  const stat = promisify(fs.stat);
@@ -63,6 +64,120 @@ const TOPIC_MAP = {
63
64
  'tables': '01_Internal_Tables.md'
64
65
  };
65
66
 
67
+ /**
68
+ * Ensure reference folder exists, create if necessary
69
+ * @returns {string|null} Path to reference folder or null if cannot create
70
+ */
71
+ function ensureReferenceFolder() {
72
+ let refFolder = detectReferenceFolder();
73
+
74
+ if (refFolder && fs.existsSync(refFolder)) {
75
+ return refFolder;
76
+ }
77
+
78
+ // Try to create the reference folder at default location
79
+ const homeDir = require('os').homedir();
80
+ const defaultPath = path.join(homeDir, 'abap-reference');
81
+
82
+ try {
83
+ if (!fs.existsSync(defaultPath)) {
84
+ fs.mkdirSync(defaultPath, { recursive: true });
85
+ }
86
+ return defaultPath;
87
+ } catch (error) {
88
+ return null;
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Clone a repository to the reference folder
94
+ * @param {string} repoUrl - Git repository URL or short name (e.g., "SAP-samples/abap-cheat-sheets")
95
+ * @param {string|null} name - Optional folder name for the cloned repo
96
+ * @returns {Object} Clone result
97
+ */
98
+ function cloneRepository(repoUrl, name = null) {
99
+ const refFolder = ensureReferenceFolder();
100
+
101
+ if (!refFolder) {
102
+ return {
103
+ success: false,
104
+ error: 'Could not create reference folder',
105
+ hint: 'Set referenceFolder in .abapGitAgent or ensure ~/abap-reference is writable'
106
+ };
107
+ }
108
+
109
+ // Parse the repo URL
110
+ let targetName = name;
111
+ let cloneUrl = repoUrl;
112
+
113
+ // Handle short names (e.g., "SAP-samples/abap-cheat-sheets")
114
+ if (!repoUrl.startsWith('http://') && !repoUrl.startsWith('https://') && !repoUrl.startsWith('git@')) {
115
+ cloneUrl = `https://github.com/${repoUrl}.git`;
116
+ }
117
+
118
+ // If no name provided, extract from URL
119
+ if (!targetName) {
120
+ // Extract repo name from URL
121
+ const urlParts = cloneUrl.split('/');
122
+ const repoWithGit = urlParts[urlParts.length - 1];
123
+ targetName = repoWithGit.replace(/\.git$/, '');
124
+ }
125
+
126
+ const targetPath = path.join(refFolder, targetName);
127
+
128
+ // Check if already exists
129
+ if (fs.existsSync(targetPath)) {
130
+ return {
131
+ success: false,
132
+ error: `Repository already exists: ${targetName}`,
133
+ hint: `Delete '${targetPath}' to re-clone, or use --name to specify a different folder name`,
134
+ existingPath: targetPath
135
+ };
136
+ }
137
+
138
+ try {
139
+ // Run git clone
140
+ execSync(`git clone "${cloneUrl}" "${targetPath}"`, {
141
+ stdio: 'pipe',
142
+ encoding: 'utf8'
143
+ });
144
+
145
+ return {
146
+ success: true,
147
+ message: `Successfully cloned ${repoUrl}`,
148
+ repository: targetName,
149
+ folder: targetPath,
150
+ referenceFolder: refFolder
151
+ };
152
+ } catch (error) {
153
+ return {
154
+ success: false,
155
+ error: `Failed to clone: ${error.message}`,
156
+ hint: 'Check the repository URL and your network connection'
157
+ };
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Display clone result in console format
163
+ * @param {Object} result - Clone result
164
+ */
165
+ function displayCloneResult(result) {
166
+ if (result.success) {
167
+ console.log(`\n ✅ ${result.message}`);
168
+ console.log(`\n 📁 Repository: ${result.repository}`);
169
+ console.log(` 📁 Location: ${result.folder}`);
170
+ console.log(` 📁 Reference folder: ${result.referenceFolder}`);
171
+ console.log(`\n 💡 You can now search this repository with:`);
172
+ console.log(` abapgit-agent ref --list-repos`);
173
+ } else {
174
+ console.error(`\n ❌ ${result.error}`);
175
+ if (result.hint) {
176
+ console.error(`\n 💡 ${result.hint}`);
177
+ }
178
+ }
179
+ }
180
+
66
181
  /**
67
182
  * Detect reference folder from config or common locations
68
183
  * @returns {string|null} Path to reference folder or null if not found
@@ -1005,7 +1120,7 @@ function displayInitResult(result) {
1005
1120
  console.log(`\n 💡 Next steps:`);
1006
1121
  console.log(` 1. Review the guidelines in abap/guidelines/`);
1007
1122
  console.log(` 2. Customize as needed for your project`);
1008
- console.log(` 3. Run 'abapgit-agent ref --export' to make them searchable`);
1123
+ console.log(` 3. Guidelines are automatically searchable with 'ref' command`);
1009
1124
  } else {
1010
1125
  console.error(`\n ❌ ${result.error}`);
1011
1126
  if (result.hint) {
@@ -1016,6 +1131,7 @@ function displayInitResult(result) {
1016
1131
 
1017
1132
  module.exports = {
1018
1133
  detectReferenceFolder,
1134
+ ensureReferenceFolder,
1019
1135
  detectGuidelinesFolder,
1020
1136
  getBuiltInGuidelinesPath,
1021
1137
  initGuidelines,
@@ -1027,11 +1143,13 @@ module.exports = {
1027
1143
  listTopics,
1028
1144
  listRepositories,
1029
1145
  exportGuidelines,
1146
+ cloneRepository,
1030
1147
  displaySearchResults,
1031
1148
  displayTopic,
1032
1149
  displayTopics,
1033
1150
  displayRepositories,
1034
1151
  displayExportResult,
1035
1152
  displayInitResult,
1153
+ displayCloneResult,
1036
1154
  TOPIC_MAP
1037
1155
  };