@mcp-abap-adt/auth-stores 0.1.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/CHANGELOG.md +45 -0
- package/LICENSE +22 -0
- package/README.md +209 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +53 -0
- package/dist/loaders/abap/serviceKeyLoader.d.ts +15 -0
- package/dist/loaders/abap/serviceKeyLoader.js +84 -0
- package/dist/loaders/xsuaa/xsuaaServiceKeyLoader.d.ts +19 -0
- package/dist/loaders/xsuaa/xsuaaServiceKeyLoader.js +80 -0
- package/dist/parsers/abap/AbapServiceKeyParser.d.ts +35 -0
- package/dist/parsers/abap/AbapServiceKeyParser.js +50 -0
- package/dist/parsers/xsuaa/XsuaaServiceKeyParser.d.ts +30 -0
- package/dist/parsers/xsuaa/XsuaaServiceKeyParser.js +72 -0
- package/dist/storage/abap/envLoader.d.ts +21 -0
- package/dist/storage/abap/envLoader.js +94 -0
- package/dist/storage/abap/tokenStorage.d.ts +24 -0
- package/dist/storage/abap/tokenStorage.js +113 -0
- package/dist/storage/xsuaa/xsuaaEnvLoader.d.ts +20 -0
- package/dist/storage/xsuaa/xsuaaEnvLoader.js +91 -0
- package/dist/storage/xsuaa/xsuaaTokenStorage.d.ts +19 -0
- package/dist/storage/xsuaa/xsuaaTokenStorage.js +115 -0
- package/dist/stores/abap/AbapServiceKeyStore.d.ts +34 -0
- package/dist/stores/abap/AbapServiceKeyStore.js +43 -0
- package/dist/stores/abap/AbapSessionStore.d.ts +80 -0
- package/dist/stores/abap/AbapSessionStore.js +239 -0
- package/dist/stores/abap/SafeAbapSessionStore.d.ts +35 -0
- package/dist/stores/abap/SafeAbapSessionStore.js +117 -0
- package/dist/stores/abstract/AbstractJsonSessionStore.d.ts +67 -0
- package/dist/stores/abstract/AbstractJsonSessionStore.js +99 -0
- package/dist/stores/abstract/AbstractSafeSessionStore.d.ts +89 -0
- package/dist/stores/abstract/AbstractSafeSessionStore.js +76 -0
- package/dist/stores/abstract/AbstractServiceKeyStore.d.ts +66 -0
- package/dist/stores/abstract/AbstractServiceKeyStore.js +165 -0
- package/dist/stores/btp/BtpServiceKeyStore.d.ts +34 -0
- package/dist/stores/btp/BtpServiceKeyStore.js +43 -0
- package/dist/stores/btp/BtpSessionStore.d.ts +79 -0
- package/dist/stores/btp/BtpSessionStore.js +247 -0
- package/dist/stores/btp/SafeBtpSessionStore.d.ts +32 -0
- package/dist/stores/btp/SafeBtpSessionStore.js +115 -0
- package/dist/stores/xsuaa/SafeXsuaaSessionStore.d.ts +34 -0
- package/dist/stores/xsuaa/SafeXsuaaSessionStore.js +117 -0
- package/dist/stores/xsuaa/XsuaaServiceKeyStore.d.ts +36 -0
- package/dist/stores/xsuaa/XsuaaServiceKeyStore.js +49 -0
- package/dist/stores/xsuaa/XsuaaSessionStore.d.ts +54 -0
- package/dist/stores/xsuaa/XsuaaSessionStore.js +223 -0
- package/dist/utils/constants.d.ts +83 -0
- package/dist/utils/constants.js +86 -0
- package/dist/utils/pathResolver.d.ts +20 -0
- package/dist/utils/pathResolver.js +105 -0
- package/package.json +63 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* XSUAA Service Key Parser
|
|
4
|
+
*
|
|
5
|
+
* Parses direct XSUAA service key format from BTP (without nested uaa object):
|
|
6
|
+
* {
|
|
7
|
+
* "url": "https://...authentication...hana.ondemand.com",
|
|
8
|
+
* "clientid": "...",
|
|
9
|
+
* "clientsecret": "...",
|
|
10
|
+
* "tenantmode": "shared",
|
|
11
|
+
* ...
|
|
12
|
+
* }
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.XsuaaServiceKeyParser = void 0;
|
|
16
|
+
/**
|
|
17
|
+
* Parser for direct XSUAA service key format from BTP
|
|
18
|
+
*/
|
|
19
|
+
class XsuaaServiceKeyParser {
|
|
20
|
+
/**
|
|
21
|
+
* Check if this parser can handle the given raw service key data
|
|
22
|
+
* @param rawData Raw JSON data from service key file
|
|
23
|
+
* @returns true if data has direct XSUAA fields (url, clientid, clientsecret) without nested uaa object
|
|
24
|
+
*/
|
|
25
|
+
canParse(rawData) {
|
|
26
|
+
if (!rawData || typeof rawData !== 'object' || Array.isArray(rawData)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
// Check for nested uaa object (ABAP format) - should not have it
|
|
30
|
+
if (rawData.uaa) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
// Check for required XSUAA fields at root level
|
|
34
|
+
return (typeof rawData.url === 'string' &&
|
|
35
|
+
typeof rawData.clientid === 'string' &&
|
|
36
|
+
typeof rawData.clientsecret === 'string' &&
|
|
37
|
+
rawData.url.length > 0 &&
|
|
38
|
+
rawData.clientid.length > 0 &&
|
|
39
|
+
rawData.clientsecret.length > 0);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parse raw service key data
|
|
43
|
+
* @param rawData Raw JSON data from service key file
|
|
44
|
+
* @returns Parsed service key object (normalized format)
|
|
45
|
+
* @throws Error if data cannot be parsed or is invalid
|
|
46
|
+
*/
|
|
47
|
+
parse(rawData) {
|
|
48
|
+
if (!this.canParse(rawData)) {
|
|
49
|
+
throw new Error('Service key does not match XSUAA format (missing url, clientid, or clientsecret at root level)');
|
|
50
|
+
}
|
|
51
|
+
// Normalize to standard format
|
|
52
|
+
// Prioritize apiurl over url for UAA authorization (if present)
|
|
53
|
+
const uaaUrl = rawData.apiurl || rawData.url;
|
|
54
|
+
return {
|
|
55
|
+
uaa: {
|
|
56
|
+
url: uaaUrl,
|
|
57
|
+
clientid: rawData.clientid,
|
|
58
|
+
clientsecret: rawData.clientsecret,
|
|
59
|
+
},
|
|
60
|
+
// Preserve abap.url if present
|
|
61
|
+
abap: rawData.abap,
|
|
62
|
+
// Preserve other optional fields
|
|
63
|
+
url: rawData.url, // UAA URL
|
|
64
|
+
apiurl: rawData.apiurl, // API URL (prioritized for UAA)
|
|
65
|
+
sap_url: rawData.sap_url,
|
|
66
|
+
client: rawData.client,
|
|
67
|
+
sap_client: rawData.sap_client,
|
|
68
|
+
language: rawData.language,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.XsuaaServiceKeyParser = XsuaaServiceKeyParser;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment file loader - loads .env files by destination name for ABAP
|
|
3
|
+
*/
|
|
4
|
+
interface EnvConfig {
|
|
5
|
+
sapUrl: string;
|
|
6
|
+
sapClient?: string;
|
|
7
|
+
jwtToken: string;
|
|
8
|
+
refreshToken?: string;
|
|
9
|
+
uaaUrl?: string;
|
|
10
|
+
uaaClientId?: string;
|
|
11
|
+
uaaClientSecret?: string;
|
|
12
|
+
language?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Load environment configuration from {destination}.env file
|
|
16
|
+
* @param destination Destination name
|
|
17
|
+
* @param searchPaths Array of paths to search for the file
|
|
18
|
+
* @returns EnvConfig object or null if file not found
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadEnvFile(destination: string, searchPaths: string[]): Promise<EnvConfig | null>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Environment file loader - loads .env files by destination name for ABAP
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.loadEnvFile = loadEnvFile;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const dotenv = __importStar(require("dotenv"));
|
|
42
|
+
const pathResolver_1 = require("../../utils/pathResolver");
|
|
43
|
+
const constants_1 = require("../../utils/constants");
|
|
44
|
+
/**
|
|
45
|
+
* Load environment configuration from {destination}.env file
|
|
46
|
+
* @param destination Destination name
|
|
47
|
+
* @param searchPaths Array of paths to search for the file
|
|
48
|
+
* @returns EnvConfig object or null if file not found
|
|
49
|
+
*/
|
|
50
|
+
async function loadEnvFile(destination, searchPaths) {
|
|
51
|
+
const fileName = `${destination}.env`;
|
|
52
|
+
const envFilePath = (0, pathResolver_1.findFileInPaths)(fileName, searchPaths);
|
|
53
|
+
if (!envFilePath) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
// Read and parse .env file
|
|
58
|
+
const envContent = fs.readFileSync(envFilePath, 'utf8');
|
|
59
|
+
const parsed = dotenv.parse(envContent);
|
|
60
|
+
// Extract required fields
|
|
61
|
+
const sapUrl = parsed[constants_1.ABAP_CONNECTION_VARS.SERVICE_URL];
|
|
62
|
+
const jwtToken = parsed[constants_1.ABAP_CONNECTION_VARS.AUTHORIZATION_TOKEN];
|
|
63
|
+
if (!sapUrl || !jwtToken) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const config = {
|
|
67
|
+
sapUrl: sapUrl.trim(),
|
|
68
|
+
jwtToken: jwtToken.trim(),
|
|
69
|
+
};
|
|
70
|
+
// Optional fields
|
|
71
|
+
if (parsed[constants_1.ABAP_CONNECTION_VARS.SAP_CLIENT]) {
|
|
72
|
+
config.sapClient = parsed[constants_1.ABAP_CONNECTION_VARS.SAP_CLIENT].trim();
|
|
73
|
+
}
|
|
74
|
+
if (parsed[constants_1.ABAP_AUTHORIZATION_VARS.REFRESH_TOKEN]) {
|
|
75
|
+
config.refreshToken = parsed[constants_1.ABAP_AUTHORIZATION_VARS.REFRESH_TOKEN].trim();
|
|
76
|
+
}
|
|
77
|
+
if (parsed[constants_1.ABAP_AUTHORIZATION_VARS.UAA_URL]) {
|
|
78
|
+
config.uaaUrl = parsed[constants_1.ABAP_AUTHORIZATION_VARS.UAA_URL].trim();
|
|
79
|
+
}
|
|
80
|
+
if (parsed[constants_1.ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID]) {
|
|
81
|
+
config.uaaClientId = parsed[constants_1.ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID].trim();
|
|
82
|
+
}
|
|
83
|
+
if (parsed[constants_1.ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET]) {
|
|
84
|
+
config.uaaClientSecret = parsed[constants_1.ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET].trim();
|
|
85
|
+
}
|
|
86
|
+
if (parsed[constants_1.ABAP_CONNECTION_VARS.SAP_LANGUAGE]) {
|
|
87
|
+
config.language = parsed[constants_1.ABAP_CONNECTION_VARS.SAP_LANGUAGE].trim();
|
|
88
|
+
}
|
|
89
|
+
return config;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new Error(`Failed to load environment file for destination "${destination}": ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token storage - saves tokens to .env files for ABAP
|
|
3
|
+
*/
|
|
4
|
+
interface EnvConfig {
|
|
5
|
+
sapUrl: string;
|
|
6
|
+
sapClient?: string;
|
|
7
|
+
jwtToken: string;
|
|
8
|
+
refreshToken?: string;
|
|
9
|
+
uaaUrl?: string;
|
|
10
|
+
uaaClientId?: string;
|
|
11
|
+
uaaClientSecret?: string;
|
|
12
|
+
language?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Save token to {destination}.env file
|
|
16
|
+
* @param destination Destination name
|
|
17
|
+
* @param savePath Path where to save the file
|
|
18
|
+
* @param config Configuration to save
|
|
19
|
+
*/
|
|
20
|
+
export declare function saveTokenToEnv(destination: string, savePath: string, config: Partial<EnvConfig> & {
|
|
21
|
+
sapUrl?: string;
|
|
22
|
+
jwtToken: string;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Token storage - saves tokens to .env files for ABAP
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.saveTokenToEnv = saveTokenToEnv;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const constants_1 = require("../../utils/constants");
|
|
43
|
+
/**
|
|
44
|
+
* Save token to {destination}.env file
|
|
45
|
+
* @param destination Destination name
|
|
46
|
+
* @param savePath Path where to save the file
|
|
47
|
+
* @param config Configuration to save
|
|
48
|
+
*/
|
|
49
|
+
async function saveTokenToEnv(destination, savePath, config) {
|
|
50
|
+
// Ensure directory exists
|
|
51
|
+
if (!fs.existsSync(savePath)) {
|
|
52
|
+
fs.mkdirSync(savePath, { recursive: true });
|
|
53
|
+
}
|
|
54
|
+
const envFilePath = path.join(savePath, `${destination}.env`);
|
|
55
|
+
const tempFilePath = `${envFilePath}.tmp`;
|
|
56
|
+
// Read existing .env file if it exists
|
|
57
|
+
let existingContent = '';
|
|
58
|
+
if (fs.existsSync(envFilePath)) {
|
|
59
|
+
existingContent = fs.readFileSync(envFilePath, 'utf8');
|
|
60
|
+
}
|
|
61
|
+
// Parse existing content to preserve other values
|
|
62
|
+
const lines = existingContent.split('\n');
|
|
63
|
+
const existingVars = new Map();
|
|
64
|
+
for (const line of lines) {
|
|
65
|
+
const trimmed = line.trim();
|
|
66
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const match = trimmed.match(/^([^=]+)=(.*)$/);
|
|
70
|
+
if (match) {
|
|
71
|
+
const key = match[1].trim();
|
|
72
|
+
const value = match[2].trim().replace(/^["']|["']$/g, ''); // Remove quotes
|
|
73
|
+
existingVars.set(key, value);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Update with new values
|
|
77
|
+
if (config.sapUrl) {
|
|
78
|
+
existingVars.set(constants_1.ABAP_CONNECTION_VARS.SERVICE_URL, config.sapUrl);
|
|
79
|
+
}
|
|
80
|
+
existingVars.set(constants_1.ABAP_CONNECTION_VARS.AUTHORIZATION_TOKEN, config.jwtToken);
|
|
81
|
+
if (config.sapClient) {
|
|
82
|
+
existingVars.set(constants_1.ABAP_CONNECTION_VARS.SAP_CLIENT, config.sapClient);
|
|
83
|
+
}
|
|
84
|
+
if (config.language) {
|
|
85
|
+
existingVars.set(constants_1.ABAP_CONNECTION_VARS.SAP_LANGUAGE, config.language);
|
|
86
|
+
}
|
|
87
|
+
if (config.refreshToken) {
|
|
88
|
+
existingVars.set(constants_1.ABAP_AUTHORIZATION_VARS.REFRESH_TOKEN, config.refreshToken);
|
|
89
|
+
}
|
|
90
|
+
if (config.uaaUrl) {
|
|
91
|
+
existingVars.set(constants_1.ABAP_AUTHORIZATION_VARS.UAA_URL, config.uaaUrl);
|
|
92
|
+
}
|
|
93
|
+
if (config.uaaClientId) {
|
|
94
|
+
existingVars.set(constants_1.ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID, config.uaaClientId);
|
|
95
|
+
}
|
|
96
|
+
if (config.uaaClientSecret) {
|
|
97
|
+
existingVars.set(constants_1.ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET, config.uaaClientSecret);
|
|
98
|
+
}
|
|
99
|
+
// Write to temporary file first (atomic write)
|
|
100
|
+
const envLines = [];
|
|
101
|
+
for (const [key, value] of existingVars.entries()) {
|
|
102
|
+
// Escape value if it contains spaces or special characters
|
|
103
|
+
const escapedValue = value.includes(' ') || value.includes('=') || value.includes('#')
|
|
104
|
+
? `"${value.replace(/"/g, '\\"')}"`
|
|
105
|
+
: value;
|
|
106
|
+
envLines.push(`${key}=${escapedValue}`);
|
|
107
|
+
}
|
|
108
|
+
const envContent = envLines.join('\n') + '\n';
|
|
109
|
+
// Write to temp file
|
|
110
|
+
fs.writeFileSync(tempFilePath, envContent, 'utf8');
|
|
111
|
+
// Atomic rename
|
|
112
|
+
fs.renameSync(tempFilePath, envFilePath);
|
|
113
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XSUAA Environment file loader - loads .env files with XSUAA_* variables for XSUAA
|
|
3
|
+
*/
|
|
4
|
+
interface XsuaaSessionConfig {
|
|
5
|
+
mcpUrl?: string;
|
|
6
|
+
jwtToken: string;
|
|
7
|
+
refreshToken?: string;
|
|
8
|
+
uaaUrl?: string;
|
|
9
|
+
uaaClientId?: string;
|
|
10
|
+
uaaClientSecret?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Load XSUAA environment configuration from {destination}.env file
|
|
14
|
+
* Reads XSUAA_* variables instead of SAP_* variables
|
|
15
|
+
* @param destination Destination name
|
|
16
|
+
* @param searchPaths Array of paths to search for the file
|
|
17
|
+
* @returns XsuaaSessionConfig object or null if file not found
|
|
18
|
+
*/
|
|
19
|
+
export declare function loadXsuaaEnvFile(destination: string, searchPaths: string[]): Promise<XsuaaSessionConfig | null>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* XSUAA Environment file loader - loads .env files with XSUAA_* variables for XSUAA
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.loadXsuaaEnvFile = loadXsuaaEnvFile;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const dotenv = __importStar(require("dotenv"));
|
|
42
|
+
const pathResolver_1 = require("../../utils/pathResolver");
|
|
43
|
+
const constants_1 = require("../../utils/constants");
|
|
44
|
+
/**
|
|
45
|
+
* Load XSUAA environment configuration from {destination}.env file
|
|
46
|
+
* Reads XSUAA_* variables instead of SAP_* variables
|
|
47
|
+
* @param destination Destination name
|
|
48
|
+
* @param searchPaths Array of paths to search for the file
|
|
49
|
+
* @returns XsuaaSessionConfig object or null if file not found
|
|
50
|
+
*/
|
|
51
|
+
async function loadXsuaaEnvFile(destination, searchPaths) {
|
|
52
|
+
const fileName = `${destination}.env`;
|
|
53
|
+
const envFilePath = (0, pathResolver_1.findFileInPaths)(fileName, searchPaths);
|
|
54
|
+
if (!envFilePath) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
// Read and parse .env file
|
|
59
|
+
const envContent = fs.readFileSync(envFilePath, 'utf8');
|
|
60
|
+
const parsed = dotenv.parse(envContent);
|
|
61
|
+
// Extract required fields (XSUAA_* variables)
|
|
62
|
+
const jwtToken = parsed[constants_1.XSUAA_CONNECTION_VARS.AUTHORIZATION_TOKEN];
|
|
63
|
+
if (!jwtToken) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const config = {
|
|
67
|
+
jwtToken: jwtToken.trim(),
|
|
68
|
+
};
|
|
69
|
+
// mcpUrl can be loaded from .env file as additional variable (not part of CONNECTION_VARS, but can be stored)
|
|
70
|
+
// URL comes from elsewhere (YAML config, parameter, or request header), but can be stored in .env
|
|
71
|
+
if (parsed['XSUAA_MCP_URL']) {
|
|
72
|
+
config.mcpUrl = parsed['XSUAA_MCP_URL'].trim();
|
|
73
|
+
}
|
|
74
|
+
if (parsed[constants_1.XSUAA_AUTHORIZATION_VARS.REFRESH_TOKEN]) {
|
|
75
|
+
config.refreshToken = parsed[constants_1.XSUAA_AUTHORIZATION_VARS.REFRESH_TOKEN].trim();
|
|
76
|
+
}
|
|
77
|
+
if (parsed[constants_1.XSUAA_AUTHORIZATION_VARS.UAA_URL]) {
|
|
78
|
+
config.uaaUrl = parsed[constants_1.XSUAA_AUTHORIZATION_VARS.UAA_URL].trim();
|
|
79
|
+
}
|
|
80
|
+
if (parsed[constants_1.XSUAA_AUTHORIZATION_VARS.UAA_CLIENT_ID]) {
|
|
81
|
+
config.uaaClientId = parsed[constants_1.XSUAA_AUTHORIZATION_VARS.UAA_CLIENT_ID].trim();
|
|
82
|
+
}
|
|
83
|
+
if (parsed[constants_1.XSUAA_AUTHORIZATION_VARS.UAA_CLIENT_SECRET]) {
|
|
84
|
+
config.uaaClientSecret = parsed[constants_1.XSUAA_AUTHORIZATION_VARS.UAA_CLIENT_SECRET].trim();
|
|
85
|
+
}
|
|
86
|
+
return config;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw new Error(`Failed to load XSUAA environment file for destination "${destination}": ${error instanceof Error ? error.message : String(error)}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XSUAA Token storage - saves tokens to .env files with XSUAA_* variables
|
|
3
|
+
*/
|
|
4
|
+
interface XsuaaSessionConfig {
|
|
5
|
+
mcpUrl?: string;
|
|
6
|
+
jwtToken: string;
|
|
7
|
+
refreshToken?: string;
|
|
8
|
+
uaaUrl?: string;
|
|
9
|
+
uaaClientId?: string;
|
|
10
|
+
uaaClientSecret?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Save XSUAA token to {destination}.env file using XSUAA_* variables
|
|
14
|
+
* @param destination Destination name
|
|
15
|
+
* @param savePath Path where to save the file
|
|
16
|
+
* @param config XSUAA session configuration to save
|
|
17
|
+
*/
|
|
18
|
+
export declare function saveXsuaaTokenToEnv(destination: string, savePath: string, config: XsuaaSessionConfig): Promise<void>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* XSUAA Token storage - saves tokens to .env files with XSUAA_* variables
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.saveXsuaaTokenToEnv = saveXsuaaTokenToEnv;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const constants_1 = require("../../utils/constants");
|
|
43
|
+
/**
|
|
44
|
+
* Save XSUAA token to {destination}.env file using XSUAA_* variables
|
|
45
|
+
* @param destination Destination name
|
|
46
|
+
* @param savePath Path where to save the file
|
|
47
|
+
* @param config XSUAA session configuration to save
|
|
48
|
+
*/
|
|
49
|
+
async function saveXsuaaTokenToEnv(destination, savePath, config) {
|
|
50
|
+
// Ensure directory exists
|
|
51
|
+
if (!fs.existsSync(savePath)) {
|
|
52
|
+
fs.mkdirSync(savePath, { recursive: true });
|
|
53
|
+
}
|
|
54
|
+
const envFilePath = path.join(savePath, `${destination}.env`);
|
|
55
|
+
const tempFilePath = `${envFilePath}.tmp`;
|
|
56
|
+
// Read existing .env file if it exists
|
|
57
|
+
let existingContent = '';
|
|
58
|
+
if (fs.existsSync(envFilePath)) {
|
|
59
|
+
existingContent = fs.readFileSync(envFilePath, 'utf8');
|
|
60
|
+
}
|
|
61
|
+
// Parse existing content to preserve other values
|
|
62
|
+
// Remove old SAP_* variables for XSUAA (use XSUAA_* instead)
|
|
63
|
+
const lines = existingContent.split('\n');
|
|
64
|
+
const existingVars = new Map();
|
|
65
|
+
for (const line of lines) {
|
|
66
|
+
const trimmed = line.trim();
|
|
67
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const match = trimmed.match(/^([^=]+)=(.*)$/);
|
|
71
|
+
if (match) {
|
|
72
|
+
const key = match[1].trim();
|
|
73
|
+
// Skip old SAP_* variables for XSUAA (we use XSUAA_* now)
|
|
74
|
+
if (key.startsWith('SAP_') && (key === 'SAP_URL' || key === 'SAP_JWT_TOKEN' || key === 'SAP_REFRESH_TOKEN' ||
|
|
75
|
+
key === 'SAP_UAA_URL' || key === 'SAP_UAA_CLIENT_ID' || key === 'SAP_UAA_CLIENT_SECRET')) {
|
|
76
|
+
continue; // Don't preserve old SAP_* variables
|
|
77
|
+
}
|
|
78
|
+
const value = match[2].trim().replace(/^["']|["']$/g, ''); // Remove quotes
|
|
79
|
+
existingVars.set(key, value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Update with new values (XSUAA_* variables)
|
|
83
|
+
// mcpUrl can be saved as additional variable (not part of CONNECTION_VARS, but can be stored for convenience)
|
|
84
|
+
// URL comes from elsewhere (YAML config, parameter, or request header), but can be stored in .env
|
|
85
|
+
if (config.mcpUrl) {
|
|
86
|
+
existingVars.set('XSUAA_MCP_URL', config.mcpUrl); // Store as additional variable (not in CONNECTION_VARS)
|
|
87
|
+
}
|
|
88
|
+
existingVars.set(constants_1.XSUAA_CONNECTION_VARS.AUTHORIZATION_TOKEN, config.jwtToken);
|
|
89
|
+
if (config.refreshToken) {
|
|
90
|
+
existingVars.set(constants_1.XSUAA_AUTHORIZATION_VARS.REFRESH_TOKEN, config.refreshToken);
|
|
91
|
+
}
|
|
92
|
+
if (config.uaaUrl) {
|
|
93
|
+
existingVars.set(constants_1.XSUAA_AUTHORIZATION_VARS.UAA_URL, config.uaaUrl);
|
|
94
|
+
}
|
|
95
|
+
if (config.uaaClientId) {
|
|
96
|
+
existingVars.set(constants_1.XSUAA_AUTHORIZATION_VARS.UAA_CLIENT_ID, config.uaaClientId);
|
|
97
|
+
}
|
|
98
|
+
if (config.uaaClientSecret) {
|
|
99
|
+
existingVars.set(constants_1.XSUAA_AUTHORIZATION_VARS.UAA_CLIENT_SECRET, config.uaaClientSecret);
|
|
100
|
+
}
|
|
101
|
+
// Write to temporary file first (atomic write)
|
|
102
|
+
const envLines = [];
|
|
103
|
+
for (const [key, value] of existingVars.entries()) {
|
|
104
|
+
// Escape value if it contains spaces or special characters
|
|
105
|
+
const escapedValue = value.includes(' ') || value.includes('=') || value.includes('#')
|
|
106
|
+
? `"${value.replace(/"/g, '\\"')}"`
|
|
107
|
+
: value;
|
|
108
|
+
envLines.push(`${key}=${escapedValue}`);
|
|
109
|
+
}
|
|
110
|
+
const envContent = envLines.join('\n') + '\n';
|
|
111
|
+
// Write to temp file
|
|
112
|
+
fs.writeFileSync(tempFilePath, envContent, 'utf8');
|
|
113
|
+
// Atomic rename
|
|
114
|
+
fs.renameSync(tempFilePath, envFilePath);
|
|
115
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ABAP Service key store - reads ABAP service keys from {destination}.json files
|
|
3
|
+
*
|
|
4
|
+
* Uses AbstractServiceKeyStore for file I/O and AbapServiceKeyParser for parsing.
|
|
5
|
+
* This extends base BTP by supporting ABAP service key format with nested uaa object.
|
|
6
|
+
*/
|
|
7
|
+
import type { IServiceKeyStore } from '@mcp-abap-adt/auth-broker';
|
|
8
|
+
import { AbstractServiceKeyStore } from '../abstract/AbstractServiceKeyStore';
|
|
9
|
+
/**
|
|
10
|
+
* ABAP Service key store implementation
|
|
11
|
+
*
|
|
12
|
+
* Uses AbstractServiceKeyStore for file operations and AbapServiceKeyParser for parsing.
|
|
13
|
+
* Search paths priority:
|
|
14
|
+
* 1. Constructor parameter (highest)
|
|
15
|
+
* 2. AUTH_BROKER_PATH environment variable
|
|
16
|
+
* 3. Current working directory (lowest)
|
|
17
|
+
*/
|
|
18
|
+
export declare class AbapServiceKeyStore extends AbstractServiceKeyStore implements IServiceKeyStore {
|
|
19
|
+
private parser;
|
|
20
|
+
/**
|
|
21
|
+
* Create a new AbapServiceKeyStore instance
|
|
22
|
+
* @param searchPaths Optional search paths for .json files.
|
|
23
|
+
* Can be a single path (string) or array of paths.
|
|
24
|
+
* If not provided, uses AUTH_BROKER_PATH env var or current working directory.
|
|
25
|
+
*/
|
|
26
|
+
constructor(searchPaths?: string | string[]);
|
|
27
|
+
/**
|
|
28
|
+
* Parse raw JSON data using AbapServiceKeyParser
|
|
29
|
+
* @param rawData Raw JSON data from service key file
|
|
30
|
+
* @returns Parsed service key object
|
|
31
|
+
* @throws Error if data cannot be parsed or is invalid
|
|
32
|
+
*/
|
|
33
|
+
protected parse(rawData: any): unknown;
|
|
34
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ABAP Service key store - reads ABAP service keys from {destination}.json files
|
|
4
|
+
*
|
|
5
|
+
* Uses AbstractServiceKeyStore for file I/O and AbapServiceKeyParser for parsing.
|
|
6
|
+
* This extends base BTP by supporting ABAP service key format with nested uaa object.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AbapServiceKeyStore = void 0;
|
|
10
|
+
const AbstractServiceKeyStore_1 = require("../abstract/AbstractServiceKeyStore");
|
|
11
|
+
const AbapServiceKeyParser_1 = require("../../parsers/abap/AbapServiceKeyParser");
|
|
12
|
+
/**
|
|
13
|
+
* ABAP Service key store implementation
|
|
14
|
+
*
|
|
15
|
+
* Uses AbstractServiceKeyStore for file operations and AbapServiceKeyParser for parsing.
|
|
16
|
+
* Search paths priority:
|
|
17
|
+
* 1. Constructor parameter (highest)
|
|
18
|
+
* 2. AUTH_BROKER_PATH environment variable
|
|
19
|
+
* 3. Current working directory (lowest)
|
|
20
|
+
*/
|
|
21
|
+
class AbapServiceKeyStore extends AbstractServiceKeyStore_1.AbstractServiceKeyStore {
|
|
22
|
+
parser;
|
|
23
|
+
/**
|
|
24
|
+
* Create a new AbapServiceKeyStore instance
|
|
25
|
+
* @param searchPaths Optional search paths for .json files.
|
|
26
|
+
* Can be a single path (string) or array of paths.
|
|
27
|
+
* If not provided, uses AUTH_BROKER_PATH env var or current working directory.
|
|
28
|
+
*/
|
|
29
|
+
constructor(searchPaths) {
|
|
30
|
+
super(searchPaths);
|
|
31
|
+
this.parser = new AbapServiceKeyParser_1.AbapServiceKeyParser();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse raw JSON data using AbapServiceKeyParser
|
|
35
|
+
* @param rawData Raw JSON data from service key file
|
|
36
|
+
* @returns Parsed service key object
|
|
37
|
+
* @throws Error if data cannot be parsed or is invalid
|
|
38
|
+
*/
|
|
39
|
+
parse(rawData) {
|
|
40
|
+
return this.parser.parse(rawData);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.AbapServiceKeyStore = AbapServiceKeyStore;
|