abapgit-agent 1.4.0 → 1.6.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.
Files changed (115) hide show
  1. package/README.md +2 -0
  2. package/abap/guidelines/00_index.md +35 -0
  3. package/abap/guidelines/01_sql.md +72 -0
  4. package/abap/guidelines/02_exceptions.md +108 -0
  5. package/abap/guidelines/03_testing.md +252 -0
  6. package/abap/guidelines/04_cds.md +120 -0
  7. package/abap/guidelines/05_classes.md +50 -0
  8. package/abap/guidelines/06_objects.md +103 -0
  9. package/abap/guidelines/07_json.md +22 -0
  10. package/abap/guidelines/08_abapgit.md +193 -0
  11. package/bin/abapgit-agent +597 -44
  12. package/bin/abgagt +24 -0
  13. package/package.json +11 -3
  14. package/src/abap-client.js +65 -2
  15. package/src/agent.js +58 -4
  16. package/src/config.js +9 -2
  17. package/src/ref-search.js +989 -0
  18. package/.abapGitAgent.example +0 -11
  19. package/.github/workflows/release.yml +0 -57
  20. package/API.md +0 -710
  21. package/CLAUDE.md +0 -1031
  22. package/CLAUDE_MEM.md +0 -88
  23. package/ERROR_HANDLING.md +0 -30
  24. package/INSTALL.md +0 -155
  25. package/RELEASE_NOTES.md +0 -143
  26. package/abap/CLAUDE.md +0 -898
  27. package/abap/copilot-instructions.md +0 -79
  28. package/abap/package.devc.xml +0 -10
  29. package/abap/zcl_abgagt_agent.clas.abap +0 -420
  30. package/abap/zcl_abgagt_agent.clas.xml +0 -15
  31. package/abap/zcl_abgagt_cmd_factory.clas.abap +0 -48
  32. package/abap/zcl_abgagt_cmd_factory.clas.xml +0 -15
  33. package/abap/zcl_abgagt_command_create.clas.abap +0 -95
  34. package/abap/zcl_abgagt_command_create.clas.xml +0 -15
  35. package/abap/zcl_abgagt_command_import.clas.abap +0 -138
  36. package/abap/zcl_abgagt_command_import.clas.xml +0 -15
  37. package/abap/zcl_abgagt_command_inspect.clas.abap +0 -411
  38. package/abap/zcl_abgagt_command_inspect.clas.testclasses.abap +0 -121
  39. package/abap/zcl_abgagt_command_inspect.clas.xml +0 -16
  40. package/abap/zcl_abgagt_command_preview.clas.abap +0 -386
  41. package/abap/zcl_abgagt_command_preview.clas.xml +0 -15
  42. package/abap/zcl_abgagt_command_pull.clas.abap +0 -80
  43. package/abap/zcl_abgagt_command_pull.clas.testclasses.abap +0 -87
  44. package/abap/zcl_abgagt_command_pull.clas.xml +0 -16
  45. package/abap/zcl_abgagt_command_tree.clas.abap +0 -237
  46. package/abap/zcl_abgagt_command_tree.clas.xml +0 -15
  47. package/abap/zcl_abgagt_command_unit.clas.abap +0 -297
  48. package/abap/zcl_abgagt_command_unit.clas.xml +0 -15
  49. package/abap/zcl_abgagt_command_view.clas.abap +0 -240
  50. package/abap/zcl_abgagt_command_view.clas.xml +0 -15
  51. package/abap/zcl_abgagt_resource_create.clas.abap +0 -71
  52. package/abap/zcl_abgagt_resource_create.clas.xml +0 -15
  53. package/abap/zcl_abgagt_resource_health.clas.abap +0 -25
  54. package/abap/zcl_abgagt_resource_health.clas.xml +0 -15
  55. package/abap/zcl_abgagt_resource_import.clas.abap +0 -66
  56. package/abap/zcl_abgagt_resource_import.clas.xml +0 -15
  57. package/abap/zcl_abgagt_resource_inspect.clas.abap +0 -62
  58. package/abap/zcl_abgagt_resource_inspect.clas.xml +0 -15
  59. package/abap/zcl_abgagt_resource_preview.clas.abap +0 -67
  60. package/abap/zcl_abgagt_resource_preview.clas.xml +0 -15
  61. package/abap/zcl_abgagt_resource_pull.clas.abap +0 -71
  62. package/abap/zcl_abgagt_resource_pull.clas.xml +0 -15
  63. package/abap/zcl_abgagt_resource_tree.clas.abap +0 -70
  64. package/abap/zcl_abgagt_resource_tree.clas.xml +0 -15
  65. package/abap/zcl_abgagt_resource_unit.clas.abap +0 -64
  66. package/abap/zcl_abgagt_resource_unit.clas.xml +0 -15
  67. package/abap/zcl_abgagt_resource_view.clas.abap +0 -68
  68. package/abap/zcl_abgagt_resource_view.clas.xml +0 -15
  69. package/abap/zcl_abgagt_rest_handler.clas.abap +0 -32
  70. package/abap/zcl_abgagt_rest_handler.clas.xml +0 -15
  71. package/abap/zcl_abgagt_util.clas.abap +0 -93
  72. package/abap/zcl_abgagt_util.clas.testclasses.abap +0 -84
  73. package/abap/zcl_abgagt_util.clas.xml +0 -16
  74. package/abap/zcl_abgagt_viewer_clas.clas.abap +0 -58
  75. package/abap/zcl_abgagt_viewer_clas.clas.xml +0 -15
  76. package/abap/zcl_abgagt_viewer_ddls.clas.abap +0 -83
  77. package/abap/zcl_abgagt_viewer_ddls.clas.xml +0 -15
  78. package/abap/zcl_abgagt_viewer_dtel.clas.abap +0 -98
  79. package/abap/zcl_abgagt_viewer_dtel.clas.xml +0 -15
  80. package/abap/zcl_abgagt_viewer_factory.clas.abap +0 -41
  81. package/abap/zcl_abgagt_viewer_factory.clas.xml +0 -15
  82. package/abap/zcl_abgagt_viewer_intf.clas.abap +0 -58
  83. package/abap/zcl_abgagt_viewer_intf.clas.xml +0 -15
  84. package/abap/zcl_abgagt_viewer_stru.clas.abap +0 -59
  85. package/abap/zcl_abgagt_viewer_stru.clas.xml +0 -15
  86. package/abap/zcl_abgagt_viewer_tabl.clas.abap +0 -59
  87. package/abap/zcl_abgagt_viewer_tabl.clas.xml +0 -15
  88. package/abap/zcl_abgagt_viewer_ttyp.clas.abap +0 -93
  89. package/abap/zcl_abgagt_viewer_ttyp.clas.xml +0 -15
  90. package/abap/zif_abgagt_agent.intf.abap +0 -53
  91. package/abap/zif_abgagt_agent.intf.xml +0 -15
  92. package/abap/zif_abgagt_cmd_factory.intf.abap +0 -7
  93. package/abap/zif_abgagt_cmd_factory.intf.xml +0 -15
  94. package/abap/zif_abgagt_command.intf.abap +0 -26
  95. package/abap/zif_abgagt_command.intf.xml +0 -15
  96. package/abap/zif_abgagt_util.intf.abap +0 -28
  97. package/abap/zif_abgagt_util.intf.xml +0 -15
  98. package/abap/zif_abgagt_viewer.intf.abap +0 -12
  99. package/abap/zif_abgagt_viewer.intf.xml +0 -15
  100. package/docs/commands.md +0 -142
  101. package/docs/create-command.md +0 -129
  102. package/docs/health-command.md +0 -89
  103. package/docs/import-command.md +0 -195
  104. package/docs/init-command.md +0 -189
  105. package/docs/inspect-command.md +0 -158
  106. package/docs/preview-command.md +0 -528
  107. package/docs/pull-command.md +0 -188
  108. package/docs/status-command.md +0 -68
  109. package/docs/tree-command.md +0 -303
  110. package/docs/unit-command.md +0 -167
  111. package/docs/view-command.md +0 -501
  112. package/img/claude.png +0 -0
  113. package/scripts/claude-integration.js +0 -351
  114. package/scripts/release.sh +0 -60
  115. package/scripts/test-integration.js +0 -139
