mesauth-angular 1.0.1 → 1.1.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
@@ -4,6 +4,15 @@ Angular helper library to connect to a backend API and SignalR hub to surface th
4
4
 
5
5
  ## Changelog
6
6
 
7
+ ### v1.1.0 (2026-01-21) - **Major Update**
8
+ - 🚀 **New `provideMesAuth()` Function**: Simplified setup with a single function call
9
+ - ✨ **Functional Interceptor**: New `mesAuthInterceptor` for better compatibility with standalone apps
10
+ - 📦 **Automatic Initialization**: `provideMesAuth()` handles service initialization via `APP_INITIALIZER`
11
+ - 🔧 **Simplified API**: Just pass `apiBaseUrl` and `userBaseUrl` - no manual DI required
12
+
13
+ ### v1.0.1 (2026-01-21)
14
+ - 🔧 Internal refactoring for better module compatibility
15
+
7
16
  ### v0.2.28 (2026-01-19)
8
17
  - ✨ **Enhanced Avatar Support**: Direct `avatarPath` usage from user data for instant display without backend calls
9
18
  - 🔄 **Improved Avatar Refresh**: Timestamp-based cache busting prevents request cancellation issues
@@ -20,7 +29,70 @@ Angular helper library to connect to a backend API and SignalR hub to surface th
20
29
  - 🎨 **Dark/Light Theme**: Automatic theme detection and support
21
30
  - 🖼️ **Avatar Support**: Direct API-based avatar loading
22
31
  - 🍞 **Toast Notifications**: In-app notification toasts
