@equinor/fusion-framework-module-msal 10.0.1 → 10.0.2

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 (58) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/esm/MsalClient.js +9 -0
  3. package/dist/esm/MsalClient.js.map +1 -1
  4. package/dist/esm/MsalConfigurator.js +3 -1
  5. package/dist/esm/MsalConfigurator.js.map +1 -1
  6. package/dist/esm/MsalProvider.js +20 -1
  7. package/dist/esm/MsalProvider.js.map +1 -1
  8. package/dist/esm/create-client-log-callback.js +1 -0
  9. package/dist/esm/create-client-log-callback.js.map +1 -1
  10. package/dist/esm/create-proxy-provider.js +5 -0
  11. package/dist/esm/create-proxy-provider.js.map +1 -1
  12. package/dist/esm/module.js +3 -2
  13. package/dist/esm/module.js.map +1 -1
  14. package/dist/esm/util/normalize-uri.js.map +1 -1
  15. package/dist/esm/v2/Logger.js +173 -0
  16. package/dist/esm/v2/Logger.js.map +1 -0
  17. package/dist/esm/v2/create-proxy-client.js +6 -0
  18. package/dist/esm/v2/create-proxy-client.js.map +1 -1
  19. package/dist/esm/v2/create-proxy-provider.js +4 -0
  20. package/dist/esm/v2/create-proxy-provider.js.map +1 -1
  21. package/dist/esm/v2/types.js +3 -124
  22. package/dist/esm/v2/types.js.map +1 -1
  23. package/dist/esm/v4/create-proxy-provider.js +1 -0
  24. package/dist/esm/v4/create-proxy-provider.js.map +1 -1
  25. package/dist/esm/v4/types.js.map +1 -1
  26. package/dist/esm/version.js +1 -1
  27. package/dist/esm/versioning/VersionError.js.map +1 -1
  28. package/dist/esm/versioning/resolve-version.js +4 -0
  29. package/dist/esm/versioning/resolve-version.js.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/dist/types/MsalClient.d.ts +4 -0
  32. package/dist/types/MsalConfigurator.d.ts +1 -0
  33. package/dist/types/MsalProvider.d.ts +13 -0
  34. package/dist/types/create-proxy-provider.d.ts +3 -0
  35. package/dist/types/static.d.ts +1 -1
  36. package/dist/types/v2/IAuthClient.interface.d.ts +2 -2
  37. package/dist/types/v2/Logger.d.ts +92 -0
  38. package/dist/types/v2/MsalProvider.interface.d.ts +1 -1
  39. package/dist/types/v2/types.d.ts +3 -49
  40. package/dist/types/v4/types.d.ts +1 -3
  41. package/dist/types/version.d.ts +1 -1
  42. package/package.json +7 -7
  43. package/src/MsalClient.ts +9 -0
  44. package/src/MsalConfigurator.ts +3 -1
  45. package/src/MsalProvider.ts +20 -1
  46. package/src/create-client-log-callback.ts +1 -0
  47. package/src/create-proxy-provider.ts +5 -0
  48. package/src/module.ts +3 -2
  49. package/src/v2/IAuthClient.interface.ts +2 -2
  50. package/src/v2/Logger.ts +204 -0
  51. package/src/v2/MsalProvider.interface.ts +1 -1
  52. package/src/v2/create-proxy-client.ts +6 -0
  53. package/src/v2/create-proxy-provider.ts +4 -0
  54. package/src/v2/types.ts +8 -158
  55. package/src/v4/create-proxy-provider.ts +1 -0
  56. package/src/v4/types.ts +3 -3
  57. package/src/version.ts +1 -1
  58. package/src/versioning/resolve-version.ts +4 -0