package/bin/abgagt ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ // abgagt - Short alias for abapgit-agent
3
+ // Usage: abgagt <command> [options]
4
+ //
5
+ // This is a wrapper script that forwards all arguments to abapgit-agent
6
+ //
7
+ // Examples:
8
+ // abgagt pull
9
+ // abgagt ref "CORRESPONDING"
10
+ // abgagt inspect --files zcl_my_class.clas.abap
11
+
12
+ const path = require('path');
13
+ const { spawn } = require('child_process');
14
+
15
+ const agentPath = path.join(__dirname, 'abapgit-agent');
16
+ const args = process.argv.slice(2);
17
+
18
+ const child = spawn('node', [agentPath, ...args], {
19
+ stdio: 'inherit'
20
+ });
21
+
22
+ child.on('exit', (code) => {
23
+ process.exit(code);
24
+ });
package/package.json CHANGED
@@ -1,16 +1,24 @@
1
1
  {
2
2
  "name": "abapgit-agent",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "ABAP Git Agent - Pull and activate ABAP code via abapGit from any git repository",
5
5
  "main": "src/index.js",
6
+ "files": [
7
+ "bin/",
8
+ "src/",
9
+ "abap/guidelines/"
10
+ ],
6
11
  "bin": {
7
- "abapgit-agent": "bin/abapgit-agent"
12
+ "abapgit-agent": "bin/abapgit-agent",
13
+ "abgagt": "bin/abgagt"
8
14
  },
9
15
  "scripts": {
10
16
  "start": "node src/server.js",
11
17
  "dev": "nodemon src/server.js",
12
18
  "test": "jest",
13
- "pull": "node bin/abapgit-agent"
19
+ "pull": "node bin/abapgit-agent",
20
+ "release": "node scripts/release.js",
21
+ "unrelease": "node scripts/unrelease.js"
14
22
  },
15
23
  "dependencies": {
16
24
  "cors": "^2.8.5",
@@ -379,7 +379,7 @@ 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) {
382
+ async preview(objects, type = null, limit = 10, where = null, columns = null) {
383
383
  // Fetch CSRF token first
384
384
  await this.fetchCsrfToken();
385
385
 
@@ -392,10 +392,73 @@ class ABAPClient {
392
392
  data.type = type;
393
393
  }
394
394
 
395
- logger.info('Previewing data', { objects, type, limit: data.limit, service: 'abapgit-agent' });
395
+ if (where) {
396
+ // Convert ISO date format (YYYY-MM-DD) to ABAP DATS format (YYYYMMDD)
397
+ // This handles date literals in WHERE clauses like "FLDATE = '2024-10-24'"
398
+ data.where = this.convertDatesInWhereClause(where);
399
+ }
400
+
401
+ if (columns) {
402
+ data.columns = columns;
403
+ }
404
+
405
+ logger.info('Previewing data', { objects, type, limit: data.limit, where: data.where, service: 'abapgit-agent' });
396
406
 
397
407
  return await this.request('POST', '/preview', data, { csrfToken: this.csrfToken });
398
408
  }
409
+
410
+ /**
411
+ * Convert ISO date formats to ABAP DATS format in WHERE clause
412
+ * @param {string} whereClause - SQL WHERE clause
413
+ * @returns {string} - WHERE clause with dates converted to YYYYMMDD format
414
+ */
415
+ convertDatesInWhereClause(whereClause) {
416
+ if (!whereClause) return whereClause;
417
+
418
+ // Pattern to match ISO date format: 'YYYY-MM-DD'
419
+ // Uses negative lookbehind and lookahead to ensure we're matching complete dates
420
+ const isoDatePattern = /'\d{4}-\d{2}-\d{2}'/g;
421
+
422
+ return whereClause.replace(isoDatePattern, (match) => {
423
+ // Extract YYYY, MM, DD from 'YYYY-MM-DD'
424
+ const dateContent = match.slice(1, -1); // Remove quotes: YYYY-MM-DD
425
+ const [year, month, day] = dateContent.split('-');
426
+ // Return in ABAP format: 'YYYYMMDD'
427
+ return `'${year}${month}${day}'`;
428
+ });
429
+ }
430
+
431
+ /**
432
+ * List objects in an ABAP package
433
+ * @param {string} packageName - ABAP package name
434
+ * @param {string} type - Comma-separated object types to filter (optional, e.g., 'CLAS,INTF')
435
+ * @param {string} name - Name pattern to filter (optional)
436
+ * @param {number} limit - Maximum number of objects to return (default: 100, max: 1000)
437
+ * @param {number} offset - Offset for pagination (default: 0)
438
+ * @returns {object} List result with objects, by_type, and total
439
+ */
440
+ async list(packageName, type = null, name = null, limit = 100, offset = 0) {
441
+ // Fetch CSRF token first
442
+ await this.fetchCsrfToken();
443
+
444
+ const data = {
445
+ package: packageName,
446
+ limit: Math.min(Math.max(1, limit), 1000),
447
+ offset: Math.max(0, offset)
448
+ };
449
+
450
+ if (type) {
451
+ data.type = type;
452
+ }
453
+
454
+ if (name) {
455
+ data.name = name;
456
+ }
457
+
458
+ logger.info('Listing objects', { package: packageName, type, name, limit: data.limit, offset: data.offset, service: 'abapgit-agent' });
459
+
460
+ return await this.request('POST', '/list', data, { csrfToken: this.csrfToken });
461
+ }
399
462
  }
400
463
 
401
464
  // Singleton instance
package/src/agent.js CHANGED
@@ -53,7 +53,7 @@ class ABAPGitAgent {
53
53
  return {
54
54
  status: 'healthy',
55
55
  abap: 'connected',
56
- version: result.version || '1.0.0'
56
+ version: result.version || '1.4.0'
57
57
  };
58
58
  } catch (error) {
59
59
  return {
@@ -192,11 +192,20 @@ class ABAPGitAgent {
192
192
  }
193
193
  }
194
194
 
195
- async preview(objects, type = null, limit = 10) {
196
- logger.info('Previewing data', { objects, type, limit });
195
+ /**
196
+ * Preview data from ABAP tables or CDS views
197
+ * @param {Array} objects - Array of table/view names
198
+ * @param {string} type - Object type (TABL, DDLS, etc.)
199
+ * @param {number} limit - Maximum rows to return
200
+ * @param {string} where - WHERE clause filter
201
+ * @param {Array} columns - Array of column names to display
202
+ * @returns {object} Preview result with rows, fields, and metadata
203
+ */
204
+ async preview(objects, type = null, limit = 10, where = null, columns = null) {
205
+ logger.info('Previewing data', { objects, type, limit, where, columns });
197
206
 
198
207
  try {
199
- const result = await this.abap.preview(objects, type, limit);
208
+ const result = await this.abap.preview(objects, type, limit, where, columns);
200
209
  return {
201
210
  success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
202
211
  command: result.COMMAND || result.command || 'PREVIEW',
@@ -210,6 +219,51 @@ class ABAPGitAgent {
210
219
  throw new Error(`Preview command failed: ${error.message}`);
211
220
  }
212
221
  }
222
+
223
+ /**
224
+ * List objects in an ABAP package
225
+ * @param {string} packageName - ABAP package name
226
+ * @param {string} type - Comma-separated object types to filter (optional)
227
+ * @param {string} name - Name pattern to filter (optional)
228
+ * @param {number} limit - Maximum number of objects to return (default: 100)
229
+ * @param {number} offset - Offset for pagination (default: 0)
230
+ * @returns {object} List result with objects, by_type, total, and error
231
+ */
232
+ async list(packageName, type = null, name = null, limit = 100, offset = 0) {
233
+ logger.info('Listing objects', { package: packageName, type, name, limit, offset });
234
+
235
+ try {
236
+ const result = await this.abap.list(packageName, type, name, limit, offset);
237
+
238
+ // Normalize objects array to use lowercase keys
239
+ const rawObjects = result.OBJECTS || result.objects || [];
240
+ const normalizedObjects = rawObjects.map(obj => ({
241
+ type: obj.TYPE || obj.type,
242
+ name: obj.NAME || obj.name
243
+ }));
244
+
245
+ // Normalize by_type array to use lowercase keys
246
+ const rawByType = result.BY_TYPE || result.by_type || [];
247
+ const normalizedByType = rawByType.map(item => ({
248
+ type: item.TYPE || item.type,
249
+ count: item.COUNT || item.count || 0
250
+ }));
251
+
252
+ return {
253
+ success: result.SUCCESS === 'X' || result.success === 'X' || result.success === true,
254
+ command: result.COMMAND || result.command || 'LIST',
255
+ package: result.PACKAGE || result.package || packageName,
256
+ message: result.MESSAGE || result.message || '',
257
+ objects: normalizedObjects,
258
+ by_type: normalizedByType,
259
+ total: result.TOTAL || result.total || 0,
260
+ error: result.ERROR || result.error || null
261
+ };
262
+ } catch (error) {
263
+ logger.error('List command failed', { error: error.message });
264
+ throw new Error(`List command failed: ${error.message}`);
265
+ }
266
+ }
213
267
  }
214
268
 
215
269
  module.exports = {
package/src/config.js CHANGED
@@ -33,7 +33,8 @@ function loadConfig() {
33
33
  password: process.env.ABAP_PASSWORD,
34
34
  language: process.env.ABAP_LANGUAGE || 'EN',
35
35
  gitUsername: process.env.GIT_USERNAME,
36
- gitPassword: process.env.GIT_PASSWORD
36
+ gitPassword: process.env.GIT_PASSWORD,
37
+ transport: process.env.ABAP_TRANSPORT
37
38
  };
38
39
  }
39
40
 
@@ -59,8 +60,14 @@ function getAgentConfig() {
59
60
  return cfg.agent;
60
61
  }
61
62
 
63
+ function getTransport() {
64
+ const cfg = loadConfig();
65
+ return cfg.transport;
66
+ }
67
+
62
68
  module.exports = {
63
69
  loadConfig,
64
70
  getAbapConfig,
65
- getAgentConfig
71
+ getAgentConfig,
72
+ getTransport
66
73
  };