23
- - 🛡️ **HTTP Interceptor**: Automatic 403 error handling
32
+ - 🛡️ **HTTP Interceptor**: Automatic 401/403 error handling with redirects
33
+
34
+ ## Quick Start (v1.1.0+)
35
+
36
+ ### 1. Install
37
+
38
+ ```bash
39
+ npm install mesauth-angular
40
+ ```
41
+
42
+ ### 2. Configure in app.config.ts (Recommended for Angular 14+)
43
+
44
+ ```ts
45
+ import { ApplicationConfig } from '@angular/core';
46
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
47
+ import { provideMesAuth, mesAuthInterceptor } from 'mesauth-angular';
48
+
49
+ export const appConfig: ApplicationConfig = {
50
+ providers: [
51
+ provideHttpClient(
52
+ withInterceptors([mesAuthInterceptor]) // Handles 401/403 redirects
53
+ ),
54
+ provideMesAuth({
55
+ apiBaseUrl: 'https://mes.kefico.vn/auth',
56
+ userBaseUrl: 'https://mes.kefico.vn/x' // For login/403 redirects
57
+ })
58
+ ]
59
+ };
60
+ ```
61
+
62
+ That's it! The library handles:
63
+ - Service initialization via `APP_INITIALIZER`
64
+ - `HttpClient` and `Router` injection automatically
65
+ - 401 → redirects to `{userBaseUrl}/login?returnUrl=...`
66
+ - 403 → redirects to `{userBaseUrl}/403?returnUrl=...`
67
+
68
+ ### 3. Use in Components
69
+
70
+ ```ts
71
+ import { MesAuthService } from 'mesauth-angular';
72
+
73
+ @Component({...})
74
+ export class MyComponent {
75
+ private auth = inject(MesAuthService);
76
+
77
+ // Observable streams
78
+ currentUser$ = this.auth.currentUser$;
79
+ notifications$ = this.auth.notifications$;
80
+
81
+ logout() {
82
+ this.auth.logout().subscribe();
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## Configuration Options
88
+
89
+ ```ts
90
+ interface MesAuthConfig {
91
+ apiBaseUrl: string; // Required: MesAuth API base URL
92
+ userBaseUrl?: string; // Optional: Base URL for login/403 redirects
93
+ withCredentials?: boolean; // Optional: Send cookies (default: true)
94
+ }
95
+ ```
24
96
 
25
97
  ## Theme Support
26
98
 
@@ -75,150 +147,9 @@ Avatar URLs include timestamps to prevent browser caching issues during updates:
75
147
  - **UI Avatars**: Generates initials-based avatars if no user data available
76
148
  - **Authentication**: Not required for fallback avatars
77
149
 
78
- ## Quick Start
79
-
80
- 1. Install (from local folder during development):
81
-
82
- ```bash
83
- cd /path/to/your/angular-app
84
- npm install ../path/to/mesauth-angular
85
- ```
86
-
87
- 2. Provide the service and import components:
88
- - **For standalone components/apps**: Import `MesAuthModule` in your standalone component or `app.config.ts`.
89
- ```ts
90
- import { MesAuthModule } from 'mesauth-angular';
91
-
92
- @Component({
93
- standalone: true,
94
- imports: [MesAuthModule, /* other imports */],
95
- // ...
96
- })
97
- export class MyComponent {}
98
- ```
99
- Or in `app.config.ts`:
100
- ```ts
101
- import { MesAuthModule } from 'mesauth-angular';
102
-
103
- export const appConfig: ApplicationConfig = {
104
- imports: [MesAuthModule],
105
- // ... other config
106
- };
107
- ```
108
- - **For module-based apps**: Import `MesAuthModule` in your `AppModule` or feature module.
109
- ```ts
110
- import { MesAuthModule } from 'mesauth-angular';
111
-
112
- @NgModule({
113
- imports: [MesAuthModule],
114
- // ... other config
115
- })
116
- export class AppModule { }
117
- ```
118
-
119
- 3. (Optional) Provide the HTTP interceptor to handle 403 errors:
120
- - The interceptor redirects to `${userBaseUrl}/403?returnUrl=encodedCurrentUrl` using `window.location.href` for external URLs (since `userBaseUrl` may be outside the client app).
121
- - **For module-based apps**: Add `MesAuthInterceptor` to providers in `AppModule`.
122
- ```ts
123
- import { HTTP_INTERCEPTORS } from '@angular/common/http';
124
- import { MesAuthInterceptor } from 'mesauth-angular';
125
-
126
- @NgModule({
127
- // ... other module config ...
128
- providers: [
129
- // ... other providers ...
130
- { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
131
- ]
132
- })
133
- export class AppModule { }
134
- ```
135
- - **For standalone apps**: Add `MesAuthInterceptor` to providers in `app.config.ts`.
136
- ```ts
137
- import { HTTP_INTERCEPTORS } from '@angular/common/http';
138
- import { MesAuthInterceptor } from 'mesauth-angular';
139
-
140
- export const appConfig: ApplicationConfig = {
141
- providers: [
142
- // ... other providers ...
143
- { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
144
- ]
145
- };
146
- ```
147
-
148
- 4. Initialize in your app (recommended in `AppComponent` constructor):
149
-
150
- **⚠️ IMPORTANT:** Starting from v0.2.16, `MesAuthService` requires `HttpClient` and optionally `Router` to be passed to the `init()` method. This prevents dependency injection timing issues.
151
-
152
- ```ts
153
- // In AppComponent constructor (recommended)
154
- import { HttpClient } from '@angular/common/http';
155
- import { Router } from '@angular/router';
156
- import { inject } from '@angular/core';
157
- import { MesAuthService } from 'mesauth-angular';
158
-
159
- export class AppComponent {
160
- readonly #mesAuthService = inject(MesAuthService);
161
- readonly #router = inject(Router);
162
-
163
- constructor() {
164
- // Initialize MesAuth with HttpClient and Router
165
- this.#mesAuthService.init(
166
- {
167
- apiBaseUrl: 'https://api.example.com',
168
- withCredentials: true,
169
- userBaseUrl: 'https://api.example.com/users'
170
- },
171
- inject(HttpClient), // Required: pass HttpClient
172
- this.#router // Optional: pass Router for automatic user refresh on navigation
173
- );
174
-
175
- // Subscribe to observables
176
- this.#mesAuthService.currentUser$.subscribe(user => console.log('user', user));
177
- this.#mesAuthService.notifications$.subscribe(n => console.log('notif', n));
178
- }
179
- }
180
- ```
181
-
182
- **Why this change?**
183
- - Previous versions injected `HttpClient` and `Router` directly in the service constructor
184
- - This caused `NG0203` injection context errors during route loading and early bootstrap
185
- - The new pattern delays dependency access until after the app is fully initialized
186
-
187
- **For Module-based Apps:**
188
-
189
- ```ts
190
- // In AppComponent
191
- import { HttpClient } from '@angular/common/http';
192
- import { Router } from '@angular/router';
193
-
194
- constructor(
195
- private mesAuth: MesAuthService,
196
- private http: HttpClient,
197
- private router: Router
198
- ) {
199
- this.mesAuth.init(
200
- {
201
- apiBaseUrl: 'https://api.example.com',
202
- withCredentials: true,
203
- userBaseUrl: 'https://api.example.com/users'
204
- },
205
- this.http, // Required
206
- this.router // Optional
207
- );
208
- }
209
- ```
210
-
211
- 5. Build the package for publishing:
212
-
213
- ```bash
214
- cd /path/to/mesauth-angular
215
- npm install
216
- npm run build
217
- ```
218
-
219
150
  ## Components
220
151
 
221
- **Note:** All components are standalone and can only be imported in standalone components or apps. If your app uses NgModules, use dynamic imports or convert to standalone.
152
+ **Note:** All components are standalone and can be imported directly.
222
153
 
223
154
  ### ma-user-profile
224
155
 
@@ -232,7 +163,7 @@ A reusable Angular component for displaying the current user's profile informati
232
163
  - **Usage Example**:
233
164
 
234
165
  ```html
235
- <ma-user-profile
166
+ <ma-user-profile
236
167
  (onNavigate)="handleNavigation($event)"
237
168
  (onLogout)="handleLogout()">
238
169
  </ma-user-profile>
@@ -273,166 +204,62 @@ A standalone component for displaying a slide-out notification panel with real-t
273
204
  notificationPanel.open();
274
205
  ```
275
206
 
276
- ## Changelog
277
-
278
- ### v0.2.27 (Latest)
279
- - 👤 **Enhanced Profile**: Added comprehensive HR information display support in user profiles
280
- - 🖼️ **Avatar Upload**: Implemented avatar cropping with drag and zoom functionality
281
- - 🔒 **Privacy Compliance**: Removed sensitive HR fields (Position/Job Title) from profile display
282
- - 🎨 **UI Improvements**: Better profile layout with HR information grid
283
-
284
- ### v0.2.18
285
- - 🔗 **Interceptor Improvement**: `MesAuthInterceptor` now uses `router.url` instead of `window.location.href` for cleaner returnUrl parameters
286
- - 📍 **Shorter URLs**: Return URLs are now relative paths (`/dashboard`) instead of full URLs (`https://domain.com/dashboard`)
287
- - 🔄 **Better Fallback**: Falls back to `window.location.pathname + search` if router URL is unavailable
288
-
289
- ### v0.2.17
290
- - 🐛 **ViewChild Fix**: Fixed `MaUserComponent` ViewChild query error by adding `AfterViewInit` lifecycle and `{ static: false }` option
291
- - ✅ **Error Handling**: Added graceful error handling for 401/403 responses on auth endpoints (silent handling when user not logged in)
292
- - 🧹 **Clean Console**: Auth errors no longer pollute the console - expected authentication failures are handled silently
293
- - 🛡️ **Null Safety**: Added null check in `onNotificationRead()` to prevent errors when userProfile is not yet initialized
294
-
295
- ### v0.2.16
296
- - 🔧 **Breaking Change**: `init()` method now requires `HttpClient` and optionally `Router` as parameters
297
- - 🚫 **Injection Fix**: Removed `HttpClient` and `Router` from service constructor to prevent `NG0203` injection context errors
298
- - ⚡ **Improved Initialization**: Dependencies are now passed explicitly to `init()` method, resolving timing issues during route loading
299
- - 📝 **API Change**: `init(config: MesAuthConfig, httpClient: HttpClient, router?: Router)`
300
- - 🎯 **Why**: Fixes dependency injection errors that occurred during lazy route loading and early bootstrap phases
301
-
302
- ### v0.2.13
303
- - 🎨 **Notification Format**: Cleaned up notification title format by removing redundant `[sourceAppName]` prefix
304
- - 📱 **Improved Layout**: Source app name now displayed separately in metadata row for better organization
305
- - 🔔 **Consistent Toasts**: Toast notifications also updated to use clean title format without app name prefix
306
-
307
- ### v0.2.12
308
- - 📝 **HTML Message Support**: Added priority support for `messageHtml` over `message` in notifications
309
- - 🎨 **Rich Text Display**: Notifications now render HTML content when available, with fallback to plain text
310
- - 🔔 **Enhanced Toasts**: Toast notifications also support HTML content with proper rendering
311
-
312
- ### v0.2.9
313
- - 🔐 **Credentials Fix**: Added `withCredentials: true` to all HTTP requests to properly send authentication cookies
314
- - 🐛 **403 Forbidden Fix**: Resolved authentication issues where API calls were failing due to missing credentials
315
- - 🔧 **Consistent Auth**: All API endpoints now properly include credentials for authenticated requests
316
-
317
- ### v0.2.8
318
- - 🔄 **Route Change Optimization**: Improved route change detection with debouncing and selective refreshing
319
- - 🛡️ **Protected Route Handling**: Only refresh user data on protected routes, avoiding auth flow interference
320
- - 🔧 **Smart URL Construction**: Fixed double `/auth` path issue for auth endpoints when apiBaseUrl includes `/auth`
321
- - ⏱️ **Timing Improvements**: Added delays and better timing for authentication state management
322
-
323
- ### v0.2.7
324
- - 🔄 **Route Change Detection**: Added automatic user data refresh when routes change in single-page applications
325
- - 🎯 **SPA Support**: Handles login scenarios where page doesn't reload but route changes occur
326
- - 🛡️ **Optional Dependency**: Router integration is optional - service works with or without Router injection
327
-
328
- ### v0.2.6
329
- - 🗑️ **Delete Button**: Added delete button for read notifications in the read tab
330
- - 🎯 **Contextual Actions**: Unread notifications show "mark as read" button, read notifications show "delete" button
331
- - 🎨 **Visual Feedback**: Delete button uses error color on hover for clear destructive action indication
332
-
333
- ### v0.2.5
334
- - 🗂️ **Notification Tabs**: Added tabs to separate unread and read notifications with unread tab as default
335
- - 📊 **Tab Counters**: Display notification counts for each tab (Unread/Read)
336
- - 🎯 **Improved UX**: Better organization of notifications with tab-based navigation
337
- - 🔄 **Enhanced Filtering**: Load both read and unread notifications for seamless tab switching
338
-
339
- ### v0.2.4
340
- - 🔔 **Notification UX**: Changed notification delete button to mark-as-read with checkmark icon
341
- - 🔄 **Badge Updates**: Added automatic badge counter refresh when notifications are marked as read
342
- - 🎯 **Event System**: Implemented event-driven communication between notification panel and badge components
343
-
344
- ### v0.2.3
345
- - 🧹 **Code Cleanup**: Removed all console.log and console.error statements for production readiness
346
- - 📚 **Documentation**: Updated README with comprehensive changelog, theme support guide, and API documentation
347
- - 🏷️ **Package Metadata**: Updated package description to reflect theme support
348
-
349
- ### v0.2.2
350
- - ✨ **Theme Support**: Added automatic dark/light theme detection and real-time theme switching
351
- - 🖼️ **Avatar API**: Changed avatar loading to use API endpoint (`/auth/{userId}/avatar`) instead of external service
352
- - 🎨 **UI Improvements**: Better toast styling with proper borders and sizing
353
-
354
- ### v0.2.1
355
- - 🔄 **Dynamic Themes**: Added real-time theme change detection using MutationObserver
356
- - 🐛 **Toast Fixes**: Improved toast background and sizing for dark themes
357
-
358
- ### v0.2.0
359
- - 🎨 **Initial Theme Support**: Basic dark/light theme implementation
360
- - 🖼️ **Avatar Updates**: Changed to API-based avatar loading
361
-
362
- ### v0.1.20
363
- - 🐛 **Bug fixes and improvements**
364
-
365
- ## Notes
366
- - The service expects an endpoint `GET {apiBaseUrl}/auth/me` that returns the current user.
367
- - Avatar endpoint: `GET {apiBaseUrl}/auth/{userId}/avatar`
368
- - SignalR events used: `ReceiveNotification` (adjust to your backend).
369
-
370
207
  ## Migration Guide
371
208
 
372
- ### Upgrading from v0.2.15 or earlier to v0.2.16+
209
+ ### Upgrading from v0.x to v1.1.0+
373
210
 
374
- The initialization pattern has changed to fix dependency injection timing issues. Follow these steps:
211
+ The setup has been greatly simplified. Here's how to migrate:
375
212
 
376
- **Before (v0.2.15 and earlier):**
213
+ **Before (v0.x):**
377
214
  ```ts
378
- constructor(private mesAuth: MesAuthService) {
379
- this.mesAuth.init({
380
- apiBaseUrl: 'https://api.example.com',
381
- withCredentials: true,
382
- userBaseUrl: 'https://api.example.com/users'
383
- });
384
- }
385
- ```
386
-
387
- **After (v0.2.16+):**
388
- ```ts
389
- import { HttpClient } from '@angular/common/http';
390
- import { Router } from '@angular/router';
391
- import { inject } from '@angular/core';
392
-
215
+ // app.config.ts - OLD WAY
216
+ import { MesAuthModule, MesAuthService } from 'mesauth-angular';
217
+ import { HTTP_INTERCEPTORS } from '@angular/common/http';
218
+
219
+ export const appConfig: ApplicationConfig = {
220
+ providers: [
221
+ importProvidersFrom(MesAuthModule),
222
+ { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
223
+ ]
224
+ };
225
+
226
+ // app.component.ts - OLD WAY
393
227
  export class AppComponent {
394
- readonly #mesAuthService = inject(MesAuthService);
395
- readonly #router = inject(Router);
396
-
397
228
  constructor() {
398
- // Pass HttpClient and Router to init()
399
- this.#mesAuthService.init(
400
- {
401
- apiBaseUrl: 'https://api.example.com',
402
- withCredentials: true,
403
- userBaseUrl: 'https://api.example.com/users'
404
- },
405
- inject(HttpClient), // Required: add this parameter
406
- this.#router // Optional: add this parameter for auto user refresh
407
- );
229
+ this.mesAuthService.init({
230
+ apiBaseUrl: '...',
231
+ userBaseUrl: '...'
232
+ }, inject(HttpClient), inject(Router));
408
233
  }
409
234
  }
410
235
  ```
411
236
 
412
- **For module-based apps:**
237
+ **After (v1.1.0+):**
413
238
  ```ts
414
- constructor(
415
- private mesAuth: MesAuthService,
416
- private http: HttpClient, // Add this
417
- private router: Router // Add this (optional)
418
- ) {
419
- this.mesAuth.init(
420
- {
421
- apiBaseUrl: 'https://api.example.com',
422
- withCredentials: true,
423
- userBaseUrl: 'https://api.example.com/users'
424
- },
425
- this.http, // Add this parameter
426
- this.router // Add this parameter (optional)
427
- );
239
+ // app.config.ts - NEW WAY (everything in one place!)
240
+ import { provideMesAuth, mesAuthInterceptor } from 'mesauth-angular';
241
+
242
+ export const appConfig: ApplicationConfig = {
243
+ providers: [
244
+ provideHttpClient(withInterceptors([mesAuthInterceptor])),
245
+ provideMesAuth({
246
+ apiBaseUrl: 'https://mes.kefico.vn/auth',
247
+ userBaseUrl: 'https://mes.kefico.vn/x'
248
+ })
249
+ ]
250
+ };
251
+
252
+ // app.component.ts - No init() needed!
253
+ export class AppComponent {
254
+ // Just inject and use - no manual initialization required
428
255
  }
429
256
  ```
430
257
 
431
- **What changed and why:**
432
- - `HttpClient` is now required as the 2nd parameter to `init()`
433
- - `Router` is optional as the 3rd parameter (recommended for SPA user refresh)
434
- - This fixes `NG0203` injection errors that occurred during route lazy-loading
435
- - The service constructor is now empty - all dependencies are passed to `init()`
258
+ **Key Changes:**
259
+ - `provideMesAuth()` replaces `MesAuthModule` + manual `init()` call
260
+ - `mesAuthInterceptor` (functional) replaces `MesAuthInterceptor` (class-based)
261
+ - No need to inject `HttpClient` or `Router` manually
262
+ - Configuration moved from `AppComponent` to `app.config.ts`
436
263
 
437
264
  ## Troubleshooting
438
265
 
@@ -440,7 +267,6 @@ constructor(
440
267
  If you encounter an error like "The injectable 'MesAuthService' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available," this typically occurs because:
441
268
  - The package is being imported directly from source code (e.g., during development) without building it first.
442
269
  - The client app is running in AOT (Ahead-of-Time) compilation mode, which requires pre-compiled libraries.
443
- - **Why JIT is required:** Originally, `MesAuthService` used `@Injectable({ providedIn: 'root' })`, making it a library-provided service. Angular libraries must be built with tools like ng-packagr to generate AOT-compatible code. If not, or if imported from source, the service requires JIT compilation in the client's app. This change (removing `providedIn: 'root'` and requiring manual provision) allows the service to be compiled in your app's context, supporting both JIT and AOT modes.
444
270
 
445
271
  **Solutions:**
446
272
  1. **Build the package for production/AOT compatibility:**
@@ -449,37 +275,17 @@ If you encounter an error like "The injectable 'MesAuthService' needs to be comp
449
275
 
450
276
  2. **For development (if you must link to source):**
451
277
  - Switch your Angular app to JIT mode by bootstrapping with `@angular/platform-browser-dynamic` instead of `@angular/platform-browser`.
452
- - Example in `main.ts`:
453
- ```ts
454
- import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
455
- import { AppModule } from './app/app.module';
456
-
457
- platformBrowserDynamic().bootstrapModule(AppModule);
458
- ```
459
- - Note: JIT is not recommended for production; use AOT for better performance.
460
278
 
461
279
  3. **Verify imports:**
462
280
  - Ensure you're importing from the built package (e.g., `import { MesAuthService } from 'mesauth-angular';`) and not from the `src` folder.
463
- - If using standalone components, confirm the service is available in the injection context.
464
-
465
- If issues persist, check your Angular version compatibility and ensure the package's `package.json` includes the correct entry points for AOT.
466
281
 
467
282
  ### Components Appear Empty
468
283
  If components like `ma-user` or `ma-user-profile` render as empty:
469
- - Ensure `MesAuthService` is provided in your app (see Quick Start step 2).
470
- - Check browser console for logs from components (e.g., "UserProfileComponent: currentUser").
471
- - If `currentUser` is null, the component shows a login button—verify the service is initialized and the API returns user data.
472
- - For standalone apps, confirm `APP_INITIALIZER` or manual init is used.
473
-
474
- ---
284
+ - Ensure `provideMesAuth()` is called in your `app.config.ts`.
285
+ - Check browser console for logs from components.
286
+ - If `currentUser` is null, the component shows a login button—verify the API returns user data.
475
287
 
476
- # Dynamic import in a module-based component
477
- import { Component } from '@angular/core';
478
-
479
- @Component({...})
480
- export class DefaultHeaderComponent {
481
- async ngOnInit() {
482
- const { MaUserComponent } = await import('mesauth-angular');
483
- // Use it dynamically
484
- }
485
- }
288
+ ## Notes
289
+ - The service expects an endpoint `GET {apiBaseUrl}/auth/me` that returns the current user.
290
+ - Avatar endpoint: `GET {apiBaseUrl}/auth/{userId}/avatar`
291
+ - SignalR events used: `ReceiveNotification` (adjust to your backend).