abapgit-agent 1.3.0 → 1.4.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.
- package/API.md +179 -1
- package/CLAUDE.md +202 -0
- package/INSTALL.md +6 -11
- package/README.md +10 -0
- package/RELEASE_NOTES.md +44 -0
- package/abap/CLAUDE.md +130 -0
- package/abap/zcl_abgagt_cmd_factory.clas.abap +1 -0
- package/abap/zcl_abgagt_command_preview.clas.abap +386 -0
- package/abap/zcl_abgagt_command_preview.clas.xml +15 -0
- package/abap/zcl_abgagt_resource_preview.clas.abap +67 -0
- package/abap/zcl_abgagt_resource_preview.clas.xml +15 -0
- package/abap/zcl_abgagt_rest_handler.clas.abap +1 -0
- package/abap/zif_abgagt_command.intf.abap +2 -1
- package/bin/abapgit-agent +237 -0
- package/docs/commands.md +5 -0
- package/docs/preview-command.md +528 -0
- package/package.json +1 -1
- package/src/abap-client.js +18 -0
- package/src/agent.js +19 -0
package/bin/abapgit-agent
CHANGED
|
@@ -1726,6 +1726,243 @@ Examples:
|
|
|
1726
1726
|
break;
|
|
1727
1727
|
}
|
|
1728
1728
|
|
|
1729
|
+
case 'preview': {
|
|
1730
|
+
const objectsArgIndex = args.indexOf('--objects');
|
|
1731
|
+
if (objectsArgIndex === -1 || objectsArgIndex + 1 >= args.length) {
|
|
1732
|
+
console.error('Error: --objects parameter required');
|
|
1733
|
+
console.error('Usage: abapgit-agent preview --objects <table1>,<view1>,... [--type <type>] [--limit <n>] [--where <condition>] [--columns <cols>] [--vertical] [--compact] [--json]');
|
|
1734
|
+
console.error('Example: abapgit-agent preview --objects SFLIGHT');
|
|
1735
|
+
console.error('Example: abapgit-agent preview --objects ZC_MY_CDS_VIEW --type DDLS');
|
|
1736
|
+
console.error('Example: abapgit-agent preview --objects SFLIGHT --where "CARRID = \'AA\'"');
|
|
1737
|
+
process.exit(1);
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
const objects = args[objectsArgIndex + 1].split(',').map(o => o.trim().toUpperCase());
|
|
1741
|
+
const typeArg = args.indexOf('--type');
|
|
1742
|
+
const type = typeArg !== -1 ? args[typeArg + 1].toUpperCase() : null;
|
|
1743
|
+
const limitArg = args.indexOf('--limit');
|
|
1744
|
+
const limit = limitArg !== -1 ? parseInt(args[limitArg + 1], 10) : 10;
|
|
1745
|
+
const whereArg = args.indexOf('--where');
|
|
1746
|
+
const where = whereArg !== -1 ? args[whereArg + 1] : null;
|
|
1747
|
+
const columnsArg = args.indexOf('--columns');
|
|
1748
|
+
const columns = columnsArg !== -1 ? args[columnsArg + 1].split(',').map(c => c.trim().toUpperCase()) : null;
|
|
1749
|
+
const verticalOutput = args.includes('--vertical');
|
|
1750
|
+
const compactOutput = args.includes('--compact');
|
|
1751
|
+
const jsonOutput = args.includes('--json');
|
|
1752
|
+
|
|
1753
|
+
console.log(`\n Previewing ${objects.length} object(s)`);
|
|
1754
|
+
|
|
1755
|
+
const config = loadConfig();
|
|
1756
|
+
const csrfToken = await fetchCsrfToken(config);
|
|
1757
|
+
|
|
1758
|
+
const data = {
|
|
1759
|
+
objects: objects,
|
|
1760
|
+
limit: Math.min(Math.max(1, limit), 100)
|
|
1761
|
+
};
|
|
1762
|
+
|
|
1763
|
+
if (type) {
|
|
1764
|
+
data.type = type;
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
if (where) {
|
|
1768
|
+
data.where = where;
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
if (columns) {
|
|
1772
|
+
data.columns = columns;
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
const result = await request('POST', '/sap/bc/z_abapgit_agent/preview', data, { csrfToken });
|
|
1776
|
+
|
|
1777
|
+
// Handle uppercase keys from ABAP
|
|
1778
|
+
const success = result.SUCCESS || result.success;
|
|
1779
|
+
const previewObjects = result.OBJECTS || result.objects || [];
|
|
1780
|
+
const message = result.MESSAGE || result.message || '';
|
|
1781
|
+
const error = result.ERROR || result.error;
|
|
1782
|
+
|
|
1783
|
+
if (!success || error) {
|
|
1784
|
+
console.error(`\n Error: ${error || 'Failed to preview objects'}`);
|
|
1785
|
+
break;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
if (jsonOutput) {
|
|
1789
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1790
|
+
} else {
|
|
1791
|
+
console.log(`\n ${message}`);
|
|
1792
|
+
console.log('');
|
|
1793
|
+
|
|
1794
|
+
// Track if columns were explicitly specified
|
|
1795
|
+
const columnsExplicit = columns !== null;
|
|
1796
|
+
|
|
1797
|
+
for (let i = 0; i < previewObjects.length; i++) {
|
|
1798
|
+
const obj = previewObjects[i];
|
|
1799
|
+
const objName = obj.NAME || obj.name || `Object ${i + 1}`;
|
|
1800
|
+
const objType = obj.TYPE || obj.type || '';
|
|
1801
|
+
const objTypeText = obj.TYPE_TEXT || obj.type_text || '';
|
|
1802
|
+
// Parse rows - could be a JSON string or array
|
|
1803
|
+
let rows = obj.ROWS || obj.rows || [];
|
|
1804
|
+
if (typeof rows === 'string') {
|
|
1805
|
+
try {
|
|
1806
|
+
rows = JSON.parse(rows);
|
|
1807
|
+
} catch (e) {
|
|
1808
|
+
rows = [];
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
const fields = obj.FIELDS || obj.fields || [];
|
|
1812
|
+
const rowCount = obj.ROW_COUNT || obj.row_count || 0;
|
|
1813
|
+
const totalRows = obj.TOTAL_ROWS || obj.total_rows || 0;
|
|
1814
|
+
const notFound = obj.NOT_FOUND || obj.not_found || false;
|
|
1815
|
+
const accessDenied = obj.ACCESS_DENIED || obj.access_denied || false;
|
|
1816
|
+
|
|
1817
|
+
// Check if object was not found
|
|
1818
|
+
if (notFound) {
|
|
1819
|
+
console.log(` ❌ ${objName} (${objTypeText})`);
|
|
1820
|
+
console.log(` Object not found: ${objName}`);
|
|
1821
|
+
continue;
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
// Check if access denied
|
|
1825
|
+
if (accessDenied) {
|
|
1826
|
+
console.log(` ❌ ${objName} (${objTypeText})`);
|
|
1827
|
+
console.log(` Access denied to: ${objName}`);
|
|
1828
|
+
continue;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
console.log(` 📊 Preview: ${objName} (${objTypeText})`);
|
|
1832
|
+
|
|
1833
|
+
// Check for errors first
|
|
1834
|
+
const objError = obj.ERROR || obj.error;
|
|
1835
|
+
if (objError) {
|
|
1836
|
+
console.log(` ❌ Error: ${objError}`);
|
|
1837
|
+
continue;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
if (rows.length === 0) {
|
|
1841
|
+
console.log(' No data found');
|
|
1842
|
+
continue;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
// Get all unique field names from all rows
|
|
1846
|
+
const allFields = new Set();
|
|
1847
|
+
rows.forEach(row => {
|
|
1848
|
+
Object.keys(row).forEach(key => allFields.add(key));
|
|
1849
|
+
});
|
|
1850
|
+
const allFieldNames = Array.from(allFields);
|
|
1851
|
+
|
|
1852
|
+
// Display as table - use fields metadata only if --columns was explicitly specified
|
|
1853
|
+
let fieldNames;
|
|
1854
|
+
let columnsAutoSelected = false;
|
|
1855
|
+
if (columnsExplicit && fields && fields.length > 0) {
|
|
1856
|
+
// Use fields from metadata (filtered by explicit --columns)
|
|
1857
|
+
fieldNames = fields.map(f => f.FIELD || f.field);
|
|
1858
|
+
} else {
|
|
1859
|
+
// Use all fields - let terminal handle wrapping if needed
|
|
1860
|
+
// Terminal width detection is unreliable without a proper TTY
|
|
1861
|
+
fieldNames = allFieldNames;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
// Calculate column widths - use reasonable defaults
|
|
1865
|
+
const colWidths = {};
|
|
1866
|
+
const maxColWidth = compactOutput ? 10 : 20;
|
|
1867
|
+
fieldNames.forEach(field => {
|
|
1868
|
+
let maxWidth = field.length;
|
|
1869
|
+
rows.forEach(row => {
|
|
1870
|
+
const value = String(row[field] || '');
|
|
1871
|
+
maxWidth = Math.max(maxWidth, value.length);
|
|
1872
|
+
});
|
|
1873
|
+
// Cap at maxColWidth (truncates both headers and data in compact mode)
|
|
1874
|
+
colWidths[field] = Math.min(maxWidth, maxColWidth);
|
|
1875
|
+
});
|
|
1876
|
+
|
|
1877
|
+
// Render output - either vertical or table
|
|
1878
|
+
if (verticalOutput) {
|
|
1879
|
+
// Vertical format: each field on its own line
|
|
1880
|
+
rows.forEach((row, rowIndex) => {
|
|
1881
|
+
if (rows.length > 1) {
|
|
1882
|
+
console.log(`\n Row ${rowIndex + 1}:`);
|
|
1883
|
+
console.log(' ' + '─'.repeat(30));
|
|
1884
|
+
}
|
|
1885
|
+
fieldNames.forEach(field => {
|
|
1886
|
+
const value = String(row[field] || '');
|
|
1887
|
+
console.log(` ${field}: ${value}`);
|
|
1888
|
+
});
|
|
1889
|
+
});
|
|
1890
|
+
console.log('');
|
|
1891
|
+
continue;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
// Build table header
|
|
1895
|
+
let headerLine = ' ┌';
|
|
1896
|
+
let separatorLine = ' ├';
|
|
1897
|
+
fieldNames.forEach(field => {
|
|
1898
|
+
const width = colWidths[field];
|
|
1899
|
+
headerLine += '─'.repeat(width + 2) + '┬';
|
|
1900
|
+
separatorLine += '─'.repeat(width + 2) + '┼';
|
|
1901
|
+
});
|
|
1902
|
+
headerLine = headerLine.slice(0, -1) + '┐';
|
|
1903
|
+
separatorLine = separatorLine.slice(0, -1) + '┤';
|
|
1904
|
+
|
|
1905
|
+
// Build header row
|
|
1906
|
+
let headerRow = ' │';
|
|
1907
|
+
fieldNames.forEach(field => {
|
|
1908
|
+
const width = colWidths[field];
|
|
1909
|
+
let displayField = String(field);
|
|
1910
|
+
if (displayField.length > width) {
|
|
1911
|
+
displayField = displayField.slice(0, width - 3) + '...';
|
|
1912
|
+
}
|
|
1913
|
+
headerRow += ' ' + displayField.padEnd(width) + ' │';
|
|
1914
|
+
});
|
|
1915
|
+
|
|
1916
|
+
console.log(headerLine);
|
|
1917
|
+
console.log(headerRow);
|
|
1918
|
+
console.log(separatorLine);
|
|
1919
|
+
|
|
1920
|
+
// Build data rows
|
|
1921
|
+
rows.forEach(row => {
|
|
1922
|
+
let dataRow = ' │';
|
|
1923
|
+
fieldNames.forEach(field => {
|
|
1924
|
+
const width = colWidths[field];
|
|
1925
|
+
const value = String(row[field] || '');
|
|
1926
|
+
const displayValue = value.length > width ? value.slice(0, width - 3) + '...' : value;
|
|
1927
|
+
dataRow += ' ' + displayValue.padEnd(width) + ' │';
|
|
1928
|
+
});
|
|
1929
|
+
console.log(dataRow);
|
|
1930
|
+
});
|
|
1931
|
+
|
|
1932
|
+
// Build bottom border
|
|
1933
|
+
let bottomLine = ' └';
|
|
1934
|
+
fieldNames.forEach(field => {
|
|
1935
|
+
const width = colWidths[field];
|
|
1936
|
+
bottomLine += '─'.repeat(width + 2) + '┴';
|
|
1937
|
+
});
|
|
1938
|
+
bottomLine = bottomLine.slice(0, -1) + '┘';
|
|
1939
|
+
console.log(bottomLine);
|
|
1940
|
+
|
|
1941
|
+
// Show row count
|
|
1942
|
+
if (totalRows > rowCount) {
|
|
1943
|
+
console.log(`\n Showing ${rowCount} of ${totalRows} rows`);
|
|
1944
|
+
} else {
|
|
1945
|
+
console.log(`\n ${rowCount} row(s)`);
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// Note about hidden columns only when --columns was explicitly specified
|
|
1949
|
+
const columnsDisplayed = fieldNames.length;
|
|
1950
|
+
let columnsHidden = [];
|
|
1951
|
+
|
|
1952
|
+
if (columnsExplicit) {
|
|
1953
|
+
columnsHidden = obj.COLUMNS_HIDDEN || obj.columns_hidden || [];
|
|
1954
|
+
if (columnsHidden.length > 0) {
|
|
1955
|
+
console.log(`\n ⚠️ ${columnsHidden.length} more columns hidden (${columnsHidden.join(', ')})`);
|
|
1956
|
+
console.log(' Use --json for full data');
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
console.log('');
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
break;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1729
1966
|
case 'help':
|
|
1730
1967
|
case '--help':
|
|
1731
1968
|
case '-h':
|
package/docs/commands.md
CHANGED
|
@@ -14,6 +14,7 @@ All available CLI commands for abapGit Agent.
|
|
|
14
14
|
| [tree](tree-command.md) | ✅ | Display package hierarchy tree |
|
|
15
15
|
| [unit](unit-command.md) | ✅ | Run AUnit tests |
|
|
16
16
|
| [view](view-command.md) | ✅ | View ABAP object source code from system |
|
|
17
|
+
| [preview](preview-command.md) | 🔄 | Preview table/CDS view data |
|
|
17
18
|
| [health](health-command.md) | ✅ | Health check |
|
|
18
19
|
| [status](status-command.md) | ✅ | Status check |
|
|
19
20
|
|
|
@@ -70,6 +71,10 @@ abapgit-agent tree --package $MY_PACKAGE
|
|
|
70
71
|
abapgit-agent view --objects ZCL_MY_CLASS
|
|
71
72
|
abapgit-agent view --objects SFLIGHT --type TABL
|
|
72
73
|
|
|
74
|
+
# Preview table/CDS view data
|
|
75
|
+
abapgit-agent preview --objects SFLIGHT
|
|
76
|
+
abapgit-agent preview --objects ZC_MY_CDS_VIEW --type DDLS
|
|
77
|
+
|
|
73
78
|
# Check configuration
|
|
74
79
|
abapgit-agent status
|
|
75
80
|
|