@@ -0,0 +1,204 @@
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
+ }
@@ -86,7 +86,7 @@ export interface IMsalProvider {
86
86
  /**
87
87
  * Handle authentication redirect
88
88
  */
89
- handleRedirect(): Promise<void | null>;
89
+ handleRedirect(): Promise<undefined | null>;
90
90
 
91
91
  /**
92
92
  * Create a proxy provider for version compatibility
@@ -28,9 +28,11 @@ import type { AccountInfo } from './types';
28
28
  export function createProxyClient(client: IMsalClient): IAuthClient {
29
29
  const proxy = new Proxy(client, {
30
30
  get: (target: IMsalClient, prop: keyof IAuthClient) => {
31
+ // Adapt each v4 client member to the v2-compatible shape expected by callers
31
32
  switch (prop) {
32
33
  case 'getAllAccounts': {
33
34
  return () => {
35
+ // Map each v4 account shape to its v2-compatible equivalent
34
36
  return target.getAllAccounts().map(mapAccountInfo);
35
37
  };
36
38
  }
@@ -69,6 +71,7 @@ export function createProxyClient(client: IMsalClient): IAuthClient {
69
71
  return async () => {
70
72
  const result = await target.handleRedirectPromise();
71
73
 
74
+ // No redirect result means there's nothing pending to map
72
75
  if (!result) {
73
76
  return null;
74
77
  }
@@ -80,6 +83,7 @@ export function createProxyClient(client: IMsalClient): IAuthClient {
80
83
  case 'getActiveAccount': {
81
84
  return () => {
82
85
  const account = target.getActiveAccount();
86
+ // No active account means there's nothing to map
83
87
  if (!account) {
84
88
  return null;
85
89
  }
@@ -185,5 +189,7 @@ export function createProxyClient(client: IMsalClient): IAuthClient {
185
189
  },
186
190
  });
187
191
 
192
+ // The Proxy handler above implements every member of `IAuthClient` at runtime via its `get`
193
+ // trap, but TypeScript can't verify a `Proxy<T>` satisfies `T` structurally.
188
194
  return proxy as unknown as IAuthClient;
189
195
  }
@@ -13,6 +13,7 @@ import { MsalModuleVersion } from '../static';
13
13
  * @returns True if the request is in v4 format (has a `request` property with `scopes` and `account`)
14
14
  */
15
15
  function isRequestV4(req: unknown): req is AcquireTokenOptions {
16
+ // Non-object/null values can never match the v4 request shape
16
17
  if (typeof req !== 'object' || req === null) {
17
18
  return false;
18
19
  }
@@ -48,6 +49,7 @@ export function createProxyProvider(provider: IMsalProvider): IMsalProvider_v2 {
48
49
  // Use Proxy to intercept property access and provide v2-compatible implementations
49
50
  const proxy = new Proxy(provider, {
50
51
  get: (target: IMsalProvider, prop: keyof IMsalProvider_v2) => {
52
+ // Adapt each v4 provider member to the v2-compatible shape expected by callers
51
53
  switch (prop) {
52
54
  case 'version': {
53
55
  return provider.version;
@@ -62,6 +64,7 @@ export function createProxyProvider(provider: IMsalProvider): IMsalProvider_v2 {
62
64
  case 'defaultClient': {
63
65
  // Deprecated property - redirect to client with warning
64
66
  console.warn('defaultClient is deprecated, use client instead');
67
+ // Same v2-compatible client wrapper as the `client` case above.
65
68
  return v2Client as unknown as IMsalProvider_v2['defaultClient'];
66
69
  }
67
70
  case 'defaultAccount': {
@@ -156,6 +159,7 @@ export function createProxyProvider(provider: IMsalProvider): IMsalProvider_v2 {
156
159
  };
157
160
  }
158
161
  default: {
162
+ // The proxy is awaited in some contexts, so `then` must resolve to undefined
159
163
  if (prop === 'then') {
160
164
  return undefined;
161
165
  }
package/src/v2/types.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  * from MSAL v2.38.4 to maintain backward compatibility while using MSAL v4 implementation.
6
6
  */
7
7
 
8
+ import type { Logger } from './Logger.js';
9
+
8
10
  // ============================================================================
9
11
  // Basic Types
10
12
  // ============================================================================
@@ -287,6 +289,7 @@ export type RedirectRequest = Partial<
287
289
  > & {
288
290
  scopes: Array<string>;
289
291
  redirectStartPage?: string;
292
+ // biome-ignore lint/suspicious/noConfusingVoidType: `void` here relies on TypeScript's special-cased "void-returning callback accepts any return value" behavior — `undefined` would break assignability of navigate functions that return a value/promise
290
293
  onRedirectNavigate?: (url: string) => boolean | void;
291
294
  tokenBodyParameters?: StringDict;
292
295
  };
@@ -334,6 +337,7 @@ export type SsoSilentRequest = Partial<
334
337
  */
335
338
  export type EndSessionRequest = Partial<Omit<CommonEndSessionRequest, 'tokenQueryParameters'>> & {
336
339
  authority?: string;
340
+ // biome-ignore lint/suspicious/noConfusingVoidType: `void` here relies on TypeScript's special-cased "void-returning callback accepts any return value" behavior — `undefined` would break assignability of navigate functions that return a value/promise
337
341
  onRedirectNavigate?: (url: string) => boolean | void;
338
342
  };
339
343
 
@@ -390,9 +394,7 @@ export enum LogLevel {
390
394
  /**
391
395
  * Callback to send the messages to
392
396
  */
393
- export interface ILoggerCallback {
394
- (level: LogLevel, message: string, containsPii: boolean): void;
395
- }
397
+ export type ILoggerCallback = (level: LogLevel, message: string, containsPii: boolean) => void;
396
398
 
397
399
  /**
398
400
  * Options for logger messages
@@ -404,161 +406,9 @@ export type LoggerOptions = {
404
406
  correlationId?: string;
405
407
  };
406
408
 
407
- /**
408
- * Class which facilitates logging of messages to a specific place
409
- */
410
- export class Logger {
411
- // Correlation ID for request, usually set by user.
412
- private correlationId: string;
413
-
414
- // Current log level, defaults to info.
415
- private level: LogLevel = LogLevel.Info;
416
-
417
- // Boolean describing whether PII logging is allowed.
418
- private piiLoggingEnabled: boolean;
419
-
420
- // Callback to send messages to.
421
- private localCallback: ILoggerCallback;
422
-
423
- // Package name implementing this logger
424
- private packageName: string;
425
-
426
- // Package version implementing this logger
427
- private packageVersion: string;
428
-
429
- constructor(loggerOptions: LoggerOptions, packageName?: string, packageVersion?: string) {
430
- const defaultLoggerCallback = () => {
431
- return;
432
- };
433
- const setLoggerOptions = loggerOptions || Logger.createDefaultLoggerOptions();
434
- this.localCallback = setLoggerOptions.loggerCallback || defaultLoggerCallback;
435
- this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false;
436
- this.level =
437
- typeof setLoggerOptions.logLevel === 'number' ? setLoggerOptions.logLevel : LogLevel.Info;
438
- this.correlationId = setLoggerOptions.correlationId || '';
439
- this.packageName = packageName || '';
440
- this.packageVersion = packageVersion || '';
441
- }
442
-
443
- private static createDefaultLoggerOptions(): LoggerOptions {
444
- return {
445
- loggerCallback: () => {
446
- // allow users to not set loggerCallback
447
- },
448
- piiLoggingEnabled: false,
449
- logLevel: LogLevel.Info,
450
- };
451
- }
452
-
453
- /**
454
- * Create new Logger with existing configurations.
455
- */
456
- public clone(packageName: string, packageVersion: string, correlationId?: string): Logger {
457
- return new Logger(
458
- {
459
- loggerCallback: this.localCallback,
460
- piiLoggingEnabled: this.piiLoggingEnabled,
461
- logLevel: this.level,
462
- correlationId: correlationId || this.correlationId,
463
- },
464
- packageName,
465
- packageVersion,
466
- );
467
- }
468
-
469
- /**
470
- * Logs error messages.
471
- */
472
- error(message: string, correlationId?: string): void {
473
- this.logMessage(message, {
474
- logLevel: LogLevel.Error,
475
- containsPii: false,
476
- correlationId: correlationId || '',
477
- });
478
- }
479
-
480
- /**
481
- * Logs warning messages.
482
- */
483
- warning(message: string, correlationId?: string): void {
484
- this.logMessage(message, {
485
- logLevel: LogLevel.Warning,
486
- containsPii: false,
487
- correlationId: correlationId || '',
488
- });
489
- }
490
-
491
- /**
492
- * Logs info messages.
493
- */
494
- info(message: string, correlationId?: string): void {
495
- this.logMessage(message, {
496
- logLevel: LogLevel.Info,
497
- containsPii: false,
498
- correlationId: correlationId || '',
499
- });
500
- }
501
-
502
- /**
503
- * Logs verbose messages.
504
- */
505
- verbose(message: string, correlationId?: string): void {
506
- this.logMessage(message, {
507
- logLevel: LogLevel.Verbose,
508
- containsPii: false,
509
- correlationId: correlationId || '',
510
- });
511
- }
512
-
513
- /**
514
- * Logs trace messages.
515
- */
516
- trace(message: string, correlationId?: string): void {
517
- this.logMessage(message, {
518
- logLevel: LogLevel.Trace,
519
- containsPii: false,
520
- correlationId: correlationId || '',
521
- });
522
- }
523
-
524
- /**
525
- * Returns whether PII Logging is enabled or not.
526
- */
527
- isPiiLoggingEnabled(): boolean {
528
- return this.piiLoggingEnabled || false;
529
- }
530
-
531
- private logMessage(
532
- logMessage: string,
533
- options: {
534
- logLevel: LogLevel;
535
- containsPii: boolean;
536
- correlationId: string;
537
- },
538
- ): void {
539
- if (options.logLevel > this.level || (!this.piiLoggingEnabled && options.containsPii)) {
540
- return;
541
- }
542
- const timestamp = new Date().toUTCString();
543
-
544
- // Add correlationId to logs if set, correlationId provided on log messages take precedence
545
- const logHeader = `[${timestamp}] : [${options.correlationId || this.correlationId || ''}]`;
546
-
547
- const log = `${logHeader} : ${this.packageName}@${
548
- this.packageVersion
549
- } : ${LogLevel[options.logLevel]} - ${logMessage}`;
550
- this.executeCallback(options.logLevel, log, options.containsPii || false);
551
- }
552
-
553
- /**
554
- * Execute callback with message.
555
- */
556
- executeCallback(level: LogLevel, message: string, containsPii: boolean): void {
557
- if (this.localCallback) {
558
- this.localCallback(level, message, containsPii);
559
- }
560
- }
561
- }
409
+ // Re-exported from its own file to satisfy single-export-per-file while
410
+ // preserving this file's existing public export surface.
411
+ export { Logger } from './Logger.js';
562
412
 
563
413
  // ============================================================================
564
414
  // Performance Types
@@ -23,6 +23,7 @@ export function createProxyProvider(provider: IMsalProvider): IMsalProvider {
23
23
  // Create passthrough proxy that only overrides msalVersion
24
24
  return new Proxy(provider, {
25
25
  get: (target: IMsalProvider, prop: keyof IMsalProvider) => {
26
+ // Passthrough every property except msalVersion, which reports V4 compatibility
26
27
  switch (prop) {
27
28
  case 'msalVersion': {
28
29
  // Report as V4 for compatibility tracking
package/src/v4/types.ts CHANGED
@@ -317,6 +317,7 @@ export type RedirectRequest = {
317
317
  sid?: string;
318
318
  account?: AccountInfo;
319
319
  redirectStartPage?: string;
320
+ // biome-ignore lint/suspicious/noConfusingVoidType: `void` here relies on TypeScript's special-cased "void-returning callback accepts any return value" behavior — `undefined` would break assignability of navigate functions that return a value/promise
320
321
  onRedirectNavigate?: (url: string) => boolean | void;
321
322
  authenticationScheme?: AuthenticationScheme;
322
323
  resourceRequestMethod?: string;
@@ -393,6 +394,7 @@ export type EndSessionRequest = {
393
394
  state?: string;
394
395
  logoutHint?: string;
395
396
  extraQueryParameters?: StringDict;
397
+ // biome-ignore lint/suspicious/noConfusingVoidType: `void` here relies on TypeScript's special-cased "void-returning callback accepts any return value" behavior — `undefined` would break assignability of navigate functions that return a value/promise
396
398
  onRedirectNavigate?: (url: string) => boolean | void;
397
399
  };
398
400
 
@@ -468,9 +470,7 @@ export enum LogLevel {
468
470
  /**
469
471
  * Callback to send the messages to
470
472
  */
471
- export interface ILoggerCallback {
472
- (level: LogLevel, message: string, containsPii: boolean): void;
473
- }
473
+ export type ILoggerCallback = (level: LogLevel, message: string, containsPii: boolean) => void;
474
474
 
475
475
  // ============================================================================
476
476
  // Event Types
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '10.0.1';
2
+ export const version = '10.0.2';
@@ -31,12 +31,15 @@ import { version as latestVersionString } from '../version';
31
31
  function mapVersionToEnumVersion(version: string | SemVer): MsalModuleVersion {
32
32
  console.log('Resolving version:', version);
33
33
  const coercedVersion = semver.coerce(version);
34
+ // An uncoercible version string cannot be mapped to a module version
34
35
  if (!coercedVersion) {
35
36
  throw new Error(`Invalid version: ${version}`);
36
37
  }
38
+ // Versions before 4.0.0 (including 2.x) map to the v2-compatible module version
37
39
  if (semver.satisfies(coercedVersion, '<4.0.0')) {
38
40
  return MsalModuleVersion.V2;
39
41
  }
42
+ // Versions before 7.0.0 (4.x and 5.x/6.x) map to the v4-compatible module version
40
43
  if (semver.satisfies(coercedVersion, '<7.0.0')) {
41
44
  return MsalModuleVersion.V4;
42
45
  }
@@ -113,6 +116,7 @@ export function resolveVersion(version?: string | SemVer): ResolvedVersion {
113
116
  wantedVersion = latestVersion;
114
117
  }
115
118
 
119
+ // Warn when the requested major version trails the latest major version
116
120
  if (wantedVersion.major < latestVersion.major) {
117
121
  const majorBehindVersionWarning = new VersionError(
118
122
  `Requested major version ${wantedVersion.major} is behind the latest major version ${latestVersion.major}`,