@equinor/fusion-framework-module-msal 11.0.0 → 11.0.1

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 (60) hide show
  1. package/dist/esm/version.js +1 -1
  2. package/dist/tsconfig.tsbuildinfo +1 -1
  3. package/dist/types/version.d.ts +1 -1
  4. package/package.json +8 -5
  5. package/CHANGELOG.md +0 -1212
  6. package/docs/api-reference.md +0 -85
  7. package/docs/auth-code-flow.md +0 -86
  8. package/docs/migration-v2-to-v4.md +0 -115
  9. package/docs/testing.md +0 -191
  10. package/docs/troubleshooting.md +0 -17
  11. package/docs/version-management.md +0 -67
  12. package/src/MsalClient.interface.ts +0 -139
  13. package/src/MsalClient.ts +0 -326
  14. package/src/MsalConfigurator.ts +0 -486
  15. package/src/MsalProvider.interface.ts +0 -179
  16. package/src/MsalProvider.ts +0 -776
  17. package/src/MsalProxyProvider.interface.ts +0 -72
  18. package/src/__tests__/MsalConfigurator.test.ts +0 -222
  19. package/src/__tests__/MsalProvider.test.ts +0 -74
  20. package/src/__tests__/create-proxy-provider.test.ts +0 -77
  21. package/src/__tests__/mock/create-mock-user-from-token.test.ts +0 -46
  22. package/src/__tests__/mock/msal-mock.test.ts +0 -613
  23. package/src/__tests__/versioning/resolve-version.test.ts +0 -161
  24. package/src/create-client-log-callback.ts +0 -102
  25. package/src/create-proxy-provider.ts +0 -97
  26. package/src/index.ts +0 -48
  27. package/src/mock/MsalMockClient.ts +0 -618
  28. package/src/mock/MsalMockConfigurator.ts +0 -305
  29. package/src/mock/create-mock-token.ts +0 -92
  30. package/src/mock/create-mock-user-from-token.ts +0 -46
  31. package/src/mock/create-msal-mock-client.ts +0 -25
  32. package/src/mock/decode-jwt-segment.ts +0 -22
  33. package/src/mock/index.ts +0 -30
  34. package/src/mock/module.ts +0 -54
  35. package/src/module.ts +0 -142
  36. package/src/msal-config-schema.ts +0 -81
  37. package/src/static.ts +0 -38
  38. package/src/telemetry-config-schema.ts +0 -25
  39. package/src/types.ts +0 -16
  40. package/src/util/compare-origin.ts +0 -18
  41. package/src/util/normalize-uri.ts +0 -24
  42. package/src/util/redirect.ts +0 -19
  43. package/src/v2/IAuthClient.interface.ts +0 -114
  44. package/src/v2/Logger.ts +0 -204
  45. package/src/v2/MsalProvider.interface.ts +0 -102
  46. package/src/v2/create-proxy-client.ts +0 -195
  47. package/src/v2/create-proxy-provider.ts +0 -177
  48. package/src/v2/map-account-info.ts +0 -23
  49. package/src/v2/map-authentication-result.ts +0 -28
  50. package/src/v2/types.ts +0 -674
  51. package/src/v4/create-proxy-provider.ts +0 -75
  52. package/src/v4/index.ts +0 -13
  53. package/src/v4/types.ts +0 -727
  54. package/src/version.ts +0 -2
  55. package/src/versioning/VersionError.ts +0 -64
  56. package/src/versioning/index.ts +0 -29
  57. package/src/versioning/resolve-version.ts +0 -154
  58. package/src/versioning/types.ts +0 -60
  59. package/tsconfig.json +0 -18
  60. package/vitest.config.ts +0 -11
