@mcp-abap-adt/auth-broker 0.2.13 → 0.2.15

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 CHANGED
@@ -11,6 +11,32 @@ Thank you to all contributors! See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the co
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [0.2.15] - 2025-12-30
15
+
16
+ ### Fixed
17
+ - **CLI**: Remove duplicate `authConfig` declaration in `mcp-auth.ts` that caused esbuild/tsx to fail with "symbol already declared" error
18
+
19
+ ## [0.2.14] - 2025-12-26
20
+
21
+ ### Added
22
+ - **Structured logging**: Added detailed logging throughout `AuthBroker` for better debugging and observability
23
+ - Logs broker initialization with configuration details
24
+ - Logs token retrieval operations with formatted tokens (start...end format)
25
+ - Logs token persistence with expiration dates in readable format
26
+ - Logs session state checks with token and refresh token information
27
+ - Uses `formatToken()` and `formatExpirationDate()` utilities for consistent formatting
28
+ - **Token formatting utilities**: Added `formatExpirationDate()` function to `utils/formatting.ts` for readable date/time formatting (e.g., "2025-12-25 19:21:27 UTC")
29
+ - **Test configuration**: Added `forceExit: true` to `jest.config.js` to prevent test hanging after completion
30
+
31
+ ### Changed
32
+ - **Dependencies**: Updated `@mcp-abap-adt/auth-providers` from `^0.2.8` to `^0.2.10`
33
+ - **Dependencies**: Updated `@mcp-abap-adt/auth-stores` from `^0.2.9` to `^0.2.10`
34
+ - **Logging format**: All token logging now uses formatted tokens (shows first 25 and last 25 characters, skipping middle)
35
+ - **Logging format**: All expiration date logging now uses readable date/time format instead of raw timestamps
36
+
37
+ ### Fixed
38
+ - **Test hanging**: Fixed issue where tests would hang after completion by adding `forceExit: true` to Jest configuration
39
+
14
40
  ## [0.2.13] - 2025-12-26
15
41
 
16
42
  ### Changed
package/README.md CHANGED
@@ -177,10 +177,14 @@ const connection = new JwtAbapConnection(config, tokenRefresher);
177
177
 
178
178
  #### Debugging Variables
179
179
 
180
- - `DEBUG_AUTH_BROKER` - Enable debug logging for `auth-broker` package
180
+ - `DEBUG_BROKER` - Enable debug logging for `auth-broker` package (short name)
181
181
  - Set to `true` to enable logging (default: `false`)
182
182
  - When enabled, logs authentication steps, token operations, and error details
183
183
  - Can be explicitly disabled by setting to `false`
184
+ - Example: `DEBUG_BROKER=true npm test`
185
+
186
+ - `DEBUG_AUTH_BROKER` - Long name (backward compatibility)
187
+ - Same as `DEBUG_BROKER`, but longer name
184
188
  - Example: `DEBUG_AUTH_BROKER=true npm test`
185
189
 
186
190
  - `LOG_LEVEL` - Control log verbosity level
@@ -189,18 +193,48 @@ const connection = new JwtAbapConnection(config, tokenRefresher);
189
193
  - `info` - Informational messages, warnings, and errors
190
194
  - `warn` - Warnings and errors only
191
195
  - `error` - Errors only
192
- - Example: `LOG_LEVEL=debug DEBUG_AUTH_BROKER=true npm test`
196
+ - Example: `LOG_LEVEL=debug DEBUG_BROKER=true npm test`
193
197
 
194
198
  - `DEBUG` - Alternative way to enable debugging
195
199
  - Set to `true` to enable all debug logging
196
- - Or set to a string containing `auth-broker` to enable only this package
197
- - Example: `DEBUG=true npm test` or `DEBUG=auth-broker npm test`
200
+ - Or set to a string containing `broker` or `auth-broker` to enable only this package
201
+ - Example: `DEBUG=true npm test` or `DEBUG=broker npm test` or `DEBUG=auth-broker npm test`
198
202
 
