@chemmangat/msal-next 2.3.0 → 3.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.
package/README.md CHANGED
@@ -5,9 +5,12 @@ Production-grade MSAL authentication library for Next.js App Router with minimal
5
5
  [![npm version](https://badge.fury.io/js/@chemmangat%2Fmsal-next.svg)](https://www.npmjs.com/package/@chemmangat/msal-next)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
+ > **v3.0.0 is here!** 🎉 New CLI tool, enhanced debugging, and better DX. [See what's new](#whats-new-in-v30)
9
+
8
10
  ## Features
9
11
 
10
- ✨ **Minimal Setup** - Just provide your `clientId` to get started
12
+ ✨ **CLI Setup** - Get started in under 2 minutes with `npx @chemmangat/msal-next init`
13
+ 🔍 **Enhanced Debugging** - Performance tracking, network logs, and log export
11
14
  🔐 **Production Ready** - Comprehensive error handling, retry logic, and SSR support
12
15
  🎨 **Beautiful Components** - Pre-styled Microsoft-branded UI components
13
16
  🪝 **Powerful Hooks** - Easy-to-use hooks for auth, Graph API, and user data
@@ -15,10 +18,69 @@ Production-grade MSAL authentication library for Next.js App Router with minimal
15
18
  ⚡ **Edge Compatible** - Middleware support for protecting routes at the edge
16
19
  📦 **Zero Config** - Sensible defaults with full customization options
17
20
 
21
+ ## What's New in v3.0
22
+
23
+ ### 🚀 CLI Tool (NEW)
24
+ ```bash
25
+ # One command setup - that's it!
26
+ npx @chemmangat/msal-next init
27
+ ```
28
+
29
+ The new CLI tool automatically:
30
+ - Detects your Next.js structure (App Router/Pages Router)
31
+ - Installs dependencies
32
+ - Creates configuration files
33
+ - Generates example pages
34
+ - Sets up middleware
35
+
36
+ **Reduces setup time from 30+ minutes to under 2 minutes!**
37
+
38
+ ### 🔍 Enhanced Debug Logger (NEW)
39
+ ```tsx
40
+ import { getDebugLogger } from '@chemmangat/msal-next';
41
+
42
+ const logger = getDebugLogger({
43
+ enabled: true,
44
+ enablePerformance: true, // Track operation timing
45
+ enableNetworkLogs: true, // Log all requests/responses
46
+ });
47
+
48
+ // Performance tracking
49
+ logger.startTiming('token-acquisition');
50
+ await acquireToken(['User.Read']);
51
+ logger.endTiming('token-acquisition'); // Logs: "⏱️ Completed: token-acquisition (45ms)"
52
+
53
+ // Export logs for debugging
54
+ logger.downloadLogs('debug-logs.json');
55
+ ```
56
+
57
+ ### 📚 New Examples
58
+ - **Role-Based Routing** - Complete RBAC implementation
59
+ - **Multi-Tenant SaaS** - Full multi-tenant architecture
60
+
61
+ ### 🔄 Breaking Changes
62
+ - Requires Node.js 18+ (was 16+)
63
+ - Requires Next.js 14.1+ (was 14.0+)
64
+ - Requires @azure/msal-browser v4+ (was v3+)
65
+ - Removed `ServerSession.accessToken` (use client-side `acquireToken()`)
66
+
67
+ [See Migration Guide](./MIGRATION_GUIDE_v3.md) for details.
68
+
18
69
  ## Installation
19
70
 
71
+ ### Option 1: CLI Setup (Recommended)
20
72
  ```bash
21
- npm install @chemmangat/msal-next @azure/msal-browser @azure/msal-react
73
+ # Create Next.js app
74
+ npx create-next-app@latest my-app
75
+ cd my-app
76
+
77
+ # Initialize MSAL
78
+ npx @chemmangat/msal-next init
79
+ ```
80
+
81
+ ### Option 2: Manual Installation
82
+ ```bash
83
+ npm install @chemmangat/msal-next@3.0.0 @azure/msal-browser@^4.0.0 @azure/msal-react@^3.0.0
22
84
  ```
23
85
 
24
86
  ## Quick Start
@@ -331,7 +393,7 @@ const acquireTokenWithRetry = createRetryWrapper(acquireToken, {
331
393
 
332
394
  ### Debug Logger
333
395
 
334
- Comprehensive logging for troubleshooting.
396
+ Comprehensive logging for troubleshooting with enhanced v3.0 features.
335
397
 
336
398
  ```tsx
337
399
  import { getDebugLogger } from '@chemmangat/msal-next';
@@ -339,11 +401,28 @@ import { getDebugLogger } from '@chemmangat/msal-next';
339
401
  const logger = getDebugLogger({
340
402
  enabled: true,
341
403
  level: 'debug',
342
- showTimestamp: true
404
+ showTimestamp: true,
405
+ enablePerformance: true, // NEW in v3.0
406
+ enableNetworkLogs: true, // NEW in v3.0
407
+ maxHistorySize: 100, // NEW in v3.0
343
408
  });
344
409
 
410
+ // Basic logging
345
411
  logger.info('User logged in', { username: 'user@example.com' });
346
412
  logger.error('Authentication failed', { error });
413
+
414
+ // NEW: Performance tracking
415
+ logger.startTiming('token-acquisition');
416
+ const token = await acquireToken(['User.Read']);
417
+ logger.endTiming('token-acquisition'); // Logs duration
418
+
419
+ // NEW: Network logging
420
+ logger.logRequest('GET', '/me');
421
+ logger.logResponse('GET', '/me', 200, userData);
422
+
423
+ // NEW: Export logs
424
+ const logs = logger.exportLogs();
425
+ logger.downloadLogs('debug-logs.json'); // Download as file
347
426
  ```
348
427
 
349
428
  ## TypeScript Support
@@ -508,6 +587,33 @@ Enable debug logging to troubleshoot issues:
508
587
 
509
588
  ## Migration Guide
510
589
 
590
+ ### From v2.x to v3.0
591
+
592
+ v3.0 includes breaking changes. See [MIGRATION_GUIDE_v3.md](./MIGRATION_GUIDE_v3.md) for complete details.
593
+
594
+ **Quick migration:**
595
+
596
+ ```bash
597
+ # 1. Update dependencies
598
+ npm install @chemmangat/msal-next@3.0.0
599
+ npm install @azure/msal-browser@^4.0.0
600
+ npm install @azure/msal-react@^3.0.0
601
+ npm install next@^14.1.0
602
+
603
+ # 2. Update Node.js to 18+
604
+ node --version # Should be v18.0.0+
605
+
606
+ # 3. Remove deprecated ServerSession.accessToken usage
607
+ # Before:
608
+ const session = await getServerSession();
609
+ const token = session.accessToken; // ❌ Removed
610
+
611
+ # After:
612
+ 'use client';
613
+ const { acquireToken } = useMsalAuth();
614
+ const token = await acquireToken(['User.Read']); // ✅
615
+ ```
616
+
511
617
  ### From v1.x to v2.x
512
618
 
513
619
  v2.0 is backward compatible with v1.x. New features are additive:
@@ -542,6 +648,19 @@ MIT © [Chemmangat](https://github.com/chemmangat)
542
648
  - 📖 [Documentation](https://github.com/chemmangat/msal-next#readme)
543
649
  - 🐛 [Issue Tracker](https://github.com/chemmangat/msal-next/issues)
544
650
  - 💬 [Discussions](https://github.com/chemmangat/msal-next/discussions)
651
+ - 🚀 [CLI Tool](https://www.npmjs.com/package/@chemmangat/msal-next-cli)
652
+ - 📋 [Migration Guide](./MIGRATION_GUIDE_v3.md)
653
+ - 🧪 [Testing Guide](./TESTING_GUIDE.md)
654
+
655
+ ## What's Coming in v3.1
656
+
657
+ - 🧪 80%+ test coverage
658
+ - 📚 6+ additional examples
659
+ - ⚡ Performance optimizations
660
+ - 🔒 Security audit
661
+ - 🆕 New hooks and components
662
+
663
+ [See Roadmap](./V3_ROADMAP.md) for details.
545
664
 
546
665
  ## Acknowledgments
547
666
 
package/dist/index.d.mts CHANGED
@@ -661,18 +661,94 @@ interface DebugLoggerConfig {
661
661
  * @default 'info'
662
662
  */
663
663
  level?: 'error' | 'warn' | 'info' | 'debug';
664
+ /**
665
+ * Enable performance tracking
666
+ * @default false
667
+ */
668
+ enablePerformance?: boolean;
669
+ /**
670
+ * Enable network request logging
671
+ * @default false
672
+ */
673
+ enableNetworkLogs?: boolean;
674
+ /**
675
+ * Maximum log history size
676
+ * @default 100
677
+ */
678
+ maxHistorySize?: number;
679
+ }
680
+ /**
681
+ * Log entry for history tracking
682
+ */
683
+ interface LogEntry {
684
+ timestamp: number;
685
+ level: string;
686
+ message: string;
687
+ data?: any;
688
+ }
689
+ /**
690
+ * Performance timing entry
691
+ */
692
+ interface PerformanceTiming {
693
+ operation: string;
694
+ startTime: number;
695
+ endTime?: number;
696
+ duration?: number;
664
697
  }
665
698
  declare class DebugLogger {
666
699
  private config;
700
+ private logHistory;
701
+ private performanceTimings;
667
702
  constructor(config?: DebugLoggerConfig);
668
703
  private shouldLog;
669
704
  private formatMessage;
705
+ private addToHistory;
670
706
  error(message: string, data?: any): void;
671
707
  warn(message: string, data?: any): void;
672
708
  info(message: string, data?: any): void;
673
709
  debug(message: string, data?: any): void;
674
710
  group(label: string): void;
675
711
  groupEnd(): void;
712
+ /**
713
+ * Start performance timing for an operation
714
+ */
715
+ startTiming(operation: string): void;
716
+ /**
717
+ * End performance timing for an operation
718
+ */
719
+ endTiming(operation: string): number | undefined;
720
+ /**
721
+ * Log network request
722
+ */
723
+ logRequest(method: string, url: string, options?: any): void;
724
+ /**
725
+ * Log network response
726
+ */
727
+ logResponse(method: string, url: string, status: number, data?: any): void;
728
+ /**
729
+ * Get log history
730
+ */
731
+ getHistory(): LogEntry[];
732
+ /**
733
+ * Get performance timings
734
+ */
735
+ getPerformanceTimings(): PerformanceTiming[];
736
+ /**
737
+ * Clear log history
738
+ */
739
+ clearHistory(): void;
740
+ /**
741
+ * Clear performance timings
742
+ */
743
+ clearTimings(): void;
744
+ /**
745
+ * Export logs as JSON
746
+ */
747
+ exportLogs(): string;
748
+ /**
749
+ * Download logs as a file
750
+ */
751
+ downloadLogs(filename?: string): void;
676
752
  setEnabled(enabled: boolean): void;
677
753
  setLevel(level: DebugLoggerConfig['level']): void;
678
754
  }
@@ -681,8 +757,22 @@ declare class DebugLogger {
681
757
  *
682
758
  * @example
683
759
  * ```tsx
684
- * const logger = getDebugLogger({ enabled: true, level: 'debug' });
760
+ * const logger = getDebugLogger({
761
+ * enabled: true,
762
+ * level: 'debug',
763
+ * enablePerformance: true,
764
+ * enableNetworkLogs: true
765
+ * });
766
+ *
767
+ * logger.startTiming('token-acquisition');
768
+ * // ... do work
769
+ * logger.endTiming('token-acquisition');
770
+ *
771
+ * logger.logRequest('GET', '/me');
685
772
  * logger.info('User logged in', { username: 'user@example.com' });
773
+ *
774
+ * // Export logs for debugging
775
+ * logger.downloadLogs();
686
776
  * ```
687
777
  */
688
778
  declare function getDebugLogger(config?: DebugLoggerConfig): DebugLogger;
@@ -691,7 +781,10 @@ declare function getDebugLogger(config?: DebugLoggerConfig): DebugLogger;
691
781
  *
692
782
  * @example
693
783
  * ```tsx
694
- * const logger = createScopedLogger('GraphAPI', { enabled: true });
784
+ * const logger = createScopedLogger('GraphAPI', {
785
+ * enabled: true,
786
+ * enableNetworkLogs: true
787
+ * });
695
788
  * logger.info('Fetching user profile');
696
789
  * ```
697
790
  */
package/dist/index.d.ts CHANGED
@@ -661,18 +661,94 @@ interface DebugLoggerConfig {
661
661
  * @default 'info'
662
662
  */
663
663
  level?: 'error' | 'warn' | 'info' | 'debug';
664
+ /**
665
+ * Enable performance tracking
666
+ * @default false
667
+ */
668
+ enablePerformance?: boolean;
669
+ /**
670
+ * Enable network request logging
671
+ * @default false
672
+ */
673
+ enableNetworkLogs?: boolean;
674
+ /**
675
+ * Maximum log history size
676
+ * @default 100
677
+ */
678
+ maxHistorySize?: number;
679
+ }
680
+ /**
681
+ * Log entry for history tracking
682
+ */
683
+ interface LogEntry {
684
+ timestamp: number;
685
+ level: string;
686
+ message: string;
687
+ data?: any;
688
+ }
689
+ /**
690
+ * Performance timing entry
691
+ */
692
+ interface PerformanceTiming {
693
+ operation: string;
694
+ startTime: number;
695
+ endTime?: number;
696
+ duration?: number;
664
697
  }
665
698
  declare class DebugLogger {
666
699
  private config;
700
+ private logHistory;
701
+ private performanceTimings;
667
702
  constructor(config?: DebugLoggerConfig);
668
703
  private shouldLog;
669
704
  private formatMessage;
705
+ private addToHistory;
670
706
  error(message: string, data?: any): void;
671
707
  warn(message: string, data?: any): void;
672
708
  info(message: string, data?: any): void;
673
709
  debug(message: string, data?: any): void;
674
710
  group(label: string): void;
675
711
  groupEnd(): void;
712
+ /**
713
+ * Start performance timing for an operation
714
+ */
715
+ startTiming(operation: string): void;
716
+ /**
717
+ * End performance timing for an operation
718
+ */
719
+ endTiming(operation: string): number | undefined;
720
+ /**
721
+ * Log network request
722
+ */
723
+ logRequest(method: string, url: string, options?: any): void;
724
+ /**
725
+ * Log network response
726
+ */
727
+ logResponse(method: string, url: string, status: number, data?: any): void;
728
+ /**
729
+ * Get log history
730
+ */
731
+ getHistory(): LogEntry[];
732
+ /**
733
+ * Get performance timings
734
+ */
735
+ getPerformanceTimings(): PerformanceTiming[];
736
+ /**
737
+ * Clear log history
738
+ */
739
+ clearHistory(): void;
740
+ /**
741
+ * Clear performance timings
742
+ */
743
+ clearTimings(): void;
744
+ /**
745
+ * Export logs as JSON
746
+ */
747
+ exportLogs(): string;
748
+ /**
749
+ * Download logs as a file
750
+ */
751
+ downloadLogs(filename?: string): void;
676
752
  setEnabled(enabled: boolean): void;
677
753
  setLevel(level: DebugLoggerConfig['level']): void;
678
754
  }
@@ -681,8 +757,22 @@ declare class DebugLogger {
681
757
  *
682
758
  * @example
683
759
  * ```tsx
684
- * const logger = getDebugLogger({ enabled: true, level: 'debug' });
760
+ * const logger = getDebugLogger({
761
+ * enabled: true,
762
+ * level: 'debug',
763
+ * enablePerformance: true,
764
+ * enableNetworkLogs: true
765
+ * });
766
+ *
767
+ * logger.startTiming('token-acquisition');
768
+ * // ... do work
769
+ * logger.endTiming('token-acquisition');
770
+ *
771
+ * logger.logRequest('GET', '/me');
685
772
  * logger.info('User logged in', { username: 'user@example.com' });
773
+ *
774
+ * // Export logs for debugging
775
+ * logger.downloadLogs();
686
776
  * ```
687
777
  */
688
778
  declare function getDebugLogger(config?: DebugLoggerConfig): DebugLogger;
@@ -691,7 +781,10 @@ declare function getDebugLogger(config?: DebugLoggerConfig): DebugLogger;
691
781
  *
692
782
  * @example
693
783
  * ```tsx
694
- * const logger = createScopedLogger('GraphAPI', { enabled: true });
784
+ * const logger = createScopedLogger('GraphAPI', {
785
+ * enabled: true,
786
+ * enableNetworkLogs: true
787
+ * });
695
788
  * logger.info('Fetching user profile');
696
789
  * ```
697
790
  */
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var msalReact=require('@azure/msal-react'),msalBrowser=require('@azure/msal-browser'),react=require('react'),jsxRuntime=require('react/jsx-runtime'),server=require('next/server');function z(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function B(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function C(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function G(r,e){try{let t=new URL(r);return e.some(o=>{let n=new URL(o);return t.origin===n.origin})}catch{return false}}function oe(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function me(r){return Array.isArray(r)&&r.every(oe)}function V(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:n,postLogoutRedirectUri:u,cacheLocation:d="sessionStorage",storeAuthStateInCookie:l=false,navigateToLoginRequestUrl:c=true,enableLogging:s=false,loggerCallback:h,allowedRedirectUris:p}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let m=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},g=typeof window<"u"?window.location.origin:"http://localhost:3000",y=n||g;if(p&&p.length>0){if(!G(y,p))throw new Error(`@chemmangat/msal-next: redirectUri "${y}" is not in the allowed list`);let i=u||y;if(!G(i,p))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${i}" is not in the allowed list`)}return {auth:{clientId:e,authority:m(),redirectUri:y,postLogoutRedirectUri:u||y,navigateToLoginRequestUrl:c},cache:{cacheLocation:d,storeAuthStateInCookie:l},system:{loggerOptions:{loggerCallback:h||((i,a,b)=>{if(!(b||!s))switch(i){case msalBrowser.LogLevel.Error:console.error("[MSAL]",a);break;case msalBrowser.LogLevel.Warning:console.warn("[MSAL]",a);break;case msalBrowser.LogLevel.Info:console.info("[MSAL]",a);break;case msalBrowser.LogLevel.Verbose:console.debug("[MSAL]",a);break}}),logLevel:s?msalBrowser.LogLevel.Verbose:msalBrowser.LogLevel.Error}}}}var ie=null;function Re(){return ie}function ve({children:r,loadingComponent:e,onInitialized:t,...o}){let[n,u]=react.useState(null),d=react.useRef(null);return react.useEffect(()=>{if(typeof window>"u"||d.current)return;(async()=>{try{let c=V(o),s=new msalBrowser.PublicClientApplication(c);await s.initialize(),await s.handleRedirectPromise()&&o.enableLogging&&console.log("[MSAL] Redirect authentication successful");let p=o.enableLogging||!1;s.addEventCallback(m=>{if(m.eventType===msalBrowser.EventType.LOGIN_SUCCESS&&p){let g=m.payload;console.log("[MSAL] Login successful:",g.account?.username);}m.eventType===msalBrowser.EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",m.error),m.eventType===msalBrowser.EventType.LOGOUT_SUCCESS&&p&&console.log("[MSAL] Logout successful");}),d.current=s,ie=s,u(s),t&&t(s);}catch(c){throw console.error("[MSAL] Initialization failed:",c),c}})();},[]),typeof window>"u"?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})}):n?jsxRuntime.jsx(msalReact.MsalProvider,{instance:n,children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})})}var _=new Map;function A(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=msalReact.useMsal(),n=msalReact.useAccount(t[0]||null),u=react.useRef(false),d=react.useMemo(()=>t.length>0,[t]),l=react.useCallback(async(i=r)=>{try{let a={scopes:i,prompt:"select_account"};await e.loginPopup(a);}catch(a){throw console.error("[MSAL] Login popup failed:",a),a}},[e,r]),c=react.useCallback(async(i=r)=>{try{let a={scopes:i,prompt:"select_account"};await e.loginRedirect(a);}catch(a){throw console.error("[MSAL] Login redirect failed:",a),a}},[e,r]),s=react.useCallback(async()=>{try{await e.logoutPopup({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout popup failed:",i),i}},[e,n]),h=react.useCallback(async()=>{try{await e.logoutRedirect({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout redirect failed:",i),i}},[e,n]),p=react.useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let a={scopes:i,account:n,forceRefresh:!1};return (await e.acquireTokenSilent(a)).accessToken}catch(a){throw console.error("[MSAL] Silent token acquisition failed:",a),a}},[e,n,r]),m=react.useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");if(u.current)throw new Error("[MSAL] Popup already in progress. Please wait.");try{u.current=!0;let a={scopes:i,account:n};return (await e.acquireTokenPopup(a)).accessToken}catch(a){throw console.error("[MSAL] Token popup acquisition failed:",a),a}finally{u.current=false;}},[e,n,r]),g=react.useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let a={scopes:i,account:n};await e.acquireTokenRedirect(a);}catch(a){throw console.error("[MSAL] Token redirect acquisition failed:",a),a}},[e,n,r]),y=react.useCallback(async(i=r)=>{let a=`${n?.homeAccountId||"anonymous"}-${i.sort().join(",")}`,b=_.get(a);if(b)return b;let v=(async()=>{try{return await p(i)}catch{return console.warn("[MSAL] Silent token acquisition failed, falling back to popup"),await m(i)}finally{_.delete(a);}})();return _.set(a,v),v},[p,m,r,n]),f=react.useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:n,accounts:t,isAuthenticated:d,inProgress:o!==msalBrowser.InteractionStatus.None,loginPopup:l,loginRedirect:c,logoutPopup:s,logoutRedirect:h,acquireToken:y,acquireTokenSilent:p,acquireTokenPopup:m,acquireTokenRedirect:g,clearSession:f}}function Le({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",useRedirect:o=false,scopes:n,className:u="",style:d,onSuccess:l,onError:c}){let{loginPopup:s,loginRedirect:h,inProgress:p}=A(),m=async()=>{try{o?await h(n):await s(n),l?.();}catch(i){c?.(i);}},g={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},f={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:p?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:p?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...g[t],...d};return jsxRuntime.jsxs("button",{onClick:m,disabled:p,className:u,style:f,"aria-label":r,children:[jsxRuntime.jsx(Me,{}),jsxRuntime.jsx("span",{children:r})]})}function Me(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function Ue({text:r="Sign out",variant:e="dark",size:t="medium",useRedirect:o=false,className:n="",style:u,onSuccess:d,onError:l}){let{logoutPopup:c,logoutRedirect:s,inProgress:h}=A(),p=async()=>{try{o?await s():await c(),d?.();}catch(f){l?.(f);}},m={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},y={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:h?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:h?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...m[t],...u};return jsxRuntime.jsxs("button",{onClick:p,disabled:h,className:n,style:y,"aria-label":r,children:[jsxRuntime.jsx(ke,{}),jsxRuntime.jsx("span",{children:r})]})}function ke(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function U(){let{acquireToken:r}=A(),e=react.useCallback(async(l,c={})=>{let{scopes:s=["User.Read"],version:h="v1.0",debug:p=false,...m}=c;try{let g=await r(s),y=`https://graph.microsoft.com/${h}`,f=l.startsWith("http")?l:`${y}${l.startsWith("/")?l:`/${l}`}`;p&&console.log("[GraphAPI] Request:",{url:f,method:m.method||"GET"});let i=await fetch(f,{...m,headers:{Authorization:`Bearer ${g}`,"Content-Type":"application/json",...m.headers}});if(!i.ok){let b=await i.text(),v=`Graph API error (${i.status}): ${b}`;throw new Error(v)}if(i.status===204||i.headers.get("content-length")==="0")return null;let a=await i.json();return p&&console.log("[GraphAPI] Response:",a),a}catch(g){let y=C(g);throw console.error("[GraphAPI] Request failed:",y),new Error(y)}},[r]),t=react.useCallback((l,c={})=>e(l,{...c,method:"GET"}),[e]),o=react.useCallback((l,c,s={})=>e(l,{...s,method:"POST",body:c?JSON.stringify(c):void 0}),[e]),n=react.useCallback((l,c,s={})=>e(l,{...s,method:"PUT",body:c?JSON.stringify(c):void 0}),[e]),u=react.useCallback((l,c,s={})=>e(l,{...s,method:"PATCH",body:c?JSON.stringify(c):void 0}),[e]),d=react.useCallback((l,c={})=>e(l,{...c,method:"DELETE"}),[e]);return {get:t,post:o,put:n,patch:u,delete:d,request:e}}var R=new Map,Fe=300*1e3,ue=100;function Ie(){if(R.size>ue){let r=Array.from(R.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,R.size-ue).forEach(([t])=>{let o=R.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),R.delete(t);});}}function J(){let{isAuthenticated:r,account:e}=A(),t=U(),[o,n]=react.useState(null),[u,d]=react.useState(false),[l,c]=react.useState(null),s=react.useCallback(async()=>{if(!r||!e){n(null);return}let p=e.homeAccountId,m=R.get(p);if(m&&Date.now()-m.timestamp<Fe){n(m.data);return}d(true),c(null);try{let g=await t.get("/me",{scopes:["User.Read"]}),y;try{let i=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});i&&(y=URL.createObjectURL(i));}catch{console.debug("[UserProfile] Photo not available");}let f={id:g.id,displayName:g.displayName,givenName:g.givenName,surname:g.surname,userPrincipalName:g.userPrincipalName,mail:g.mail,jobTitle:g.jobTitle,officeLocation:g.officeLocation,mobilePhone:g.mobilePhone,businessPhones:g.businessPhones,photo:y};R.set(p,{data:f,timestamp:Date.now()}),Ie(),n(f);}catch(g){let f=C(g),i=new Error(f);c(i),console.error("[UserProfile] Failed to fetch profile:",f);}finally{d(false);}},[r,e,t]),h=react.useCallback(()=>{if(e){let p=R.get(e.homeAccountId);p?.data.photo&&URL.revokeObjectURL(p.data.photo),R.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),n(null);},[e,o]);return react.useEffect(()=>(s(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[s]),react.useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:u,error:l,refetch:s,clearCache:h}}function De({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:n}){let{profile:u,loading:d}=J(),[l,c]=react.useState(null),[s,h]=react.useState(false);react.useEffect(()=>{u?.photo&&c(u.photo);},[u?.photo]);let p=()=>{if(!u)return "?";let{givenName:y,surname:f,displayName:i}=u;if(y&&f)return `${y[0]}${f[0]}`.toUpperCase();if(i){let a=i.split(" ");return a.length>=2?`${a[0][0]}${a[a.length-1][0]}`.toUpperCase():i.substring(0,2).toUpperCase()}return "?"},m={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},g=u?.displayName||"User";return d?jsxRuntime.jsx("div",{className:e,style:{...m,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsxRuntime.jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):l&&!s?jsxRuntime.jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:jsxRuntime.jsx("img",{src:l,alt:g,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),n&&c(n);}})}):jsxRuntime.jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:p()})}function Oe({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:n,renderUnauthenticated:u}){let{isAuthenticated:d,inProgress:l,account:c}=A(),s={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(l)return o?jsxRuntime.jsx(jsxRuntime.Fragment,{children:o()}):jsxRuntime.jsxs("div",{className:r,style:{...s,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(Z,{color:"#FFA500"}),jsxRuntime.jsx("span",{children:"Loading..."})]});if(d){let h=c?.username||c?.name||"User";return n?jsxRuntime.jsx(jsxRuntime.Fragment,{children:n(h)}):jsxRuntime.jsxs("div",{className:r,style:{...s,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(Z,{color:"#28A745"}),jsxRuntime.jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return u?jsxRuntime.jsx(jsxRuntime.Fragment,{children:u()}):jsxRuntime.jsxs("div",{className:r,style:{...s,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(Z,{color:"#DC3545"}),jsxRuntime.jsx("span",{children:"Not authenticated"})]})}function Z({color:r}){return jsxRuntime.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsxRuntime.jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function Q({children:r,loadingComponent:e,fallbackComponent:t,useRedirect:o=true,scopes:n,onAuthRequired:u}){let{isAuthenticated:d,inProgress:l,loginRedirect:c,loginPopup:s}=A();return react.useEffect(()=>{!d&&!l&&(u?.(),(async()=>{try{o?await c(n):await s(n);}catch(p){console.error("[AuthGuard] Authentication failed:",p);}})());},[d,l,o,n,c,s,u]),l?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Authenticating..."})}):d?jsxRuntime.jsx(jsxRuntime.Fragment,{children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:t||jsxRuntime.jsx("div",{children:"Redirecting to login..."})})}var ee=class extends react.Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:n,debug:u}=this.props;u&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),n?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:n,fallback:u}=this.props;return t&&o?u?u(o,this.reset):jsxRuntime.jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsxRuntime.jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsxRuntime.jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsxRuntime.jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):n}};var w=new Map,Be=300*1e3,de=100;function Ve(r){r?w.delete(r):w.clear();}function We(){if(w.size>de){let r=Array.from(w.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,w.size-de).forEach(([t])=>w.delete(t));}}function _e(){let{isAuthenticated:r,account:e}=A(),t=U(),[o,n]=react.useState([]),[u,d]=react.useState([]),[l,c]=react.useState(false),[s,h]=react.useState(null),p=react.useCallback(async()=>{if(!r||!e){n([]),d([]);return}let i=e.homeAccountId,a=w.get(i);if(a&&Date.now()-a.timestamp<Be){n(a.roles),d(a.groups);return}c(true),h(null);try{let v=e.idTokenClaims?.roles||[],O=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(te=>te.id);w.set(i,{roles:v,groups:O,timestamp:Date.now()}),We(),n(v),d(O);}catch(b){let D=C(b),O=new Error(D);h(O),console.error("[Roles] Failed to fetch roles/groups:",D);let he=e.idTokenClaims?.roles||[];n(he);}finally{c(false);}},[r,e,t]),m=react.useCallback(i=>o.includes(i),[o]),g=react.useCallback(i=>u.includes(i),[u]),y=react.useCallback(i=>i.some(a=>o.includes(a)),[o]),f=react.useCallback(i=>i.every(a=>o.includes(a)),[o]);return react.useEffect(()=>(p(),()=>{e&&Ve(e.homeAccountId);}),[p,e]),{roles:o,groups:u,loading:l,error:s,hasRole:m,hasGroup:g,hasAnyRole:y,hasAllRoles:f,refetch:p}}function je(r,e={}){let{displayName:t,...o}=e,n=u=>jsxRuntime.jsx(Q,{...o,children:jsxRuntime.jsx(r,{...u})});return n.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,n}async function fe(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:n=1e4,backoffMultiplier:u=2,debug:d=false}=e,l,c=o;for(let s=0;s<=t;s++)try{return d&&s>0&&console.log(`[TokenRetry] Attempt ${s+1}/${t+1}`),await r()}catch(h){if(l=h,s===t){d&&console.error("[TokenRetry] All retry attempts failed");break}if(!Je(h))throw d&&console.log("[TokenRetry] Non-retryable error, aborting"),h;d&&console.warn(`[TokenRetry] Attempt ${s+1} failed, retrying in ${c}ms...`),await Ze(c),c=Math.min(c*u,n);}throw l}function Je(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function Ze(r){return new Promise(e=>setTimeout(e,r))}function He(r,e={}){return (...t)=>fe(()=>r(...t),e)}var $=class{constructor(e={}){this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info"};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let n=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",u=this.config.prefix,d=`[${e.toUpperCase()}]`,l=`${n} ${u} ${d} ${t}`;return o!==void 0&&(l+=`
2
- `+JSON.stringify(o,null,2)),l}error(e,t){this.shouldLog("error")&&console.error(this.formatMessage("error",e,t));}warn(e,t){this.shouldLog("warn")&&console.warn(this.formatMessage("warn",e,t));}info(e,t){this.shouldLog("info")&&console.info(this.formatMessage("info",e,t));}debug(e,t){this.shouldLog("debug")&&console.debug(this.formatMessage("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},N=null;function Ke(r){return N?r&&(r.enabled!==void 0&&N.setEnabled(r.enabled),r.level&&N.setLevel(r.level)):N=new $(r),N}function Xe(r,e){return new $({...e,prefix:`[MSAL-Next:${r}]`})}function Qe(r={}){let{protectedRoutes:e=[],publicOnlyRoutes:t=[],loginPath:o="/login",redirectAfterLogin:n="/",sessionCookie:u="msal.account",isAuthenticated:d,debug:l=false}=r;return async function(s){let{pathname:h}=s.nextUrl;l&&console.log("[AuthMiddleware] Processing:",h);let p=false;d?p=await d(s):p=!!s.cookies.get(u)?.value,l&&console.log("[AuthMiddleware] Authenticated:",p);let m=e.some(f=>h.startsWith(f)),g=t.some(f=>h.startsWith(f));if(m&&!p){l&&console.log("[AuthMiddleware] Redirecting to login");let f=s.nextUrl.clone();return f.pathname=o,f.searchParams.set("returnUrl",h),server.NextResponse.redirect(f)}if(g&&p){l&&console.log("[AuthMiddleware] Redirecting to home");let f=s.nextUrl.searchParams.get("returnUrl"),i=s.nextUrl.clone();return i.pathname=f||n,i.searchParams.delete("returnUrl"),server.NextResponse.redirect(i)}let y=server.NextResponse.next();if(p){y.headers.set("x-msal-authenticated","true");try{let f=s.cookies.get(u);if(f?.value){let i=z(f.value,B);i?.username&&y.headers.set("x-msal-username",i.username);}}catch{l&&console.warn("[AuthMiddleware] Failed to parse session data");}}return y}}Object.defineProperty(exports,"useAccount",{enumerable:true,get:function(){return msalReact.useAccount}});Object.defineProperty(exports,"useIsAuthenticated",{enumerable:true,get:function(){return msalReact.useIsAuthenticated}});Object.defineProperty(exports,"useMsal",{enumerable:true,get:function(){return msalReact.useMsal}});exports.AuthGuard=Q;exports.AuthStatus=Oe;exports.ErrorBoundary=ee;exports.MicrosoftSignInButton=Le;exports.MsalAuthProvider=ve;exports.SignOutButton=Ue;exports.UserAvatar=De;exports.createAuthMiddleware=Qe;exports.createMsalConfig=V;exports.createRetryWrapper=He;exports.createScopedLogger=Xe;exports.getDebugLogger=Ke;exports.getMsalInstance=Re;exports.isValidAccountData=B;exports.isValidRedirectUri=G;exports.isValidScope=oe;exports.retryWithBackoff=fe;exports.safeJsonParse=z;exports.sanitizeError=C;exports.useGraphApi=U;exports.useMsalAuth=A;exports.useRoles=_e;exports.useUserProfile=J;exports.validateScopes=me;exports.withAuth=je;
1
+ 'use strict';var msalReact=require('@azure/msal-react'),msalBrowser=require('@azure/msal-browser'),react=require('react'),jsxRuntime=require('react/jsx-runtime'),server=require('next/server');function z(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function B(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function S(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function G(r,e){try{let t=new URL(r);return e.some(o=>{let n=new URL(o);return t.origin===n.origin})}catch{return false}}function oe(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function me(r){return Array.isArray(r)&&r.every(oe)}function H(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:n,postLogoutRedirectUri:a,cacheLocation:d="sessionStorage",storeAuthStateInCookie:c=false,navigateToLoginRequestUrl:u=true,enableLogging:s=false,loggerCallback:h,allowedRedirectUris:p}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let m=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},g=typeof window<"u"?window.location.origin:"http://localhost:3000",y=n||g;if(p&&p.length>0){if(!G(y,p))throw new Error(`@chemmangat/msal-next: redirectUri "${y}" is not in the allowed list`);let i=a||y;if(!G(i,p))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${i}" is not in the allowed list`)}return {auth:{clientId:e,authority:m(),redirectUri:y,postLogoutRedirectUri:a||y,navigateToLoginRequestUrl:u},cache:{cacheLocation:d,storeAuthStateInCookie:c},system:{loggerOptions:{loggerCallback:h||((i,l,A)=>{if(!(A||!s))switch(i){case msalBrowser.LogLevel.Error:console.error("[MSAL]",l);break;case msalBrowser.LogLevel.Warning:console.warn("[MSAL]",l);break;case msalBrowser.LogLevel.Info:console.info("[MSAL]",l);break;case msalBrowser.LogLevel.Verbose:console.debug("[MSAL]",l);break}}),logLevel:s?msalBrowser.LogLevel.Verbose:msalBrowser.LogLevel.Error}}}}var ie=null;function Pe(){return ie}function ve({children:r,loadingComponent:e,onInitialized:t,...o}){let[n,a]=react.useState(null),d=react.useRef(null);return react.useEffect(()=>{if(typeof window>"u"||d.current)return;(async()=>{try{let u=H(o),s=new msalBrowser.PublicClientApplication(u);await s.initialize(),await s.handleRedirectPromise()&&o.enableLogging&&console.log("[MSAL] Redirect authentication successful");let p=o.enableLogging||!1;s.addEventCallback(m=>{if(m.eventType===msalBrowser.EventType.LOGIN_SUCCESS&&p){let g=m.payload;console.log("[MSAL] Login successful:",g.account?.username);}m.eventType===msalBrowser.EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",m.error),m.eventType===msalBrowser.EventType.LOGOUT_SUCCESS&&p&&console.log("[MSAL] Logout successful");}),d.current=s,ie=s,a(s),t&&t(s);}catch(u){throw console.error("[MSAL] Initialization failed:",u),u}})();},[]),typeof window>"u"?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})}):n?jsxRuntime.jsx(msalReact.MsalProvider,{instance:n,children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})})}var W=new Map;function b(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=msalReact.useMsal(),n=msalReact.useAccount(t[0]||null),a=react.useRef(false),d=react.useMemo(()=>t.length>0,[t]),c=react.useCallback(async(i=r)=>{try{let l={scopes:i,prompt:"select_account"};await e.loginPopup(l);}catch(l){throw console.error("[MSAL] Login popup failed:",l),l}},[e,r]),u=react.useCallback(async(i=r)=>{try{let l={scopes:i,prompt:"select_account"};await e.loginRedirect(l);}catch(l){throw console.error("[MSAL] Login redirect failed:",l),l}},[e,r]),s=react.useCallback(async()=>{try{await e.logoutPopup({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout popup failed:",i),i}},[e,n]),h=react.useCallback(async()=>{try{await e.logoutRedirect({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout redirect failed:",i),i}},[e,n]),p=react.useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let l={scopes:i,account:n,forceRefresh:!1};return (await e.acquireTokenSilent(l)).accessToken}catch(l){throw console.error("[MSAL] Silent token acquisition failed:",l),l}},[e,n,r]),m=react.useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");if(a.current)throw new Error("[MSAL] Popup already in progress. Please wait.");try{a.current=!0;let l={scopes:i,account:n};return (await e.acquireTokenPopup(l)).accessToken}catch(l){throw console.error("[MSAL] Token popup acquisition failed:",l),l}finally{a.current=false;}},[e,n,r]),g=react.useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let l={scopes:i,account:n};await e.acquireTokenRedirect(l);}catch(l){throw console.error("[MSAL] Token redirect acquisition failed:",l),l}},[e,n,r]),y=react.useCallback(async(i=r)=>{let l=`${n?.homeAccountId||"anonymous"}-${i.sort().join(",")}`,A=W.get(l);if(A)return A;let v=(async()=>{try{return await p(i)}catch{return console.warn("[MSAL] Silent token acquisition failed, falling back to popup"),await m(i)}finally{W.delete(l);}})();return W.set(l,v),v},[p,m,r,n]),f=react.useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:n,accounts:t,isAuthenticated:d,inProgress:o!==msalBrowser.InteractionStatus.None,loginPopup:c,loginRedirect:u,logoutPopup:s,logoutRedirect:h,acquireToken:y,acquireTokenSilent:p,acquireTokenPopup:m,acquireTokenRedirect:g,clearSession:f}}function Le({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",useRedirect:o=false,scopes:n,className:a="",style:d,onSuccess:c,onError:u}){let{loginPopup:s,loginRedirect:h,inProgress:p}=b(),m=async()=>{try{o?await h(n):await s(n),c?.();}catch(i){u?.(i);}},g={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},f={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:p?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:p?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...g[t],...d};return jsxRuntime.jsxs("button",{onClick:m,disabled:p,className:a,style:f,"aria-label":r,children:[jsxRuntime.jsx(ke,{}),jsxRuntime.jsx("span",{children:r})]})}function ke(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function Ue({text:r="Sign out",variant:e="dark",size:t="medium",useRedirect:o=false,className:n="",style:a,onSuccess:d,onError:c}){let{logoutPopup:u,logoutRedirect:s,inProgress:h}=b(),p=async()=>{try{o?await s():await u(),d?.();}catch(f){c?.(f);}},m={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},y={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:h?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:h?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...m[t],...a};return jsxRuntime.jsxs("button",{onClick:p,disabled:h,className:n,style:y,"aria-label":r,children:[jsxRuntime.jsx(Me,{}),jsxRuntime.jsx("span",{children:r})]})}function Me(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function U(){let{acquireToken:r}=b(),e=react.useCallback(async(c,u={})=>{let{scopes:s=["User.Read"],version:h="v1.0",debug:p=false,...m}=u;try{let g=await r(s),y=`https://graph.microsoft.com/${h}`,f=c.startsWith("http")?c:`${y}${c.startsWith("/")?c:`/${c}`}`;p&&console.log("[GraphAPI] Request:",{url:f,method:m.method||"GET"});let i=await fetch(f,{...m,headers:{Authorization:`Bearer ${g}`,"Content-Type":"application/json",...m.headers}});if(!i.ok){let A=await i.text(),v=`Graph API error (${i.status}): ${A}`;throw new Error(v)}if(i.status===204||i.headers.get("content-length")==="0")return null;let l=await i.json();return p&&console.log("[GraphAPI] Response:",l),l}catch(g){let y=S(g);throw console.error("[GraphAPI] Request failed:",y),new Error(y)}},[r]),t=react.useCallback((c,u={})=>e(c,{...u,method:"GET"}),[e]),o=react.useCallback((c,u,s={})=>e(c,{...s,method:"POST",body:u?JSON.stringify(u):void 0}),[e]),n=react.useCallback((c,u,s={})=>e(c,{...s,method:"PUT",body:u?JSON.stringify(u):void 0}),[e]),a=react.useCallback((c,u,s={})=>e(c,{...s,method:"PATCH",body:u?JSON.stringify(u):void 0}),[e]),d=react.useCallback((c,u={})=>e(c,{...u,method:"DELETE"}),[e]);return {get:t,post:o,put:n,patch:a,delete:d,request:e}}var P=new Map,Fe=300*1e3,ue=100;function Ne(){if(P.size>ue){let r=Array.from(P.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,P.size-ue).forEach(([t])=>{let o=P.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),P.delete(t);});}}function j(){let{isAuthenticated:r,account:e}=b(),t=U(),[o,n]=react.useState(null),[a,d]=react.useState(false),[c,u]=react.useState(null),s=react.useCallback(async()=>{if(!r||!e){n(null);return}let p=e.homeAccountId,m=P.get(p);if(m&&Date.now()-m.timestamp<Fe){n(m.data);return}d(true),u(null);try{let g=await t.get("/me",{scopes:["User.Read"]}),y;try{let i=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});i&&(y=URL.createObjectURL(i));}catch{console.debug("[UserProfile] Photo not available");}let f={id:g.id,displayName:g.displayName,givenName:g.givenName,surname:g.surname,userPrincipalName:g.userPrincipalName,mail:g.mail,jobTitle:g.jobTitle,officeLocation:g.officeLocation,mobilePhone:g.mobilePhone,businessPhones:g.businessPhones,photo:y};P.set(p,{data:f,timestamp:Date.now()}),Ne(),n(f);}catch(g){let f=S(g),i=new Error(f);u(i),console.error("[UserProfile] Failed to fetch profile:",f);}finally{d(false);}},[r,e,t]),h=react.useCallback(()=>{if(e){let p=P.get(e.homeAccountId);p?.data.photo&&URL.revokeObjectURL(p.data.photo),P.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),n(null);},[e,o]);return react.useEffect(()=>(s(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[s]),react.useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:a,error:c,refetch:s,clearCache:h}}function De({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:n}){let{profile:a,loading:d}=j(),[c,u]=react.useState(null),[s,h]=react.useState(false);react.useEffect(()=>{a?.photo&&u(a.photo);},[a?.photo]);let p=()=>{if(!a)return "?";let{givenName:y,surname:f,displayName:i}=a;if(y&&f)return `${y[0]}${f[0]}`.toUpperCase();if(i){let l=i.split(" ");return l.length>=2?`${l[0][0]}${l[l.length-1][0]}`.toUpperCase():i.substring(0,2).toUpperCase()}return "?"},m={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},g=a?.displayName||"User";return d?jsxRuntime.jsx("div",{className:e,style:{...m,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsxRuntime.jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):c&&!s?jsxRuntime.jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:jsxRuntime.jsx("img",{src:c,alt:g,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),n&&u(n);}})}):jsxRuntime.jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:p()})}function Oe({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:n,renderUnauthenticated:a}){let{isAuthenticated:d,inProgress:c,account:u}=b(),s={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(c)return o?jsxRuntime.jsx(jsxRuntime.Fragment,{children:o()}):jsxRuntime.jsxs("div",{className:r,style:{...s,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(J,{color:"#FFA500"}),jsxRuntime.jsx("span",{children:"Loading..."})]});if(d){let h=u?.username||u?.name||"User";return n?jsxRuntime.jsx(jsxRuntime.Fragment,{children:n(h)}):jsxRuntime.jsxs("div",{className:r,style:{...s,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(J,{color:"#28A745"}),jsxRuntime.jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return a?jsxRuntime.jsx(jsxRuntime.Fragment,{children:a()}):jsxRuntime.jsxs("div",{className:r,style:{...s,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(J,{color:"#DC3545"}),jsxRuntime.jsx("span",{children:"Not authenticated"})]})}function J({color:r}){return jsxRuntime.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsxRuntime.jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function Q({children:r,loadingComponent:e,fallbackComponent:t,useRedirect:o=true,scopes:n,onAuthRequired:a}){let{isAuthenticated:d,inProgress:c,loginRedirect:u,loginPopup:s}=b();return react.useEffect(()=>{!d&&!c&&(a?.(),(async()=>{try{o?await u(n):await s(n);}catch(p){console.error("[AuthGuard] Authentication failed:",p);}})());},[d,c,o,n,u,s,a]),c?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Authenticating..."})}):d?jsxRuntime.jsx(jsxRuntime.Fragment,{children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:t||jsxRuntime.jsx("div",{children:"Redirecting to login..."})})}var ee=class extends react.Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:n,debug:a}=this.props;a&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),n?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:n,fallback:a}=this.props;return t&&o?a?a(o,this.reset):jsxRuntime.jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsxRuntime.jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsxRuntime.jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsxRuntime.jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):n}};var R=new Map,Be=300*1e3,de=100;function He(r){r?R.delete(r):R.clear();}function Ve(){if(R.size>de){let r=Array.from(R.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,R.size-de).forEach(([t])=>R.delete(t));}}function We(){let{isAuthenticated:r,account:e}=b(),t=U(),[o,n]=react.useState([]),[a,d]=react.useState([]),[c,u]=react.useState(false),[s,h]=react.useState(null),p=react.useCallback(async()=>{if(!r||!e){n([]),d([]);return}let i=e.homeAccountId,l=R.get(i);if(l&&Date.now()-l.timestamp<Be){n(l.roles),d(l.groups);return}u(true),h(null);try{let v=e.idTokenClaims?.roles||[],O=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(te=>te.id);R.set(i,{roles:v,groups:O,timestamp:Date.now()}),Ve(),n(v),d(O);}catch(A){let D=S(A),O=new Error(D);h(O),console.error("[Roles] Failed to fetch roles/groups:",D);let he=e.idTokenClaims?.roles||[];n(he);}finally{u(false);}},[r,e,t]),m=react.useCallback(i=>o.includes(i),[o]),g=react.useCallback(i=>a.includes(i),[a]),y=react.useCallback(i=>i.some(l=>o.includes(l)),[o]),f=react.useCallback(i=>i.every(l=>o.includes(l)),[o]);return react.useEffect(()=>(p(),()=>{e&&He(e.homeAccountId);}),[p,e]),{roles:o,groups:a,loading:c,error:s,hasRole:m,hasGroup:g,hasAnyRole:y,hasAllRoles:f,refetch:p}}function _e(r,e={}){let{displayName:t,...o}=e,n=a=>jsxRuntime.jsx(Q,{...o,children:jsxRuntime.jsx(r,{...a})});return n.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,n}async function fe(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:n=1e4,backoffMultiplier:a=2,debug:d=false}=e,c,u=o;for(let s=0;s<=t;s++)try{return d&&s>0&&console.log(`[TokenRetry] Attempt ${s+1}/${t+1}`),await r()}catch(h){if(c=h,s===t){d&&console.error("[TokenRetry] All retry attempts failed");break}if(!je(h))throw d&&console.log("[TokenRetry] Non-retryable error, aborting"),h;d&&console.warn(`[TokenRetry] Attempt ${s+1} failed, retrying in ${u}ms...`),await Je(u),u=Math.min(u*a,n);}throw c}function je(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function Je(r){return new Promise(e=>setTimeout(e,r))}function Ze(r,e={}){return (...t)=>fe(()=>r(...t),e)}var q=class{constructor(e={}){this.logHistory=[];this.performanceTimings=new Map;this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info",enablePerformance:e.enablePerformance??false,enableNetworkLogs:e.enableNetworkLogs??false,maxHistorySize:e.maxHistorySize??100};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let n=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",a=this.config.prefix,d=`[${e.toUpperCase()}]`,c=`${n} ${a} ${d} ${t}`;return o!==void 0&&(c+=`
2
+ `+JSON.stringify(o,null,2)),c}addToHistory(e,t,o){this.logHistory.length>=this.config.maxHistorySize&&this.logHistory.shift(),this.logHistory.push({timestamp:Date.now(),level:e,message:t,data:o});}error(e,t){this.shouldLog("error")&&(console.error(this.formatMessage("error",e,t)),this.addToHistory("error",e,t));}warn(e,t){this.shouldLog("warn")&&(console.warn(this.formatMessage("warn",e,t)),this.addToHistory("warn",e,t));}info(e,t){this.shouldLog("info")&&(console.info(this.formatMessage("info",e,t)),this.addToHistory("info",e,t));}debug(e,t){this.shouldLog("debug")&&(console.debug(this.formatMessage("debug",e,t)),this.addToHistory("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}startTiming(e){this.config.enablePerformance&&(this.performanceTimings.set(e,{operation:e,startTime:performance.now()}),this.debug(`\u23F1\uFE0F Started: ${e}`));}endTiming(e){if(this.config.enablePerformance){let t=this.performanceTimings.get(e);if(t)return t.endTime=performance.now(),t.duration=t.endTime-t.startTime,this.info(`\u23F1\uFE0F Completed: ${e} (${t.duration.toFixed(2)}ms)`),t.duration}}logRequest(e,t,o){this.config.enableNetworkLogs&&this.debug(`\u{1F310} ${e} ${t}`,o);}logResponse(e,t,o,n){if(this.config.enableNetworkLogs){let a=o>=200&&o<300?"\u2705":"\u274C";this.debug(`${a} ${e} ${t} - ${o}`,n);}}getHistory(){return [...this.logHistory]}getPerformanceTimings(){return Array.from(this.performanceTimings.values())}clearHistory(){this.logHistory=[];}clearTimings(){this.performanceTimings.clear();}exportLogs(){return JSON.stringify({config:this.config,history:this.logHistory,performanceTimings:Array.from(this.performanceTimings.values()),exportedAt:new Date().toISOString()},null,2)}downloadLogs(e="msal-next-debug-logs.json"){if(typeof window>"u")return;let t=this.exportLogs(),o=new Blob([t],{type:"application/json"}),n=URL.createObjectURL(o),a=document.createElement("a");a.href=n,a.download=e,a.click(),URL.revokeObjectURL(n);}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},I=null;function Ke(r){return I?r&&(r.enabled!==void 0&&I.setEnabled(r.enabled),r.level&&I.setLevel(r.level)):I=new q(r),I}function Xe(r,e){return new q({...e,prefix:`[MSAL-Next:${r}]`})}function Qe(r={}){let{protectedRoutes:e=[],publicOnlyRoutes:t=[],loginPath:o="/login",redirectAfterLogin:n="/",sessionCookie:a="msal.account",isAuthenticated:d,debug:c=false}=r;return async function(s){let{pathname:h}=s.nextUrl;c&&console.log("[AuthMiddleware] Processing:",h);let p=false;d?p=await d(s):p=!!s.cookies.get(a)?.value,c&&console.log("[AuthMiddleware] Authenticated:",p);let m=e.some(f=>h.startsWith(f)),g=t.some(f=>h.startsWith(f));if(m&&!p){c&&console.log("[AuthMiddleware] Redirecting to login");let f=s.nextUrl.clone();return f.pathname=o,f.searchParams.set("returnUrl",h),server.NextResponse.redirect(f)}if(g&&p){c&&console.log("[AuthMiddleware] Redirecting to home");let f=s.nextUrl.searchParams.get("returnUrl"),i=s.nextUrl.clone();return i.pathname=f||n,i.searchParams.delete("returnUrl"),server.NextResponse.redirect(i)}let y=server.NextResponse.next();if(p){y.headers.set("x-msal-authenticated","true");try{let f=s.cookies.get(a);if(f?.value){let i=z(f.value,B);i?.username&&y.headers.set("x-msal-username",i.username);}}catch{c&&console.warn("[AuthMiddleware] Failed to parse session data");}}return y}}Object.defineProperty(exports,"useAccount",{enumerable:true,get:function(){return msalReact.useAccount}});Object.defineProperty(exports,"useIsAuthenticated",{enumerable:true,get:function(){return msalReact.useIsAuthenticated}});Object.defineProperty(exports,"useMsal",{enumerable:true,get:function(){return msalReact.useMsal}});exports.AuthGuard=Q;exports.AuthStatus=Oe;exports.ErrorBoundary=ee;exports.MicrosoftSignInButton=Le;exports.MsalAuthProvider=ve;exports.SignOutButton=Ue;exports.UserAvatar=De;exports.createAuthMiddleware=Qe;exports.createMsalConfig=H;exports.createRetryWrapper=Ze;exports.createScopedLogger=Xe;exports.getDebugLogger=Ke;exports.getMsalInstance=Pe;exports.isValidAccountData=B;exports.isValidRedirectUri=G;exports.isValidScope=oe;exports.retryWithBackoff=fe;exports.safeJsonParse=z;exports.sanitizeError=S;exports.useGraphApi=U;exports.useMsalAuth=b;exports.useRoles=We;exports.useUserProfile=j;exports.validateScopes=me;exports.withAuth=_e;
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import {MsalProvider,useMsal,useAccount}from'@azure/msal-react';export{useAccount,useIsAuthenticated,useMsal}from'@azure/msal-react';import {LogLevel,PublicClientApplication,EventType,InteractionStatus}from'@azure/msal-browser';import {useState,useRef,useEffect,useMemo,useCallback,Component}from'react';import {jsx,Fragment,jsxs}from'react/jsx-runtime';import {NextResponse}from'next/server';function z(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function B(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function C(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function G(r,e){try{let t=new URL(r);return e.some(o=>{let n=new URL(o);return t.origin===n.origin})}catch{return false}}function oe(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function me(r){return Array.isArray(r)&&r.every(oe)}function V(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:n,postLogoutRedirectUri:u,cacheLocation:d="sessionStorage",storeAuthStateInCookie:l=false,navigateToLoginRequestUrl:c=true,enableLogging:s=false,loggerCallback:h,allowedRedirectUris:p}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let m=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},g=typeof window<"u"?window.location.origin:"http://localhost:3000",y=n||g;if(p&&p.length>0){if(!G(y,p))throw new Error(`@chemmangat/msal-next: redirectUri "${y}" is not in the allowed list`);let i=u||y;if(!G(i,p))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${i}" is not in the allowed list`)}return {auth:{clientId:e,authority:m(),redirectUri:y,postLogoutRedirectUri:u||y,navigateToLoginRequestUrl:c},cache:{cacheLocation:d,storeAuthStateInCookie:l},system:{loggerOptions:{loggerCallback:h||((i,a,b)=>{if(!(b||!s))switch(i){case LogLevel.Error:console.error("[MSAL]",a);break;case LogLevel.Warning:console.warn("[MSAL]",a);break;case LogLevel.Info:console.info("[MSAL]",a);break;case LogLevel.Verbose:console.debug("[MSAL]",a);break}}),logLevel:s?LogLevel.Verbose:LogLevel.Error}}}}var ie=null;function Re(){return ie}function ve({children:r,loadingComponent:e,onInitialized:t,...o}){let[n,u]=useState(null),d=useRef(null);return useEffect(()=>{if(typeof window>"u"||d.current)return;(async()=>{try{let c=V(o),s=new PublicClientApplication(c);await s.initialize(),await s.handleRedirectPromise()&&o.enableLogging&&console.log("[MSAL] Redirect authentication successful");let p=o.enableLogging||!1;s.addEventCallback(m=>{if(m.eventType===EventType.LOGIN_SUCCESS&&p){let g=m.payload;console.log("[MSAL] Login successful:",g.account?.username);}m.eventType===EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",m.error),m.eventType===EventType.LOGOUT_SUCCESS&&p&&console.log("[MSAL] Logout successful");}),d.current=s,ie=s,u(s),t&&t(s);}catch(c){throw console.error("[MSAL] Initialization failed:",c),c}})();},[]),typeof window>"u"?jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})}):n?jsx(MsalProvider,{instance:n,children:r}):jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})})}var _=new Map;function A(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=useMsal(),n=useAccount(t[0]||null),u=useRef(false),d=useMemo(()=>t.length>0,[t]),l=useCallback(async(i=r)=>{try{let a={scopes:i,prompt:"select_account"};await e.loginPopup(a);}catch(a){throw console.error("[MSAL] Login popup failed:",a),a}},[e,r]),c=useCallback(async(i=r)=>{try{let a={scopes:i,prompt:"select_account"};await e.loginRedirect(a);}catch(a){throw console.error("[MSAL] Login redirect failed:",a),a}},[e,r]),s=useCallback(async()=>{try{await e.logoutPopup({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout popup failed:",i),i}},[e,n]),h=useCallback(async()=>{try{await e.logoutRedirect({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout redirect failed:",i),i}},[e,n]),p=useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let a={scopes:i,account:n,forceRefresh:!1};return (await e.acquireTokenSilent(a)).accessToken}catch(a){throw console.error("[MSAL] Silent token acquisition failed:",a),a}},[e,n,r]),m=useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");if(u.current)throw new Error("[MSAL] Popup already in progress. Please wait.");try{u.current=!0;let a={scopes:i,account:n};return (await e.acquireTokenPopup(a)).accessToken}catch(a){throw console.error("[MSAL] Token popup acquisition failed:",a),a}finally{u.current=false;}},[e,n,r]),g=useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let a={scopes:i,account:n};await e.acquireTokenRedirect(a);}catch(a){throw console.error("[MSAL] Token redirect acquisition failed:",a),a}},[e,n,r]),y=useCallback(async(i=r)=>{let a=`${n?.homeAccountId||"anonymous"}-${i.sort().join(",")}`,b=_.get(a);if(b)return b;let v=(async()=>{try{return await p(i)}catch{return console.warn("[MSAL] Silent token acquisition failed, falling back to popup"),await m(i)}finally{_.delete(a);}})();return _.set(a,v),v},[p,m,r,n]),f=useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:n,accounts:t,isAuthenticated:d,inProgress:o!==InteractionStatus.None,loginPopup:l,loginRedirect:c,logoutPopup:s,logoutRedirect:h,acquireToken:y,acquireTokenSilent:p,acquireTokenPopup:m,acquireTokenRedirect:g,clearSession:f}}function Le({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",useRedirect:o=false,scopes:n,className:u="",style:d,onSuccess:l,onError:c}){let{loginPopup:s,loginRedirect:h,inProgress:p}=A(),m=async()=>{try{o?await h(n):await s(n),l?.();}catch(i){c?.(i);}},g={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},f={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:p?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:p?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...g[t],...d};return jsxs("button",{onClick:m,disabled:p,className:u,style:f,"aria-label":r,children:[jsx(Me,{}),jsx("span",{children:r})]})}function Me(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function Ue({text:r="Sign out",variant:e="dark",size:t="medium",useRedirect:o=false,className:n="",style:u,onSuccess:d,onError:l}){let{logoutPopup:c,logoutRedirect:s,inProgress:h}=A(),p=async()=>{try{o?await s():await c(),d?.();}catch(f){l?.(f);}},m={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},y={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:h?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:h?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...m[t],...u};return jsxs("button",{onClick:p,disabled:h,className:n,style:y,"aria-label":r,children:[jsx(ke,{}),jsx("span",{children:r})]})}function ke(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function U(){let{acquireToken:r}=A(),e=useCallback(async(l,c={})=>{let{scopes:s=["User.Read"],version:h="v1.0",debug:p=false,...m}=c;try{let g=await r(s),y=`https://graph.microsoft.com/${h}`,f=l.startsWith("http")?l:`${y}${l.startsWith("/")?l:`/${l}`}`;p&&console.log("[GraphAPI] Request:",{url:f,method:m.method||"GET"});let i=await fetch(f,{...m,headers:{Authorization:`Bearer ${g}`,"Content-Type":"application/json",...m.headers}});if(!i.ok){let b=await i.text(),v=`Graph API error (${i.status}): ${b}`;throw new Error(v)}if(i.status===204||i.headers.get("content-length")==="0")return null;let a=await i.json();return p&&console.log("[GraphAPI] Response:",a),a}catch(g){let y=C(g);throw console.error("[GraphAPI] Request failed:",y),new Error(y)}},[r]),t=useCallback((l,c={})=>e(l,{...c,method:"GET"}),[e]),o=useCallback((l,c,s={})=>e(l,{...s,method:"POST",body:c?JSON.stringify(c):void 0}),[e]),n=useCallback((l,c,s={})=>e(l,{...s,method:"PUT",body:c?JSON.stringify(c):void 0}),[e]),u=useCallback((l,c,s={})=>e(l,{...s,method:"PATCH",body:c?JSON.stringify(c):void 0}),[e]),d=useCallback((l,c={})=>e(l,{...c,method:"DELETE"}),[e]);return {get:t,post:o,put:n,patch:u,delete:d,request:e}}var R=new Map,Fe=300*1e3,ue=100;function Ie(){if(R.size>ue){let r=Array.from(R.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,R.size-ue).forEach(([t])=>{let o=R.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),R.delete(t);});}}function J(){let{isAuthenticated:r,account:e}=A(),t=U(),[o,n]=useState(null),[u,d]=useState(false),[l,c]=useState(null),s=useCallback(async()=>{if(!r||!e){n(null);return}let p=e.homeAccountId,m=R.get(p);if(m&&Date.now()-m.timestamp<Fe){n(m.data);return}d(true),c(null);try{let g=await t.get("/me",{scopes:["User.Read"]}),y;try{let i=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});i&&(y=URL.createObjectURL(i));}catch{console.debug("[UserProfile] Photo not available");}let f={id:g.id,displayName:g.displayName,givenName:g.givenName,surname:g.surname,userPrincipalName:g.userPrincipalName,mail:g.mail,jobTitle:g.jobTitle,officeLocation:g.officeLocation,mobilePhone:g.mobilePhone,businessPhones:g.businessPhones,photo:y};R.set(p,{data:f,timestamp:Date.now()}),Ie(),n(f);}catch(g){let f=C(g),i=new Error(f);c(i),console.error("[UserProfile] Failed to fetch profile:",f);}finally{d(false);}},[r,e,t]),h=useCallback(()=>{if(e){let p=R.get(e.homeAccountId);p?.data.photo&&URL.revokeObjectURL(p.data.photo),R.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),n(null);},[e,o]);return useEffect(()=>(s(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[s]),useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:u,error:l,refetch:s,clearCache:h}}function De({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:n}){let{profile:u,loading:d}=J(),[l,c]=useState(null),[s,h]=useState(false);useEffect(()=>{u?.photo&&c(u.photo);},[u?.photo]);let p=()=>{if(!u)return "?";let{givenName:y,surname:f,displayName:i}=u;if(y&&f)return `${y[0]}${f[0]}`.toUpperCase();if(i){let a=i.split(" ");return a.length>=2?`${a[0][0]}${a[a.length-1][0]}`.toUpperCase():i.substring(0,2).toUpperCase()}return "?"},m={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},g=u?.displayName||"User";return d?jsx("div",{className:e,style:{...m,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):l&&!s?jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:jsx("img",{src:l,alt:g,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),n&&c(n);}})}):jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:p()})}function Oe({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:n,renderUnauthenticated:u}){let{isAuthenticated:d,inProgress:l,account:c}=A(),s={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(l)return o?jsx(Fragment,{children:o()}):jsxs("div",{className:r,style:{...s,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsx(Z,{color:"#FFA500"}),jsx("span",{children:"Loading..."})]});if(d){let h=c?.username||c?.name||"User";return n?jsx(Fragment,{children:n(h)}):jsxs("div",{className:r,style:{...s,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsx(Z,{color:"#28A745"}),jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return u?jsx(Fragment,{children:u()}):jsxs("div",{className:r,style:{...s,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsx(Z,{color:"#DC3545"}),jsx("span",{children:"Not authenticated"})]})}function Z({color:r}){return jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function Q({children:r,loadingComponent:e,fallbackComponent:t,useRedirect:o=true,scopes:n,onAuthRequired:u}){let{isAuthenticated:d,inProgress:l,loginRedirect:c,loginPopup:s}=A();return useEffect(()=>{!d&&!l&&(u?.(),(async()=>{try{o?await c(n):await s(n);}catch(p){console.error("[AuthGuard] Authentication failed:",p);}})());},[d,l,o,n,c,s,u]),l?jsx(Fragment,{children:e||jsx("div",{children:"Authenticating..."})}):d?jsx(Fragment,{children:r}):jsx(Fragment,{children:t||jsx("div",{children:"Redirecting to login..."})})}var ee=class extends Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:n,debug:u}=this.props;u&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),n?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:n,fallback:u}=this.props;return t&&o?u?u(o,this.reset):jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):n}};var w=new Map,Be=300*1e3,de=100;function Ve(r){r?w.delete(r):w.clear();}function We(){if(w.size>de){let r=Array.from(w.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,w.size-de).forEach(([t])=>w.delete(t));}}function _e(){let{isAuthenticated:r,account:e}=A(),t=U(),[o,n]=useState([]),[u,d]=useState([]),[l,c]=useState(false),[s,h]=useState(null),p=useCallback(async()=>{if(!r||!e){n([]),d([]);return}let i=e.homeAccountId,a=w.get(i);if(a&&Date.now()-a.timestamp<Be){n(a.roles),d(a.groups);return}c(true),h(null);try{let v=e.idTokenClaims?.roles||[],O=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(te=>te.id);w.set(i,{roles:v,groups:O,timestamp:Date.now()}),We(),n(v),d(O);}catch(b){let D=C(b),O=new Error(D);h(O),console.error("[Roles] Failed to fetch roles/groups:",D);let he=e.idTokenClaims?.roles||[];n(he);}finally{c(false);}},[r,e,t]),m=useCallback(i=>o.includes(i),[o]),g=useCallback(i=>u.includes(i),[u]),y=useCallback(i=>i.some(a=>o.includes(a)),[o]),f=useCallback(i=>i.every(a=>o.includes(a)),[o]);return useEffect(()=>(p(),()=>{e&&Ve(e.homeAccountId);}),[p,e]),{roles:o,groups:u,loading:l,error:s,hasRole:m,hasGroup:g,hasAnyRole:y,hasAllRoles:f,refetch:p}}function je(r,e={}){let{displayName:t,...o}=e,n=u=>jsx(Q,{...o,children:jsx(r,{...u})});return n.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,n}async function fe(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:n=1e4,backoffMultiplier:u=2,debug:d=false}=e,l,c=o;for(let s=0;s<=t;s++)try{return d&&s>0&&console.log(`[TokenRetry] Attempt ${s+1}/${t+1}`),await r()}catch(h){if(l=h,s===t){d&&console.error("[TokenRetry] All retry attempts failed");break}if(!Je(h))throw d&&console.log("[TokenRetry] Non-retryable error, aborting"),h;d&&console.warn(`[TokenRetry] Attempt ${s+1} failed, retrying in ${c}ms...`),await Ze(c),c=Math.min(c*u,n);}throw l}function Je(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function Ze(r){return new Promise(e=>setTimeout(e,r))}function He(r,e={}){return (...t)=>fe(()=>r(...t),e)}var $=class{constructor(e={}){this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info"};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let n=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",u=this.config.prefix,d=`[${e.toUpperCase()}]`,l=`${n} ${u} ${d} ${t}`;return o!==void 0&&(l+=`
2
- `+JSON.stringify(o,null,2)),l}error(e,t){this.shouldLog("error")&&console.error(this.formatMessage("error",e,t));}warn(e,t){this.shouldLog("warn")&&console.warn(this.formatMessage("warn",e,t));}info(e,t){this.shouldLog("info")&&console.info(this.formatMessage("info",e,t));}debug(e,t){this.shouldLog("debug")&&console.debug(this.formatMessage("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},N=null;function Ke(r){return N?r&&(r.enabled!==void 0&&N.setEnabled(r.enabled),r.level&&N.setLevel(r.level)):N=new $(r),N}function Xe(r,e){return new $({...e,prefix:`[MSAL-Next:${r}]`})}function Qe(r={}){let{protectedRoutes:e=[],publicOnlyRoutes:t=[],loginPath:o="/login",redirectAfterLogin:n="/",sessionCookie:u="msal.account",isAuthenticated:d,debug:l=false}=r;return async function(s){let{pathname:h}=s.nextUrl;l&&console.log("[AuthMiddleware] Processing:",h);let p=false;d?p=await d(s):p=!!s.cookies.get(u)?.value,l&&console.log("[AuthMiddleware] Authenticated:",p);let m=e.some(f=>h.startsWith(f)),g=t.some(f=>h.startsWith(f));if(m&&!p){l&&console.log("[AuthMiddleware] Redirecting to login");let f=s.nextUrl.clone();return f.pathname=o,f.searchParams.set("returnUrl",h),NextResponse.redirect(f)}if(g&&p){l&&console.log("[AuthMiddleware] Redirecting to home");let f=s.nextUrl.searchParams.get("returnUrl"),i=s.nextUrl.clone();return i.pathname=f||n,i.searchParams.delete("returnUrl"),NextResponse.redirect(i)}let y=NextResponse.next();if(p){y.headers.set("x-msal-authenticated","true");try{let f=s.cookies.get(u);if(f?.value){let i=z(f.value,B);i?.username&&y.headers.set("x-msal-username",i.username);}}catch{l&&console.warn("[AuthMiddleware] Failed to parse session data");}}return y}}export{Q as AuthGuard,Oe as AuthStatus,ee as ErrorBoundary,Le as MicrosoftSignInButton,ve as MsalAuthProvider,Ue as SignOutButton,De as UserAvatar,Qe as createAuthMiddleware,V as createMsalConfig,He as createRetryWrapper,Xe as createScopedLogger,Ke as getDebugLogger,Re as getMsalInstance,B as isValidAccountData,G as isValidRedirectUri,oe as isValidScope,fe as retryWithBackoff,z as safeJsonParse,C as sanitizeError,U as useGraphApi,A as useMsalAuth,_e as useRoles,J as useUserProfile,me as validateScopes,je as withAuth};
1
+ import {MsalProvider,useMsal,useAccount}from'@azure/msal-react';export{useAccount,useIsAuthenticated,useMsal}from'@azure/msal-react';import {LogLevel,PublicClientApplication,EventType,InteractionStatus}from'@azure/msal-browser';import {useState,useRef,useEffect,useMemo,useCallback,Component}from'react';import {jsx,Fragment,jsxs}from'react/jsx-runtime';import {NextResponse}from'next/server';function z(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function B(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function S(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function G(r,e){try{let t=new URL(r);return e.some(o=>{let n=new URL(o);return t.origin===n.origin})}catch{return false}}function oe(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function me(r){return Array.isArray(r)&&r.every(oe)}function H(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:n,postLogoutRedirectUri:a,cacheLocation:d="sessionStorage",storeAuthStateInCookie:c=false,navigateToLoginRequestUrl:u=true,enableLogging:s=false,loggerCallback:h,allowedRedirectUris:p}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let m=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},g=typeof window<"u"?window.location.origin:"http://localhost:3000",y=n||g;if(p&&p.length>0){if(!G(y,p))throw new Error(`@chemmangat/msal-next: redirectUri "${y}" is not in the allowed list`);let i=a||y;if(!G(i,p))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${i}" is not in the allowed list`)}return {auth:{clientId:e,authority:m(),redirectUri:y,postLogoutRedirectUri:a||y,navigateToLoginRequestUrl:u},cache:{cacheLocation:d,storeAuthStateInCookie:c},system:{loggerOptions:{loggerCallback:h||((i,l,A)=>{if(!(A||!s))switch(i){case LogLevel.Error:console.error("[MSAL]",l);break;case LogLevel.Warning:console.warn("[MSAL]",l);break;case LogLevel.Info:console.info("[MSAL]",l);break;case LogLevel.Verbose:console.debug("[MSAL]",l);break}}),logLevel:s?LogLevel.Verbose:LogLevel.Error}}}}var ie=null;function Pe(){return ie}function ve({children:r,loadingComponent:e,onInitialized:t,...o}){let[n,a]=useState(null),d=useRef(null);return useEffect(()=>{if(typeof window>"u"||d.current)return;(async()=>{try{let u=H(o),s=new PublicClientApplication(u);await s.initialize(),await s.handleRedirectPromise()&&o.enableLogging&&console.log("[MSAL] Redirect authentication successful");let p=o.enableLogging||!1;s.addEventCallback(m=>{if(m.eventType===EventType.LOGIN_SUCCESS&&p){let g=m.payload;console.log("[MSAL] Login successful:",g.account?.username);}m.eventType===EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",m.error),m.eventType===EventType.LOGOUT_SUCCESS&&p&&console.log("[MSAL] Logout successful");}),d.current=s,ie=s,a(s),t&&t(s);}catch(u){throw console.error("[MSAL] Initialization failed:",u),u}})();},[]),typeof window>"u"?jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})}):n?jsx(MsalProvider,{instance:n,children:r}):jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})})}var W=new Map;function b(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=useMsal(),n=useAccount(t[0]||null),a=useRef(false),d=useMemo(()=>t.length>0,[t]),c=useCallback(async(i=r)=>{try{let l={scopes:i,prompt:"select_account"};await e.loginPopup(l);}catch(l){throw console.error("[MSAL] Login popup failed:",l),l}},[e,r]),u=useCallback(async(i=r)=>{try{let l={scopes:i,prompt:"select_account"};await e.loginRedirect(l);}catch(l){throw console.error("[MSAL] Login redirect failed:",l),l}},[e,r]),s=useCallback(async()=>{try{await e.logoutPopup({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout popup failed:",i),i}},[e,n]),h=useCallback(async()=>{try{await e.logoutRedirect({account:n||void 0});}catch(i){throw console.error("[MSAL] Logout redirect failed:",i),i}},[e,n]),p=useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let l={scopes:i,account:n,forceRefresh:!1};return (await e.acquireTokenSilent(l)).accessToken}catch(l){throw console.error("[MSAL] Silent token acquisition failed:",l),l}},[e,n,r]),m=useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");if(a.current)throw new Error("[MSAL] Popup already in progress. Please wait.");try{a.current=!0;let l={scopes:i,account:n};return (await e.acquireTokenPopup(l)).accessToken}catch(l){throw console.error("[MSAL] Token popup acquisition failed:",l),l}finally{a.current=false;}},[e,n,r]),g=useCallback(async(i=r)=>{if(!n)throw new Error("[MSAL] No active account. Please login first.");try{let l={scopes:i,account:n};await e.acquireTokenRedirect(l);}catch(l){throw console.error("[MSAL] Token redirect acquisition failed:",l),l}},[e,n,r]),y=useCallback(async(i=r)=>{let l=`${n?.homeAccountId||"anonymous"}-${i.sort().join(",")}`,A=W.get(l);if(A)return A;let v=(async()=>{try{return await p(i)}catch{return console.warn("[MSAL] Silent token acquisition failed, falling back to popup"),await m(i)}finally{W.delete(l);}})();return W.set(l,v),v},[p,m,r,n]),f=useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:n,accounts:t,isAuthenticated:d,inProgress:o!==InteractionStatus.None,loginPopup:c,loginRedirect:u,logoutPopup:s,logoutRedirect:h,acquireToken:y,acquireTokenSilent:p,acquireTokenPopup:m,acquireTokenRedirect:g,clearSession:f}}function Le({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",useRedirect:o=false,scopes:n,className:a="",style:d,onSuccess:c,onError:u}){let{loginPopup:s,loginRedirect:h,inProgress:p}=b(),m=async()=>{try{o?await h(n):await s(n),c?.();}catch(i){u?.(i);}},g={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},f={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:p?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:p?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...g[t],...d};return jsxs("button",{onClick:m,disabled:p,className:a,style:f,"aria-label":r,children:[jsx(ke,{}),jsx("span",{children:r})]})}function ke(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function Ue({text:r="Sign out",variant:e="dark",size:t="medium",useRedirect:o=false,className:n="",style:a,onSuccess:d,onError:c}){let{logoutPopup:u,logoutRedirect:s,inProgress:h}=b(),p=async()=>{try{o?await s():await u(),d?.();}catch(f){c?.(f);}},m={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},y={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:h?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:h?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...m[t],...a};return jsxs("button",{onClick:p,disabled:h,className:n,style:y,"aria-label":r,children:[jsx(Me,{}),jsx("span",{children:r})]})}function Me(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function U(){let{acquireToken:r}=b(),e=useCallback(async(c,u={})=>{let{scopes:s=["User.Read"],version:h="v1.0",debug:p=false,...m}=u;try{let g=await r(s),y=`https://graph.microsoft.com/${h}`,f=c.startsWith("http")?c:`${y}${c.startsWith("/")?c:`/${c}`}`;p&&console.log("[GraphAPI] Request:",{url:f,method:m.method||"GET"});let i=await fetch(f,{...m,headers:{Authorization:`Bearer ${g}`,"Content-Type":"application/json",...m.headers}});if(!i.ok){let A=await i.text(),v=`Graph API error (${i.status}): ${A}`;throw new Error(v)}if(i.status===204||i.headers.get("content-length")==="0")return null;let l=await i.json();return p&&console.log("[GraphAPI] Response:",l),l}catch(g){let y=S(g);throw console.error("[GraphAPI] Request failed:",y),new Error(y)}},[r]),t=useCallback((c,u={})=>e(c,{...u,method:"GET"}),[e]),o=useCallback((c,u,s={})=>e(c,{...s,method:"POST",body:u?JSON.stringify(u):void 0}),[e]),n=useCallback((c,u,s={})=>e(c,{...s,method:"PUT",body:u?JSON.stringify(u):void 0}),[e]),a=useCallback((c,u,s={})=>e(c,{...s,method:"PATCH",body:u?JSON.stringify(u):void 0}),[e]),d=useCallback((c,u={})=>e(c,{...u,method:"DELETE"}),[e]);return {get:t,post:o,put:n,patch:a,delete:d,request:e}}var P=new Map,Fe=300*1e3,ue=100;function Ne(){if(P.size>ue){let r=Array.from(P.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,P.size-ue).forEach(([t])=>{let o=P.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),P.delete(t);});}}function j(){let{isAuthenticated:r,account:e}=b(),t=U(),[o,n]=useState(null),[a,d]=useState(false),[c,u]=useState(null),s=useCallback(async()=>{if(!r||!e){n(null);return}let p=e.homeAccountId,m=P.get(p);if(m&&Date.now()-m.timestamp<Fe){n(m.data);return}d(true),u(null);try{let g=await t.get("/me",{scopes:["User.Read"]}),y;try{let i=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});i&&(y=URL.createObjectURL(i));}catch{console.debug("[UserProfile] Photo not available");}let f={id:g.id,displayName:g.displayName,givenName:g.givenName,surname:g.surname,userPrincipalName:g.userPrincipalName,mail:g.mail,jobTitle:g.jobTitle,officeLocation:g.officeLocation,mobilePhone:g.mobilePhone,businessPhones:g.businessPhones,photo:y};P.set(p,{data:f,timestamp:Date.now()}),Ne(),n(f);}catch(g){let f=S(g),i=new Error(f);u(i),console.error("[UserProfile] Failed to fetch profile:",f);}finally{d(false);}},[r,e,t]),h=useCallback(()=>{if(e){let p=P.get(e.homeAccountId);p?.data.photo&&URL.revokeObjectURL(p.data.photo),P.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),n(null);},[e,o]);return useEffect(()=>(s(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[s]),useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:a,error:c,refetch:s,clearCache:h}}function De({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:n}){let{profile:a,loading:d}=j(),[c,u]=useState(null),[s,h]=useState(false);useEffect(()=>{a?.photo&&u(a.photo);},[a?.photo]);let p=()=>{if(!a)return "?";let{givenName:y,surname:f,displayName:i}=a;if(y&&f)return `${y[0]}${f[0]}`.toUpperCase();if(i){let l=i.split(" ");return l.length>=2?`${l[0][0]}${l[l.length-1][0]}`.toUpperCase():i.substring(0,2).toUpperCase()}return "?"},m={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},g=a?.displayName||"User";return d?jsx("div",{className:e,style:{...m,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):c&&!s?jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:jsx("img",{src:c,alt:g,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),n&&u(n);}})}):jsx("div",{className:e,style:m,title:o?g:void 0,"aria-label":`${g} avatar`,children:p()})}function Oe({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:n,renderUnauthenticated:a}){let{isAuthenticated:d,inProgress:c,account:u}=b(),s={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(c)return o?jsx(Fragment,{children:o()}):jsxs("div",{className:r,style:{...s,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsx(J,{color:"#FFA500"}),jsx("span",{children:"Loading..."})]});if(d){let h=u?.username||u?.name||"User";return n?jsx(Fragment,{children:n(h)}):jsxs("div",{className:r,style:{...s,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsx(J,{color:"#28A745"}),jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return a?jsx(Fragment,{children:a()}):jsxs("div",{className:r,style:{...s,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsx(J,{color:"#DC3545"}),jsx("span",{children:"Not authenticated"})]})}function J({color:r}){return jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function Q({children:r,loadingComponent:e,fallbackComponent:t,useRedirect:o=true,scopes:n,onAuthRequired:a}){let{isAuthenticated:d,inProgress:c,loginRedirect:u,loginPopup:s}=b();return useEffect(()=>{!d&&!c&&(a?.(),(async()=>{try{o?await u(n):await s(n);}catch(p){console.error("[AuthGuard] Authentication failed:",p);}})());},[d,c,o,n,u,s,a]),c?jsx(Fragment,{children:e||jsx("div",{children:"Authenticating..."})}):d?jsx(Fragment,{children:r}):jsx(Fragment,{children:t||jsx("div",{children:"Redirecting to login..."})})}var ee=class extends Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:n,debug:a}=this.props;a&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),n?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:n,fallback:a}=this.props;return t&&o?a?a(o,this.reset):jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):n}};var R=new Map,Be=300*1e3,de=100;function He(r){r?R.delete(r):R.clear();}function Ve(){if(R.size>de){let r=Array.from(R.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,R.size-de).forEach(([t])=>R.delete(t));}}function We(){let{isAuthenticated:r,account:e}=b(),t=U(),[o,n]=useState([]),[a,d]=useState([]),[c,u]=useState(false),[s,h]=useState(null),p=useCallback(async()=>{if(!r||!e){n([]),d([]);return}let i=e.homeAccountId,l=R.get(i);if(l&&Date.now()-l.timestamp<Be){n(l.roles),d(l.groups);return}u(true),h(null);try{let v=e.idTokenClaims?.roles||[],O=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(te=>te.id);R.set(i,{roles:v,groups:O,timestamp:Date.now()}),Ve(),n(v),d(O);}catch(A){let D=S(A),O=new Error(D);h(O),console.error("[Roles] Failed to fetch roles/groups:",D);let he=e.idTokenClaims?.roles||[];n(he);}finally{u(false);}},[r,e,t]),m=useCallback(i=>o.includes(i),[o]),g=useCallback(i=>a.includes(i),[a]),y=useCallback(i=>i.some(l=>o.includes(l)),[o]),f=useCallback(i=>i.every(l=>o.includes(l)),[o]);return useEffect(()=>(p(),()=>{e&&He(e.homeAccountId);}),[p,e]),{roles:o,groups:a,loading:c,error:s,hasRole:m,hasGroup:g,hasAnyRole:y,hasAllRoles:f,refetch:p}}function _e(r,e={}){let{displayName:t,...o}=e,n=a=>jsx(Q,{...o,children:jsx(r,{...a})});return n.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,n}async function fe(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:n=1e4,backoffMultiplier:a=2,debug:d=false}=e,c,u=o;for(let s=0;s<=t;s++)try{return d&&s>0&&console.log(`[TokenRetry] Attempt ${s+1}/${t+1}`),await r()}catch(h){if(c=h,s===t){d&&console.error("[TokenRetry] All retry attempts failed");break}if(!je(h))throw d&&console.log("[TokenRetry] Non-retryable error, aborting"),h;d&&console.warn(`[TokenRetry] Attempt ${s+1} failed, retrying in ${u}ms...`),await Je(u),u=Math.min(u*a,n);}throw c}function je(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function Je(r){return new Promise(e=>setTimeout(e,r))}function Ze(r,e={}){return (...t)=>fe(()=>r(...t),e)}var q=class{constructor(e={}){this.logHistory=[];this.performanceTimings=new Map;this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info",enablePerformance:e.enablePerformance??false,enableNetworkLogs:e.enableNetworkLogs??false,maxHistorySize:e.maxHistorySize??100};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let n=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",a=this.config.prefix,d=`[${e.toUpperCase()}]`,c=`${n} ${a} ${d} ${t}`;return o!==void 0&&(c+=`
2
+ `+JSON.stringify(o,null,2)),c}addToHistory(e,t,o){this.logHistory.length>=this.config.maxHistorySize&&this.logHistory.shift(),this.logHistory.push({timestamp:Date.now(),level:e,message:t,data:o});}error(e,t){this.shouldLog("error")&&(console.error(this.formatMessage("error",e,t)),this.addToHistory("error",e,t));}warn(e,t){this.shouldLog("warn")&&(console.warn(this.formatMessage("warn",e,t)),this.addToHistory("warn",e,t));}info(e,t){this.shouldLog("info")&&(console.info(this.formatMessage("info",e,t)),this.addToHistory("info",e,t));}debug(e,t){this.shouldLog("debug")&&(console.debug(this.formatMessage("debug",e,t)),this.addToHistory("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}startTiming(e){this.config.enablePerformance&&(this.performanceTimings.set(e,{operation:e,startTime:performance.now()}),this.debug(`\u23F1\uFE0F Started: ${e}`));}endTiming(e){if(this.config.enablePerformance){let t=this.performanceTimings.get(e);if(t)return t.endTime=performance.now(),t.duration=t.endTime-t.startTime,this.info(`\u23F1\uFE0F Completed: ${e} (${t.duration.toFixed(2)}ms)`),t.duration}}logRequest(e,t,o){this.config.enableNetworkLogs&&this.debug(`\u{1F310} ${e} ${t}`,o);}logResponse(e,t,o,n){if(this.config.enableNetworkLogs){let a=o>=200&&o<300?"\u2705":"\u274C";this.debug(`${a} ${e} ${t} - ${o}`,n);}}getHistory(){return [...this.logHistory]}getPerformanceTimings(){return Array.from(this.performanceTimings.values())}clearHistory(){this.logHistory=[];}clearTimings(){this.performanceTimings.clear();}exportLogs(){return JSON.stringify({config:this.config,history:this.logHistory,performanceTimings:Array.from(this.performanceTimings.values()),exportedAt:new Date().toISOString()},null,2)}downloadLogs(e="msal-next-debug-logs.json"){if(typeof window>"u")return;let t=this.exportLogs(),o=new Blob([t],{type:"application/json"}),n=URL.createObjectURL(o),a=document.createElement("a");a.href=n,a.download=e,a.click(),URL.revokeObjectURL(n);}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},I=null;function Ke(r){return I?r&&(r.enabled!==void 0&&I.setEnabled(r.enabled),r.level&&I.setLevel(r.level)):I=new q(r),I}function Xe(r,e){return new q({...e,prefix:`[MSAL-Next:${r}]`})}function Qe(r={}){let{protectedRoutes:e=[],publicOnlyRoutes:t=[],loginPath:o="/login",redirectAfterLogin:n="/",sessionCookie:a="msal.account",isAuthenticated:d,debug:c=false}=r;return async function(s){let{pathname:h}=s.nextUrl;c&&console.log("[AuthMiddleware] Processing:",h);let p=false;d?p=await d(s):p=!!s.cookies.get(a)?.value,c&&console.log("[AuthMiddleware] Authenticated:",p);let m=e.some(f=>h.startsWith(f)),g=t.some(f=>h.startsWith(f));if(m&&!p){c&&console.log("[AuthMiddleware] Redirecting to login");let f=s.nextUrl.clone();return f.pathname=o,f.searchParams.set("returnUrl",h),NextResponse.redirect(f)}if(g&&p){c&&console.log("[AuthMiddleware] Redirecting to home");let f=s.nextUrl.searchParams.get("returnUrl"),i=s.nextUrl.clone();return i.pathname=f||n,i.searchParams.delete("returnUrl"),NextResponse.redirect(i)}let y=NextResponse.next();if(p){y.headers.set("x-msal-authenticated","true");try{let f=s.cookies.get(a);if(f?.value){let i=z(f.value,B);i?.username&&y.headers.set("x-msal-username",i.username);}}catch{c&&console.warn("[AuthMiddleware] Failed to parse session data");}}return y}}export{Q as AuthGuard,Oe as AuthStatus,ee as ErrorBoundary,Le as MicrosoftSignInButton,ve as MsalAuthProvider,Ue as SignOutButton,De as UserAvatar,Qe as createAuthMiddleware,H as createMsalConfig,Ze as createRetryWrapper,Xe as createScopedLogger,Ke as getDebugLogger,Pe as getMsalInstance,B as isValidAccountData,G as isValidRedirectUri,oe as isValidScope,fe as retryWithBackoff,z as safeJsonParse,S as sanitizeError,U as useGraphApi,b as useMsalAuth,We as useRoles,j as useUserProfile,me as validateScopes,_e as withAuth};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chemmangat/msal-next",
3
- "version": "2.3.0",
3
+ "version": "3.0.1",
4
4
  "description": "Production-grade MSAL authentication package for Next.js App Router with minimal boilerplate",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",