package/src/module.ts DELETED
@@ -1,142 +0,0 @@
1
- import {
2
- type Module,
3
- type IModulesConfigurator,
4
- type ModuleConfigType,
5
- SemanticVersion,
6
- } from '@equinor/fusion-framework-module';
7
-
8
- import { MsalConfigurator } from './MsalConfigurator';
9
- import { MsalProvider, type IMsalProvider } from './MsalProvider';
10
-
11
- import { version } from './version';
12
-
13
- /**
14
- * MSAL authentication module configuration.
15
- *
16
- * This module provides Microsoft Authentication Library (MSAL) integration for the
17
- * Fusion Framework, supporting MSAL v4 with backward compatibility for v2 applications.
18
- */
19
- export type MsalModule = Module<'auth', IMsalProvider, MsalConfigurator, [MsalModule]>;
20
-
21
- /**
22
- * MSAL authentication module definition.
23
- *
24
- * This module manages authentication providers with the following initialization flow:
25
- * 1. Check for custom provider configuration
26
- * 2. Check for existing provider in parent module (for proxy compatibility)
27
- * 3. Create new provider with client configuration
28
- *
29
- * @remarks
30
- * The module supports proxy providers for version compatibility, allowing v4 implementations
31
- * to work with v2-compatible code during migration periods.
32
- */
33
- export const module: MsalModule = {
34
- name: 'auth',
35
- version: new SemanticVersion(version),
36
- configure: () => new MsalConfigurator(),
37
- initialize: async (init) => {
38
- const config = await init.config.createConfigAsync(init);
39
-
40
- // Priority 1: Use custom provider if explicitly configured
41
- if (config.provider) {
42
- return config.provider;
43
- }
44
-
45
- // Priority 2: Check if provider exists in parent module (proxy compatibility)
46
- // This allows child applications to reuse parent's authentication provider
47
- const hostProvider = init.ref?.auth;
48
- // Reuse the parent's provider (via a version-compatible proxy) when available
49
- if (hostProvider) {
50
- try {
51
- const proxyProvider = hostProvider.createProxyProvider(config.version);
52
- return proxyProvider;
53
- } catch (error) {
54
- console.error('MsalModule::Failed to create proxy provider', error);
55
- // Fallback to host provider to prevent app breakage during migration
56
- // TODO(#5114): Consider throwing error instead once all apps are migrated to v4
57
- return hostProvider;
58
- }
59
- }
60
-
61
- // Priority 3: Validate client configuration is provided
62
- if (!config.client) {
63
- throw new Error(
64
- 'Client configuration is required when provider is not in the parent module nor defined',
65
- );
66
- }
67
-
68
- // Create new MSAL provider instance
69
- const provider = new MsalProvider(config);
70
-
71
- // Initialize the provider (handles redirect callbacks, SSO, etc.)
72
- await provider.initialize();
73
-
74
- return provider;
75
- },
76
- };
77
-
78
- /**
79
- * Configuration function type for MSAL module setup.
80
- *
81
- * This function receives a builder object with methods to configure the MSAL client
82
- * and authentication requirements.
83
- */
84
- export type AuthConfigFn<TRef = unknown> = (
85
- configurator: ModuleConfigType<MsalModule>,
86
- ref?: TRef,
87
- ) => void;
88
-
89
- /**
90
- * Enables MSAL authentication module in the framework.
91
- *
92
- * This is a convenience function that adds the MSAL module configuration to the
93
- * framework configurator with optional configuration callback.
94
- *
95
- * @param configurator - The framework modules configurator instance
96
- * @param configure - Optional configuration callback for MSAL setup
97
- *
98
- * @example
99
- * ```typescript
100
- * enableMSAL(frameworkConfigurator, (builder) => {
101
- * builder.setClientConfig({
102
- * auth: { clientId: 'your-client-id', tenantId: 'your-tenant-id' }
103
- * });
104
- * builder.setRequiresAuth(true);
105
- * });
106
- * ```
107
- */
108
- export const enableMSAL = (
109
- // biome-ignore lint/suspicious/noExplicitAny: must be any to support all module types
110
- configurator: IModulesConfigurator<any, any>,
111
- configure?: AuthConfigFn,
112
- ): void => {
113
- const config = configure ? configureMsal(configure) : { module };
114
- configurator.addConfig(config);
115
- };
116
-
117
- /**
118
- * Creates MSAL module configuration with custom setup.
119
- *
120
- * @param configure - Configuration callback function
121
- * @returns Module configuration object ready for framework integration
122
- *
123
- * @example
124
- * ```typescript
125
- * const msalConfig = configureMsal((builder) => {
126
- * builder.setClientConfig(msalClientConfig);
127
- * builder.setRequiresAuth(true);
128
- * });
129
- * ```
130
- */
131
- export const configureMsal = (configure: AuthConfigFn) => ({
132
- module,
133
- configure,
134
- });
135
-
136
- declare module '@equinor/fusion-framework-module' {
137
- interface Modules {
138
- auth: MsalModule;
139
- }
140
- }
141
-
142
- export default module;
@@ -1,81 +0,0 @@
1
- import z from 'zod';
2
- import semver from 'semver';
3
- import { CacheLookupPolicy } from '@azure/msal-browser';
4
-
5
- import type { IMsalClient } from './MsalClient.interface';
6
- import type { IMsalProvider } from './MsalProvider.interface';
7
- import { TelemetryConfigSchema } from './telemetry-config-schema';
8
- export type { TelemetryConfig } from './telemetry-config-schema';
9
-
10
- /**
11
- * Zod schema for MSAL module configuration validation.
12
- *
13
- * @remarks
14
- * Kept in its own module so the configuration can be extended at its source.
15
- * The schema itself describes what reaches `MsalProvider` and strips anything
16
- * else; keys a variant of this module needs only while the configuration is
17
- * being built are declared on {@link MsalConfigExtension} instead.
18
- */
19
- export const MsalConfigSchema = z.object({
20
- client: z.custom<IMsalClient>().optional(),
21
- provider: z.custom<IMsalProvider>().optional(),
22
- requiresAuth: z.boolean().optional(),
23
- redirectUri: z.string().optional(),
24
- loginHint: z.string().optional(),
25
- authCode: z.string().optional(),
26
- cacheLookupPolicy: z
27
- .custom<CacheLookupPolicy>(
28
- (val) =>
29
- typeof val === 'number' &&
30
- Object.values(CacheLookupPolicy).includes(val as CacheLookupPolicy),
31
- )
32
- .optional(),
33
- version: z.string().transform((value, ctx) => {
34
- const coerced = semver.coerce(value);
35
- // `semver.coerce` returns `null` for an unparseable version; without this guard it
36
- // would silently become the literal string "null" instead of failing validation.
37
- if (!coerced) {
38
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid MSAL module version' });
39
- return z.NEVER;
40
- }
41
- return coerced.version;
42
- }),
43
- telemetry: TelemetryConfigSchema,
44
- });
45
-
46
- /**
47
- * Configuration a variant of this module adds to {@link MsalConfig}.
48
- *
49
- * @remarks
50
- * Empty by design: production MSAL configuration is exactly the schema. This
51
- * exists so a variant — the test double in `./mock`, for instance — can declare
52
- * its own branch of the configuration through declaration merging:
53
- *
54
- * ```typescript
55
- * declare module '@equinor/fusion-framework-module-msal' {
56
- * interface MsalConfigExtension {
57
- * mock?: { account?: MsalMockUser };
58
- * }
59
- * }
60
- * ```
61
- *
62
- * That is what keeps `BaseConfigBuilder._set` honest about the added key. Its
63
- * target is a dot-path union derived from {@link MsalConfig}, so a key the type
64
- * does not know about can only be set by casting past the builder — and a
65
- * generic configurator cannot help, because a dot-path union over an unresolved
66
- * type parameter defers, taking every existing literal path down with it.
67
- *
68
- * The key exists to carry a declaration across the builder, not to reach the
69
- * provider: the schema strips it during validation, so it is readable from the
70
- * raw configuration and absent from the validated one.
71
- */
72
- // biome-ignore lint/suspicious/noEmptyInterface: the extension point is the point
73
- export interface MsalConfigExtension {}
74
-
75
- /**
76
- * Complete configuration object for MSAL authentication module.
77
- *
78
- * This type represents the full configuration including client setup, authentication
79
- * requirements, telemetry, and version information.
80
- */
81
- export type MsalConfig = z.infer<typeof MsalConfigSchema> & MsalConfigExtension;
package/src/static.ts DELETED
@@ -1,38 +0,0 @@
1
- /**
2
- * Module identifier for the MSAL authentication module.
3
- *
4
- * This constant is used to register and identify the MSAL module within the Fusion Framework.
5
- */
6
- export const ModuleName = 'msal' as const;
7
-
8
- /**
9
- * Enumeration of supported MSAL module versions.
10
- *
11
- * This enum defines the available MSAL versions and provides type-safe access to version identifiers.
12
- *
13
- * @remarks
14
- * - `V2`: MSAL v2 compatibility (legacy support)
15
- * - `V4`: MSAL v4 compatibility (supports @azure/msal-browser 4.x)
16
- * - `V5`: MSAL v5 compatibility (supports @azure/msal-browser 5.x)
17
- *
18
- * @example
19
- * ```typescript
20
- * import { MsalModuleVersion } from '@equinor/fusion-framework-module-msal';
21
- *
22
- * // Check version
23
- * if (version === MsalModuleVersion.V5) {
24
- * console.log('Using MSAL v5 compatible version');
25
- * }
26
- *
27
- * // Create version-specific proxy
28
- * const proxy = provider.createProxyProvider(MsalModuleVersion.V2);
29
- * ```
30
- */
31
- export enum MsalModuleVersion {
32
- /** MSAL v2 compatibility version (legacy support) */
33
- V2 = 'v2',
34
- /** MSAL v4 compatibility version (supports @azure/msal-browser 4.x) */
35
- V4 = 'v4',
36
- /** MSAL v5 compatibility version (supports @azure/msal-browser 5.x) */
37
- V5 = 'v5',
38
- }
@@ -1,25 +0,0 @@
1
- import z from 'zod';
2
- import type { ITelemetryProvider } from '@equinor/fusion-framework-module-telemetry';
3
- import { version } from './version';
4
-
5
- /**
6
- * Zod schema for telemetry configuration validation.
7
- *
8
- * @internal
9
- */
10
- export const TelemetryConfigSchema = z.object({
11
- provider: z.custom<ITelemetryProvider>().optional(),
12
- metadata: z.record(z.string(), z.unknown()).optional().default({
13
- module: 'msal',
14
- version,
15
- }),
16
- scope: z.array(z.string()).optional().default(['framework', 'authentication']),
17
- });
18
-
19
- /**
20
- * Telemetry configuration for MSAL module.
21
- *
22
- * This configuration controls how authentication events are tracked and logged
23
- * through the framework's telemetry system.
24
- */
25
- export type TelemetryConfig = z.infer<typeof TelemetryConfigSchema>;
package/src/types.ts DELETED
@@ -1,16 +0,0 @@
1
- /**
2
- * Re-exports of core MSAL types from @azure/msal-browser.
3
- *
4
- * This module provides convenient access to commonly used MSAL types without
5
- * requiring direct imports from @azure/msal-browser. These types represent
6
- * fundamental authentication entities used throughout the MSAL module.
7
- *
8
- * @module
9
- */
10
-
11
- export {
12
- /** Represents account information for an authenticated user */
13
- AccountInfo,
14
- /** Represents the result of an authentication operation including tokens and account */
15
- AuthenticationResult,
16
- } from '@azure/msal-browser';
@@ -1,18 +0,0 @@
1
- import { normalizeUri } from './normalize-uri';
2
-
3
- /**
4
- * Compares two URIs after normalizing them to their canonical form.
5
- *
6
- * Both values are passed through {@link normalizeUri} before comparison, so relative
7
- * paths, double slashes, and trailing slashes are handled transparently.
8
- *
9
- * @internal
10
- *
11
- * @param a - First URI or relative path
12
- * @param b - Second URI or relative path
13
- * @returns `true` when both URIs resolve to the same normalized string
14
- */
15
- export const compareOrigin = (a: string, b: string): boolean => {
16
- const url = { a: normalizeUri(a), b: normalizeUri(b) };
17
- return url.a === url.b;
18
- };
@@ -1,24 +0,0 @@
1
- /**
2
- * Creates and normalizes a redirect URI.
3
- *
4
- * Resolves relative paths against the provided base URL and strips double and trailing slashes
5
- * from the resulting pathname. Used internally to sanitize redirect URIs before passing them
6
- * to MSAL authentication flows.
7
- *
8
- * @internal
9
- *
10
- * @param uri - Relative path (e.g. `/callback`) or absolute URL (e.g. `https://app.com/callback`)
11
- * @param home - Base URL for resolving relative paths. Defaults to `window.location.origin`.
12
- * @returns Fully-qualified, normalized URI string
13
- *
14
- * @example
15
- * ```typescript
16
- * normalizeUri('/callback'); // https://current-origin.com/callback
17
- * normalizeUri('https://app.com//callback/'); // https://app.com/callback
18
- * ```
19
- */
20
- export const normalizeUri = (uri: string, home: string = window.location.origin): string => {
21
- uri = uri.match(/^http[s]?/) ? uri : home + uri;
22
- const { origin, pathname } = new URL(uri);
23
- return origin + pathname.replace(/([^:]\/)\/+/g, '$1');
24
- };
@@ -1,19 +0,0 @@
1
- /**
2
- * Redirects the browser to the specified URL.
3
- *
4
- * If the browser has not navigated away within the given timeout, the returned
5
- * promise is rejected. This acts as a safeguard against redirect failures.
6
- *
7
- * @internal
8
- *
9
- * @param url - Endpoint to navigate to
10
- * @param timeout - Maximum milliseconds to wait before considering the redirect failed. Defaults to `3000`.
11
- * @param history - When `true`, uses `location.assign()` so the current page is kept in browser history.
12
- * Otherwise uses `location.replace()` which replaces the current history entry.
13
- * @returns A promise that rejects after the timeout (it never resolves because a successful redirect
14
- * causes the page to unload)
15
- */
16
- export const redirect = (url: string, timeout = 3000, history?: boolean): Promise<void> => {
17
- history ? window.location.assign(url) : window.location.replace(url);
18
- return new Promise((_, reject) => setTimeout(reject, timeout));
19
- };
@@ -1,114 +0,0 @@
1
- import type {
2
- AccountInfo as AccountInfoBase,
3
- AuthenticationResult,
4
- IPublicClientApplication,
5
- } from './types';
6
-
7
- /**
8
- * Simplified ID token claims used by the v2 compatibility layer.
9
- *
10
- * @property aud - Token audience (application ID)
11
- * @property exp - Token expiration time (seconds since epoch)
12
- */
13
- export type IdTokenClaims = {
14
- aud: string;
15
- exp: number;
16
- };
17
-
18
- /**
19
- * Extended account information for v2 compatibility.
20
- *
21
- * Augments the base v2 `AccountInfo` with typed ID token claims.
22
- */
23
- export type AccountInfo = AccountInfoBase & {
24
- idTokenClaims?: IdTokenClaims;
25
- };
26
-
27
- /**
28
- * Authentication behavior type for v2-compatible login and token flows.
29
- *
30
- * - `'popup'` — Opens a popup window for authentication
31
- * - `'redirect'` — Navigates the browser to the Microsoft login page
32
- */
33
- export type AuthBehavior = 'popup' | 'redirect';
34
-
35
- /**
36
- * Simplified authentication request for v2-compatible methods.
37
- *
38
- * @property scopes - Optional OAuth scopes to request (e.g. `['User.Read']`)
39
- * @property loginHint - Optional username hint to pre-fill the login form
40
- */
41
- export type AuthRequest = {
42
- scopes?: string[];
43
- loginHint?: string;
44
- };
45
-
46
- /**
47
- * Interface for MSAL v2 compatible authentication client.
48
- *
49
- * This interface defines the contract for authentication clients that maintain
50
- * backward compatibility with MSAL v2 API while using MSAL v4 implementation
51
- * under the hood. This is useful for gradual migration scenarios.
52
- *
53
- * @example
54
- * ```typescript
55
- * const client: IAuthClient_v2 = createProxyClient(baseClient);
56
- *
57
- * // Use v2 compatible API
58
- * const account = client.account;
59
- * const result = await client.login({ scopes: ['User.Read'] });
60
- * ```
61
- */
62
- export interface IAuthClient extends IPublicClientApplication {
63
- /**
64
- * Tenant ID for the client domain
65
- */
66
- readonly tenantId: string;
67
-
68
- /**
69
- * Returns account for client tenant that MSAL currently has data for.
70
- * (the account object is created at the time of successful login)
71
- */
72
- get account(): AccountInfo | undefined;
73
-
74
- /**
75
- * Check if the current account has valid claims
76
- */
77
- get hasValidClaims(): boolean;
78
-
79
- /**
80
- * Configured client ID
81
- */
82
- get clientId(): string | undefined;
83
-
84
- /**
85
- * Request origin from browser storage
86
- */
87
- get requestOrigin(): string | null;
88
-
89
- /**
90
- * Login user with optional silent authentication fallback
91
- * @param options - Optional authentication request options
92
- * @param behavior - Authentication method: 'popup' or 'redirect'
93
- * @param silent - Whether to attempt silent authentication first
94
- * @returns Promise resolving to authentication result or void
95
- */
96
- login(
97
- options?: AuthRequest,
98
- behavior?: AuthBehavior,
99
- silent?: boolean,
100
- ): Promise<AuthenticationResult | undefined>;
101
-
102
- /**
103
- * Acquire access token with optional silent authentication fallback
104
- * @param options - Authentication request options
105
- * @param behavior - Authentication method: 'popup' or 'redirect'
106
- * @param silent - Whether to attempt silent authentication first
107
- * @returns Promise resolving to authentication result or void
108
- */
109
- acquireToken(
110
- options?: AuthRequest,
111
- behavior?: AuthBehavior,
112
- silent?: boolean,
113
- ): Promise<AuthenticationResult | undefined>;
114
- }
package/src/v2/Logger.ts DELETED
@@ -1,204 +0,0 @@
1
- import { LogLevel, type ILoggerCallback, type LoggerOptions } from './types.js';
2
-
3
- /**
4
- * Class which facilitates logging of messages to a specific place
5
- */
6
- export class Logger {
7
- // Correlation ID for request, usually set by user.
8
- private correlationId: string;
9
-
10
- // Current log level, defaults to info.
11
- private level: LogLevel = LogLevel.Info;
12
-
13
- // Boolean describing whether PII logging is allowed.
14
- private piiLoggingEnabled: boolean;
15
-
16
- // Callback to send messages to.
17
- private localCallback: ILoggerCallback;
18
-
19
- // Package name implementing this logger
20
- private packageName: string;
21
-
22
- // Package version implementing this logger
23
- private packageVersion: string;
24
-
25
- /**
26
- * Creates a new `Logger`.
27
- *
28
- * @param loggerOptions - Logger configuration, including callback, PII, and log level settings.
29
- * @param packageName - Name of the package implementing this logger.
30
- * @param packageVersion - Version of the package implementing this logger.
31
- */
32
- constructor(loggerOptions: LoggerOptions, packageName?: string, packageVersion?: string) {
33
- const defaultLoggerCallback = () => {
34
- return;
35
- };
36
- const setLoggerOptions = loggerOptions || Logger.createDefaultLoggerOptions();
37
- this.localCallback = setLoggerOptions.loggerCallback || defaultLoggerCallback;
38
- this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false;
39
- this.level =
40
- typeof setLoggerOptions.logLevel === 'number' ? setLoggerOptions.logLevel : LogLevel.Info;
41
- this.correlationId = setLoggerOptions.correlationId || '';
42
- this.packageName = packageName || '';
43
- this.packageVersion = packageVersion || '';
44
- }
45
-
46
- /**
47
- * Creates the default logger options used when none are provided.
48
- *
49
- * @returns Default logger options with a no-op callback, PII logging disabled, and Info level.
50
- */
51
- private static createDefaultLoggerOptions(): LoggerOptions {
52
- return {
53
- loggerCallback: () => {
54
- // allow users to not set loggerCallback
55
- },
56
- piiLoggingEnabled: false,
57
- logLevel: LogLevel.Info,
58
- };
59
- }
60
-
61
- /**
62
- * Create new Logger with existing configurations.
63
- *
64
- * @param packageName - Name of the package implementing this logger.
65
- * @param packageVersion - Version of the package implementing this logger.
66
- * @param correlationId - Correlation ID to use, falling back to this logger's own if omitted.
67
- * @returns A new `Logger` instance cloned from this one.
68
- */
69
- public clone(packageName: string, packageVersion: string, correlationId?: string): Logger {
70
- return new Logger(
71
- {
72
- loggerCallback: this.localCallback,
73
- piiLoggingEnabled: this.piiLoggingEnabled,
74
- logLevel: this.level,
75
- correlationId: correlationId || this.correlationId,
76
- },
77
- packageName,
78
- packageVersion,
79
- );
80
- }
81
-
82
- /**
83
- * Logs error messages.
84
- *
85
- * @param message - The message to log.
86
- * @param correlationId - Correlation ID to attach to the log entry, if any.
87
- */
88
- error(message: string, correlationId?: string): void {
89
- this.logMessage(message, {
90
- logLevel: LogLevel.Error,
91
- containsPii: false,
92
- correlationId: correlationId || '',
93
- });
94
- }
95
-
96
- /**
97
- * Logs warning messages.
98
- *
99
- * @param message - The message to log.
100
- * @param correlationId - Correlation ID to attach to the log entry, if any.
101
- */
102
- warning(message: string, correlationId?: string): void {
103
- this.logMessage(message, {
104
- logLevel: LogLevel.Warning,
105
- containsPii: false,
106
- correlationId: correlationId || '',
107
- });
108
- }
109
-
110
- /**
111
- * Logs info messages.
112
- *
113
- * @param message - The message to log.
114
- * @param correlationId - Correlation ID to attach to the log entry, if any.
115
- */
116
- info(message: string, correlationId?: string): void {
117
- this.logMessage(message, {
118
- logLevel: LogLevel.Info,
119
- containsPii: false,
120
- correlationId: correlationId || '',
121
- });
122
- }
123
-
124
- /**
125
- * Logs verbose messages.
126
- *
127
- * @param message - The message to log.
128
- * @param correlationId - Correlation ID to attach to the log entry, if any.
129
- */
130
- verbose(message: string, correlationId?: string): void {
131
- this.logMessage(message, {
132
- logLevel: LogLevel.Verbose,
133
- containsPii: false,
134
- correlationId: correlationId || '',
135
- });
136
- }
137
-
138
- /**
139
- * Logs trace messages.
140
- *
141
- * @param message - The message to log.
142
- * @param correlationId - Correlation ID to attach to the log entry, if any.
143
- */
144
- trace(message: string, correlationId?: string): void {
145
- this.logMessage(message, {
146
- logLevel: LogLevel.Trace,
147
- containsPii: false,
148
- correlationId: correlationId || '',
149
- });
150
- }
151
-
152
- /**
153
- * Returns whether PII Logging is enabled or not.
154
- *
155
- * @returns `true` when PII logging is enabled, otherwise `false`.
156
- */
157
- isPiiLoggingEnabled(): boolean {
158
- return this.piiLoggingEnabled || false;
159
- }
160
-
161
- /**
162
- * Formats and dispatches a log message to the configured callback, unless it
163
- * is below the configured log level or contains PII while PII logging is disabled.
164
- *
165
- * @param logMessage - The raw message to log.
166
- * @param options - Log level, PII flag, and correlation ID for this message.
167
- */
168
- private logMessage(
169
- logMessage: string,
170
- options: {
171
- logLevel: LogLevel;
172
- containsPii: boolean;
173
- correlationId: string;
174
- },
175
- ): void {
176
- // Skip messages below the configured level or containing PII when PII logging is disabled
177
- if (options.logLevel > this.level || (!this.piiLoggingEnabled && options.containsPii)) {
178
- return;
179
- }
180
- const timestamp = new Date().toUTCString();
181
-
182
- // Add correlationId to logs if set, correlationId provided on log messages take precedence
183
- const logHeader = `[${timestamp}] : [${options.correlationId || this.correlationId || ''}]`;
184
-
185
- const log = `${logHeader} : ${this.packageName}@${
186
- this.packageVersion
187
- } : ${LogLevel[options.logLevel]} - ${logMessage}`;
188
- this.executeCallback(options.logLevel, log, options.containsPii || false);
189
- }
190
-
191
- /**
192
- * Execute callback with message.
193
- *
194
- * @param level - The log level of the message.
195
- * @param message - The formatted message to send to the callback.
196
- * @param containsPii - Whether the message contains personally identifiable information.
197
- */
198
- executeCallback(level: LogLevel, message: string, containsPii: boolean): void {
199
- // Only invoke the callback when one has been configured
200
- if (this.localCallback) {
201
- this.localCallback(level, message, containsPii);
202
- }
203
- }
204
- }