199
203
  **Note**: For debugging related packages:
200
- - `DEBUG_AUTH_STORES` - Enable logging for `@mcp-abap-adt/auth-stores` package
201
- - `DEBUG_AUTH_PROVIDERS` - Enable logging for `@mcp-abap-adt/auth-providers` package
204
+ - `DEBUG_STORES` (short) or `DEBUG_AUTH_STORES` (long) - Enable logging for `@mcp-abap-adt/auth-stores` package
205
+ - `DEBUG_PROVIDER` (short) or `DEBUG_AUTH_PROVIDERS` (long) - Enable logging for `@mcp-abap-adt/auth-providers` package
206
+
207
+ **Legacy Support**: `DEBUG_AUTH_LOG` is still supported for backward compatibility (equivalent to `DEBUG_BROKER=true LOG_LEVEL=debug`)
208
+
209
+ ### Logging Features
210
+
211
+ When logging is enabled (via `DEBUG_BROKER=true` or `DEBUG_AUTH_BROKER=true`), the broker provides detailed structured logging:
212
+
213
+ **What is logged:**
214
+ - **Broker initialization**: Configuration details, stores, token provider, browser settings
215
+ - **Token retrieval**: Session state checks, token presence, refresh token availability
216
+ - **Token operations**: Token requests via provider, received tokens with expiration information
217
+ - **Token persistence**: Saving tokens to session with formatted token values and expiration dates
218
+ - **Error context**: Detailed error information with file paths, error codes, missing fields
219
+
220
+ **Logging Features:**
221
+ - **Token Formatting**: Tokens are logged in truncated format (first 25 and last 25 characters, skipping middle) for security and readability
222
+ - **Date Formatting**: Expiration dates are logged in readable format (e.g., "2025-12-25 19:21:27 UTC") instead of raw timestamps
223
+ - **Structured Logging**: Uses `DefaultLogger` from `@mcp-abap-adt/logger` for proper formatting with icons and level prefixes
224
+ - **Log Levels**: Controlled via `LOG_LEVEL` or `AUTH_LOG_LEVEL` environment variable (error, warn, info, debug)
225
+
226
+ Example output with `DEBUG_BROKER=true LOG_LEVEL=info`:
227
+ ```
228
+ [INFO] ℹ️ [AUTH-BROKER] Broker initialized: hasServiceKeyStore(true), hasSessionStore(true), hasTokenProvider(true), browser(system), allowBrowserAuth(true)
229
+ [INFO] ℹ️ [AUTH-BROKER] Getting token for destination: TRIAL
230
+ [INFO] ℹ️ [AUTH-BROKER] Session check for TRIAL: hasToken(true), hasAuthConfig(true), hasServiceUrl(true), serviceUrl(https://...abap...), authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w), hasRefreshToken(true)
231
+ [INFO] ℹ️ [AUTH-BROKER] Requesting tokens for TRIAL via session
232
+ [INFO] ℹ️ [AUTH-BROKER] Tokens received for TRIAL: authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w), hasRefreshToken(true), authType(authorization_code), expiresIn(43199), expiresAt(2025-12-26 20:15:30 UTC)
233
+ [INFO] ℹ️ [AUTH-BROKER] Saving tokens to session for TRIAL: serviceUrl(https://...abap...), authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w), hasRefreshToken(true), expiresAt(2025-12-26 20:15:30 UTC)
234
+ [INFO] ℹ️ [AUTH-BROKER] Token retrieved for TRIAL (via session): authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w)
235
+ ```
202
236
 
203
- **Legacy Support**: `DEBUG_AUTH_LOG` is still supported for backward compatibility (equivalent to `DEBUG_AUTH_BROKER=true LOG_LEVEL=debug`)
237
+ **Note**: Logging only works when a logger is explicitly provided to the broker constructor. The broker will not output anything to console if no logger is passed.
204
238
 
