abap-local-client 1.1.1 → 1.3.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.
@@ -82,9 +82,26 @@ function dpapiDecrypt(base64Text) {
82
82
 
83
83
  function defaultConfig() {
84
84
  return {
85
- mcpApiKey: '',
85
+ mcpApiKey: 'arc_de2fb7965d536a5911ffd7d9ba39d70c',
86
86
  wsUrl: 'ws://localhost:8080',
87
- systems: {},
87
+ systems: {
88
+ S4D: {
89
+ authMode: 'snc',
90
+ connection: {
91
+ host: 'vhlbvs4dci.sap.piracanjuba.com.br',
92
+ sysnr: '00',
93
+ client: '100',
94
+ username: '',
95
+ saprouter: '',
96
+ sncPartnerName: 'p:CN=svc.ssoS4D',
97
+ sncMyName: '',
98
+ sncQop: '3',
99
+ sncLib: '',
100
+ language: 'PT',
101
+ },
102
+ enabled: true,
103
+ },
104
+ },
88
105
  enableArcanumFallback: false,
89
106
  reconnectDelayMs: 5000,
90
107
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abap-local-client",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "SAP Local Client — WebSocket bridge with Basic, SPNEGO, X.509, SAML & SNC authentication",
5
5
  "main": "sso-sap-client.mjs",
6
6
  "type": "module",
@@ -670,9 +670,49 @@ async function connect() {
670
670
  }
671
671
 
672
672
  // ════════════════════════════════════════════════════════════════════════════
673
- // Start
673
+ // Start — with inline CLI for setup/config when run directly
674
674
  // ════════════════════════════════════════════════════════════════════════════
675
675
 
676
+ const args = process.argv.slice(2);
677
+ const command = args[0];
678
+
679
+ // If the user ran "node sso-sap-client.mjs setup" or "npx abap-local-client config xyz",
680
+ // delegate to the config CLI instead of starting the WebSocket client.
681
+ if (command === 'setup' || command === 'config' || command === 'add-system' || command === 'set-mcp-key' ||
682
+ command === 'list-systems' || command === 'remove-system' || command === 'enable-system' ||
683
+ command === 'disable-system' || command === 'show-config' || command === 'arcanum-fallback' ||
684
+ command === 'set-ws-url' || command === 'help') {
685
+ // Dynamically import the config CLI so it processes the same argv
686
+ await import('./config-cli.mjs');
687
+ process.exit(0);
688
+ }
689
+
690
+ // If no config exists, use built-in default (S4D Piracanjuba SNC + API key)
691
+ if (!config.isConfigInitialized()) {
692
+ console.log('╔═══════════════════════════════════════════════════════════╗');
693
+ console.log('║ SAP Local Client — First Run ║');
694
+ console.log('║ Using default config: S4D (Piracanjuba) via SNC ║');
695
+ console.log('╚═══════════════════════════════════════════════════════════╝');
696
+
697
+ // Save the default config so it persists across restarts
698
+ config.addOrUpdateSystem('S4D', {
699
+ authMode: 'snc',
700
+ connection: {
701
+ host: 'vhlbvs4dci.sap.piracanjuba.com.br',
702
+ sysnr: '00',
703
+ client: '100',
704
+ username: '',
705
+ sncPartnerName: 'p:CN=svc.ssoS4D',
706
+ sncQop: '3',
707
+ language: 'PT',
708
+ },
709
+ enabled: true,
710
+ });
711
+ config.setMcpApiKey('arc_de2fb7965d536a5911ffd7d9ba39d70c');
712
+ console.log(' Config saved. Edit with: node sso-sap-client.mjs help');
713
+ console.log('');
714
+ }
715
+
676
716
  console.log('╔═══════════════════════════════════════════════════════════╗');
677
717
  console.log('║ SAP Local Client — Multi-System SSO Bridge ║');
678
718
  console.log('╚═══════════════════════════════════════════════════════════╝');
package/xml-utils.mjs ADDED
@@ -0,0 +1,60 @@
1
+ import { XMLParser } from 'fast-xml-parser';
2
+
3
+ // Create XML parser instance
4
+ const xmlParser = new XMLParser({
5
+ ignoreAttributes: false,
6
+ attributeNamePrefix: '@_'
7
+ });
8
+
9
+ /**
10
+ * Parse SAP XML response and check for errors
11
+ * Returns: { hasErrors: boolean, errorMessages: string[], parsedData: object }
12
+ */
13
+ export function parseSAPResponse(xmlString) {
14
+ if (typeof xmlString !== 'string' || !xmlString.includes('<?xml')) {
15
+ return { hasErrors: false, errorMessages: [], parsedData: null };
16
+ }
17
+
18
+ try {
19
+ const parsed = xmlParser.parse(xmlString);
20
+
21
+ // Check for syntax check errors (chkrun:checkMessage with type="E")
22
+ if (parsed['chkrun:checkRunReports']) {
23
+ const report = parsed['chkrun:checkRunReports']['chkrun:checkReport'];
24
+ const messageList = report?.['chkrun:checkMessageList'];
25
+
26
+ if (messageList && messageList['chkrun:checkMessage']) {
27
+ const messages = Array.isArray(messageList['chkrun:checkMessage'])
28
+ ? messageList['chkrun:checkMessage']
29
+ : [messageList['chkrun:checkMessage']];
30
+
31
+ const errorMessages = [];
32
+ for (const msg of messages) {
33
+ if (msg['@_chkrun:type'] === 'E') {
34
+ let line = null;
35
+ if (msg['@_chkrun:uri'] && msg['@_chkrun:uri'].includes('#start=')) {
36
+ const match = msg['@_chkrun:uri'].match(/#start=(\d+),(\d+)/);
37
+ if (match) {
38
+ line = parseInt(match[1]);
39
+ }
40
+ }
41
+ const text = msg['@_chkrun:shortText'] || 'Unknown error';
42
+ const lineInfo = line ? ` (line ${line})` : '';
43
+ errorMessages.push(`${text}${lineInfo}`);
44
+ }
45
+ }
46
+
47
+ if (errorMessages.length > 0) {
48
+ return { hasErrors: true, errorMessages, parsedData: parsed };
49
+ }
50
+ }
51
+ }
52
+
53
+ // Add other error patterns here if needed (e.g., activation errors, etc.)
54
+
55
+ return { hasErrors: false, errorMessages: [], parsedData: parsed };
56
+ } catch (error) {
57
+ console.error(' ⚠️ XML parsing failed:', error.message);
58
+ return { hasErrors: false, errorMessages: [], parsedData: null };
59
+ }
60
+ }