205
239
  ### File Structure
206
240
 
package/bin/mcp-auth.ts CHANGED
@@ -486,7 +486,6 @@ async function main() {
486
486
  console.log(`✅ Token obtained successfully`);
487
487
 
488
488
  const connConfig = await sessionStore.getConnectionConfig(destination);
489
- const authConfig = await sessionStore.getAuthorizationConfig(destination);
490
489
 
491
490
  if (!token) {
492
491
  throw new Error(
@@ -1 +1 @@
1
- {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EAGrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AA4C7B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,YAAY,EAAE,aAAa,CAAC;IAC5B,uEAAuE;IACvE,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,4IAA4I;IAC5I,aAAa,EAAE,cAAc,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,gBAAgB,CAAU;IAElC;;;;;;;;;;;OAWG;gBACS,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO;IAkFxE;;OAEG;YACW,eAAe;IA0D7B;;OAEG;YACW,aAAa;IAoD3B;;OAEG;YACW,oCAAoC;IA4ClD;;OAEG;YACW,kBAAkB;YAkClB,aAAa;YA8Cb,kBAAkB;IAiChC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsHpD;;;;;OAKG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASxD;;;;OAIG;IACG,sBAAsB,CAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAoEvC;;;;OAIG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IA8DpC;;;;;;;;;;;;;;;;OAgBG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAqB3D"}
1
+ {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EAGrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AA6C7B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,YAAY,EAAE,aAAa,CAAC;IAC5B,uEAAuE;IACvE,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,4IAA4I;IAC5I,aAAa,EAAE,cAAc,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,gBAAgB,CAAU;IAElC;;;;;;;;;;;OAWG;gBACS,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO;IAsFxE;;OAEG;YACW,eAAe;IA0D7B;;OAEG;YACW,aAAa;IAoD3B;;OAEG;YACW,oCAAoC;IA4ClD;;OAEG;YACW,kBAAkB;YAkClB,aAAa;YA0Db,kBAAkB;IAgDhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkJpD;;;;;OAKG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASxD;;;;OAIG;IACG,sBAAsB,CAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAoEvC;;;;OAIG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAgEpC;;;;;;;;;;;;;;;;OAgBG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAqB3D"}
@@ -5,6 +5,7 @@
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.AuthBroker = void 0;
7
7
  const interfaces_1 = require("@mcp-abap-adt/interfaces");
8
+ const formatting_1 = require("./utils/formatting");
8
9
  /**
9
10
  * No-op logger implementation for default fallback when logger is not provided
10
11
  */
@@ -108,7 +109,13 @@ class AuthBroker {
108
109
  this.allowBrowserAuth = config.allowBrowserAuth ?? true;
109
110
  // Log successful initialization
110
111
  const hasServiceKeyStore = !!this.serviceKeyStore;
111
- this.logger?.debug(`AuthBroker initialized: sessionStore(ok), serviceKeyStore(${hasServiceKeyStore ? 'ok' : 'none'}), tokenProvider(ok)`);
112
+ this.logger?.info('[AuthBroker] Broker initialized', {
113
+ hasServiceKeyStore,
114
+ hasSessionStore: true,
115
+ hasTokenProvider: true,
116
+ browser: this.browser,
117
+ allowBrowserAuth: this.allowBrowserAuth,
118
+ });
112
119
  }
113
120
  /**
114
121
  * Load session data (connection and authorization configs)
@@ -246,13 +253,25 @@ class AuthBroker {
246
253
  }
247
254
  }
248
255
  async requestTokens(destination, sourceLabel) {
249
- this.logger?.debug(`Requesting tokens for ${destination} via ${sourceLabel}`);
256
+ this.logger?.info(`[AuthBroker] Requesting tokens for ${destination} via ${sourceLabel}`);
250
257
  try {
251
258
  const getTokens = this.tokenProvider.getTokens;
252
259
  if (!getTokens) {
253
260
  throw new Error('AuthBroker: tokenProvider.getTokens is required');
254
261
  }
255
- return await getTokens.call(this.tokenProvider);
262
+ const tokenResult = await getTokens.call(this.tokenProvider);
263
+ const expiresAt = tokenResult.expiresIn
264
+ ? Date.now() + tokenResult.expiresIn * 1000
265
+ : undefined;
266
+ this.logger?.info(`[AuthBroker] Tokens received for ${destination}`, {
267
+ authorizationToken: (0, formatting_1.formatToken)(tokenResult.authorizationToken),
268
+ hasRefreshToken: !!tokenResult.refreshToken,
269
+ refreshToken: (0, formatting_1.formatToken)(tokenResult.refreshToken),
270
+ authType: tokenResult.authType,
271
+ expiresIn: tokenResult.expiresIn,
272
+ expiresAt: expiresAt ? (0, formatting_1.formatExpirationDate)(expiresAt) : undefined,
273
+ });
274
+ return tokenResult;
256
275
  }
257
276
  catch (error) {
258
277
  if (hasErrorCode(error)) {
@@ -289,6 +308,17 @@ class AuthBroker {
289
308
  ...authConfig,
290
309
  refreshToken: tokenResult.refreshToken ?? authConfig.refreshToken,
291
310
  };
311
+ const expiresAt = tokenResult.expiresIn
312
+ ? Date.now() + tokenResult.expiresIn * 1000
313
+ : undefined;
314
+ this.logger?.info(`[AuthBroker] Saving tokens to session for ${destination}`, {
315
+ serviceUrl,
316
+ authorizationToken: (0, formatting_1.formatToken)(token),
317
+ hasRefreshToken: !!authorizationConfig.refreshToken,
318
+ refreshToken: (0, formatting_1.formatToken)(authorizationConfig.refreshToken),
319
+ expiresIn: tokenResult.expiresIn,
320
+ expiresAt: expiresAt ? (0, formatting_1.formatExpirationDate)(expiresAt) : undefined,
321
+ });
292
322
  await this.saveTokenToSession(destination, connectionConfigWithServiceUrl, authorizationConfig);
293
323
  }
294
324
  /**
@@ -332,7 +362,7 @@ class AuthBroker {
332
362
  * @throws Error if session initialization fails or authentication failed
333
363
  */
334
364
  async getToken(destination) {
335
- this.logger?.debug(`Getting token for destination: ${destination}`);
365
+ this.logger?.info(`[AuthBroker] Getting token for destination: ${destination}`);
336
366
  // Load session data
337
367
  const { connConfig, authConfig } = await this.loadSessionData(destination);
338
368
  // Get serviceUrl (required)
@@ -340,7 +370,15 @@ class AuthBroker {
340
370
  // Check if we have token or UAA credentials
341
371
  const hasToken = !!connConfig?.authorizationToken;
342
372
  const hasAuthConfig = !!authConfig;
343
- this.logger?.debug(`Session check for ${destination}: hasToken(${hasToken}), hasAuthConfig(${hasAuthConfig}), serviceUrl(${serviceUrl ? 'yes' : 'no'})`);
373
+ this.logger?.info(`[AuthBroker] Session check for ${destination}`, {
374
+ hasToken,
375
+ hasAuthConfig,
376
+ hasServiceUrl: !!serviceUrl,
377
+ serviceUrl,
378
+ authorizationToken: (0, formatting_1.formatToken)(connConfig?.authorizationToken),
379
+ hasRefreshToken: !!authConfig?.refreshToken,
380
+ refreshToken: (0, formatting_1.formatToken)(authConfig?.refreshToken),
381
+ });
344
382
  // Step 0: Initialize Session with Token (if needed)
345
383
  if (!hasToken && !hasAuthConfig) {
346
384
  if (!this.allowBrowserAuth) {
@@ -353,6 +391,9 @@ class AuthBroker {
353
391
  const serviceKeyAuthConfig = await this.getAuthorizationConfigFromServiceKey(destination);
354
392
  const tokenResult = await this.requestTokens(destination, 'serviceKey');
355
393
  await this.persistTokenResult(destination, serviceUrl, connConfig, serviceKeyAuthConfig, tokenResult);
394
+ this.logger?.info(`[AuthBroker] Token retrieved for ${destination} (initialized from service key)`, {
395
+ authorizationToken: (0, formatting_1.formatToken)(tokenResult.authorizationToken),
396
+ });
356
397
  return tokenResult.authorizationToken;
357
398
  }
358
399
  // Step 1: Request tokens via provider (provider handles token lifecycle internally)
@@ -371,6 +412,9 @@ class AuthBroker {
371
412
  try {
372
413
  const tokenResult = await this.requestTokens(destination, 'session');
373
414
  await this.persistTokenResult(destination, serviceUrl, connConfig, authConfig, tokenResult);
415
+ this.logger?.info(`[AuthBroker] Token retrieved for ${destination} (via session)`, {
416
+ authorizationToken: (0, formatting_1.formatToken)(tokenResult.authorizationToken),
417
+ });
374
418
  return tokenResult.authorizationToken;
375
419
  }
376
420
  catch (error) {
@@ -394,6 +438,9 @@ class AuthBroker {
394
438
  const serviceKeyAuthConfig = await this.getAuthorizationConfigFromServiceKey(destination);
395
439
  const tokenResult = await this.requestTokens(destination, 'serviceKey');
396
440
  await this.persistTokenResult(destination, serviceUrl, connConfig, serviceKeyAuthConfig, tokenResult);
441
+ this.logger?.info(`[AuthBroker] Token retrieved for ${destination} (fallback to service key)`, {
442
+ authorizationToken: (0, formatting_1.formatToken)(tokenResult.authorizationToken),
443
+ });
397
444
  return tokenResult.authorizationToken;
398
445
  }
399
446
  /**
@@ -481,7 +528,9 @@ class AuthBroker {
481
528
  this.logger?.warn(`Failed to get connection config from session store for ${destination}: ${getErrorMessage(error)}`);
482
529
  }
483
530
  if (sessionConnConfig) {
484
- this.logger?.debug(`Connection config from session for ${destination}: token(${sessionConnConfig.authorizationToken?.length || 0} chars), serviceUrl(${sessionConnConfig.serviceUrl ? 'yes' : 'no'})`);
531
+ const tokenLength = sessionConnConfig.authorizationToken?.length || 0;
532
+ const formattedToken = (0, formatting_1.formatToken)(sessionConnConfig.authorizationToken);
533
+ this.logger?.debug(`Connection config from session for ${destination}: token(${tokenLength} chars${formattedToken ? `, ${formattedToken}` : ''}), serviceUrl(${sessionConnConfig.serviceUrl ? 'yes' : 'no'})`);
485
534
  return sessionConnConfig;
486
535
  }
487
536
  // Fall back to service key store (has URLs but no tokens) if available
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Test logger with environment variable control
3
+ * Uses DefaultLogger from @mcp-abap-adt/logger for proper formatting
3
4
  */
4
5
  import type { ILogger } from '@mcp-abap-adt/interfaces';
5
6
  export declare function createTestLogger(prefix?: string): ILogger;
@@ -1 +1 @@
1
- {"version":3,"file":"testLogger.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/testLogger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAgBxD,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,MAAe,GAAG,OAAO,CAkEjE"}
1
+ {"version":3,"file":"testLogger.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/testLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGxD,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,MAAe,GAAG,OAAO,CAmDjE"}
@@ -1,80 +1,53 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Test logger with environment variable control
4
+ * Uses DefaultLogger from @mcp-abap-adt/logger for proper formatting
4
5
  */
5
6
  Object.defineProperty(exports, "__esModule", { value: true });
6
7
  exports.createTestLogger = createTestLogger;
7
- function getLogLevel() {
8
- const level = process.env.LOG_LEVEL?.toLowerCase() || 'info';
9
- const levels = ['debug', 'info', 'warn', 'error'];
10
- return levels.includes(level) ? level : 'info';
11
- }
12
- function shouldLog(level) {
13
- const currentLevel = getLogLevel();
14
- const levels = ['debug', 'info', 'warn', 'error'];
15
- return levels.indexOf(level) >= levels.indexOf(currentLevel);
16
- }
8
+ const logger_1 = require("@mcp-abap-adt/logger");
17
9
  function createTestLogger(prefix = 'TEST') {
18
10
  // Check if logging is enabled - requires explicit enable
19
11
  const isEnabled = () => {
20
- // Explicitly disabled
21
- if (process.env.DEBUG_AUTH_BROKER === 'false') {
12
+ // Explicitly disabled (support both short and long names)
13
+ if (process.env.DEBUG_BROKER === 'false' ||
14
+ process.env.DEBUG_AUTH_BROKER === 'false') {
22
15
  return false;
23
16
  }
24
- // Explicitly enabled
25
- if (process.env.DEBUG_AUTH_BROKER === 'true' ||
17
+ // Explicitly enabled (support both short and long names)
18
+ if (process.env.DEBUG_BROKER === 'true' ||
19
+ process.env.DEBUG_AUTH_BROKER === 'true' ||
26
20
  process.env.DEBUG === 'true' ||
21
+ process.env.DEBUG?.includes('broker') === true ||
27
22
  process.env.DEBUG?.includes('auth-broker') === true) {
28
23
  return true;
29
24
  }
30
25
  // Do not enable by default - require explicit enable
31
26
  return false;
32
27
  };
33
- // Format message and meta into single line
34
- const formatMessage = (message, meta) => {
35
- if (!meta || meta === '') {
36
- return message;
37
- }
38
- // If meta is an object, format it concisely
39
- if (typeof meta === 'object' && !Array.isArray(meta)) {
40
- const parts = [];
41
- for (const [key, value] of Object.entries(meta)) {
42
- if (value !== undefined && value !== null) {
43
- if (typeof value === 'string' && value.length > 50) {
44
- parts.push(`${key}(${value.substring(0, 50)}...)`);
45
- }
46
- else if (typeof value === 'boolean') {
47
- parts.push(`${key}(${value})`);
48
- }
49
- else {
50
- parts.push(`${key}(${value})`);
51
- }
52
- }
53
- }
54
- return parts.length > 0 ? `${message} ${parts.join(', ')}` : message;
55
- }
56
- // If meta is a string or other type, append it
57
- return `${message} ${String(meta)}`;
58
- };
28
+ // Create DefaultLogger with appropriate log level
29
+ // getLogLevel respects AUTH_LOG_LEVEL env var and defaults to INFO
30
+ const baseLogger = new logger_1.DefaultLogger((0, logger_1.getLogLevel)());
31
+ // Return wrapper that checks if logging is enabled
59
32
  return {
60
33
  debug: (message, meta) => {
61
- if (isEnabled() && shouldLog('debug')) {
62
- console.debug(`[${prefix}] [DEBUG] ${formatMessage(message, meta)}`);
34
+ if (isEnabled()) {
35
+ baseLogger.debug(`[${prefix}] ${message}`, meta);
63
36
  }
64
37
  },
65
38
  info: (message, meta) => {
66
- if (isEnabled() && shouldLog('info')) {
67
- console.info(`[${prefix}] ${formatMessage(message, meta)}`);
39
+ if (isEnabled()) {
40
+ baseLogger.info(`[${prefix}] ${message}`, meta);
68
41
  }
69
42
  },
70
43
  warn: (message, meta) => {
71
- if (isEnabled() && shouldLog('warn')) {
72
- console.warn(`[${prefix}] [WARN] ${formatMessage(message, meta)}`);
44
+ if (isEnabled()) {
45
+ baseLogger.warn(`[${prefix}] ${message}`, meta);
73
46
  }
74
47
  },
75
48
  error: (message, meta) => {
76
- if (isEnabled() && shouldLog('error')) {
77
- console.error(`[${prefix}] [ERROR] ${formatMessage(message, meta)}`);
49
+ if (isEnabled()) {
50
+ baseLogger.error(`[${prefix}] ${message}`, meta);
78
51
  }
79
52
  },
80
53
  };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Formatting utilities for logging
3
+ */
4
+ /**
5
+ * Format token for logging (start...end)
6
+ * @param token Token string to format
7
+ * @returns Formatted token string or undefined if token is empty
8
+ */
9
+ export declare function formatToken(token?: string): string | undefined;
10
+ /**
11
+ * Format timestamp to readable date/time string
12
+ * @param timestamp Timestamp in milliseconds
13
+ * @returns Formatted date string (e.g., "2025-12-25 19:21:27 UTC")
14
+ */
15
+ export declare function formatExpirationDate(timestamp: number): string;
16
+ //# sourceMappingURL=formatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../src/utils/formatting.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAS9D"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Formatting utilities for logging
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatToken = formatToken;
7
+ exports.formatExpirationDate = formatExpirationDate;
8
+ /**
9
+ * Format token for logging (start...end)
10
+ * @param token Token string to format
11
+ * @returns Formatted token string or undefined if token is empty
12
+ */
13
+ function formatToken(token) {
14
+ if (!token)
15
+ return undefined;
16
+ if (token.length <= 50)
17
+ return token;
18
+ return `${token.substring(0, 25)}...${token.substring(token.length - 25)}`;
19
+ }
20
+ /**
21
+ * Format timestamp to readable date/time string
22
+ * @param timestamp Timestamp in milliseconds
23
+ * @returns Formatted date string (e.g., "2025-12-25 19:21:27 UTC")
24
+ */
25
+ function formatExpirationDate(timestamp) {
26
+ const date = new Date(timestamp);
27
+ const year = date.getUTCFullYear();
28
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
29
+ const day = String(date.getUTCDate()).padStart(2, '0');
30
+ const hours = String(date.getUTCHours()).padStart(2, '0');
31
+ const minutes = String(date.getUTCMinutes()).padStart(2, '0');
32
+ const seconds = String(date.getUTCSeconds()).padStart(2, '0');
33
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds} UTC`;
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/auth-broker",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "JWT authentication broker for MCP ABAP ADT - manages tokens based on destination headers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -56,14 +56,15 @@
56
56
  "node": ">=18.0.0"
57
57
  },
58
58
  "dependencies": {
59
- "@mcp-abap-adt/auth-providers": "^0.2.8",
60
- "@mcp-abap-adt/auth-stores": "^0.2.9",
59
+ "@mcp-abap-adt/auth-providers": "^0.2.10",
60
+ "@mcp-abap-adt/auth-stores": "^0.2.10",
61
61
  "@mcp-abap-adt/interfaces": "^0.2.14",
62
62
  "axios": "^1.13.2",
63
63
  "tsx": "^4.21.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@biomejs/biome": "^2.3.10",
67
+ "@mcp-abap-adt/logger": "^0.1.4",
67
68
  "@types/express": "^5.0.5",
68
69
  "@types/jest": "^30.0.0",
69
70
  "@types/js-yaml": "^4.0.9",
@@ -71,6 +72,8 @@
71
72
  "jest": "^30.2.0",
72
73
  "jest-util": "^30.2.0",
73
74
  "js-yaml": "^4.1.1",
75
+ "pino": "^10.1.0",
76
+ "pino-pretty": "^13.1.3",
74
77
  "ts-jest": "^29.2.5",
75
78
  "typescript": "^5.9.2"
76
79
  }