@opensourcekd/ng-common-libs 1.2.4 → 1.2.5

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.
@@ -1,8 +1,6 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { Subject, ReplaySubject, BehaviorSubject, throwError, timer, Observable } from 'rxjs';
3
- import { filter, map, retry, catchError, tap } from 'rxjs/operators';
4
- import { HttpClient, HttpResponse } from '@angular/common/http';
5
- import { Router } from '@angular/router';
1
+ import { Injectable } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { ReplaySubject, BehaviorSubject } from 'rxjs';
6
4
 
7
5
  /******************************************************************************
8
6
  Copyright (c) Microsoft Corporation.
@@ -37,821 +35,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
37
35
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
36
  };
39
37
 
40
- /**
41
- * EventBus - A centralized event bus for application-wide communication
42
- * Framework-agnostic implementation using only RxJS
43
- *
44
- * @example
45
- * ```typescript
46
- * // Create an instance
47
- * const eventBus = new EventBus();
48
- *
49
- * // Emit an event
50
- * eventBus.emit('user:login', { userId: '123', username: 'john' });
51
- *
52
- * // Subscribe to an event
53
- * eventBus.on('user:login').subscribe(data => {
54
- * console.log('User logged in:', data);
55
- * });
56
- * ```
57
- */
58
- class EventBus {
59
- eventSubject = new Subject();
60
- /**
61
- * Emit an event with optional data
62
- * @param eventType - The type/name of the event
63
- * @param data - Optional data to send with the event
64
- */
65
- emit(eventType, data) {
66
- this.eventSubject.next({
67
- type: eventType,
68
- data,
69
- timestamp: Date.now()
70
- });
71
- }
72
- /**
73
- * Subscribe to a specific event type
74
- * @param eventType - The type/name of the event to listen for
75
- * @returns Observable that emits the event data
76
- */
77
- on(eventType) {
78
- return this.eventSubject.asObservable().pipe(filter(event => event.type === eventType), map(event => event.data));
79
- }
80
- /**
81
- * Subscribe to multiple event types
82
- * @param eventTypes - Array of event types to listen for
83
- * @returns Observable that emits the full event payload
84
- */
85
- onMultiple(eventTypes) {
86
- return this.eventSubject.asObservable().pipe(filter(event => eventTypes.includes(event.type)));
87
- }
88
- /**
89
- * Subscribe to all events
90
- * @returns Observable that emits all event payloads
91
- */
92
- onAll() {
93
- return this.eventSubject.asObservable();
94
- }
95
- }
96
-
97
- /**
98
- * NgEventEmitter - Angular service wrapper for EventBus
99
- * Provides Angular dependency injection support for the framework-agnostic EventBus
100
- *
101
- * @example
102
- * ```typescript
103
- * import { Component, inject } from '@angular/core';
104
- * import { NgEventEmitter } from 'common-libs';
105
- *
106
- * @Component({
107
- * selector: 'app-example',
108
- * template: '...'
109
- * })
110
- * export class ExampleComponent {
111
- * private eventEmitter = inject(NgEventEmitter);
112
- *
113
- * ngOnInit() {
114
- * this.eventEmitter.on('user:login').subscribe(data => {
115
- * console.log('User logged in:', data);
116
- * });
117
- * }
118
- *
119
- * login() {
120
- * this.eventEmitter.emit('user:login', { userId: '123' });
121
- * }
122
- * }
123
- * ```
124
- */
125
- let NgEventEmitter = class NgEventEmitter extends EventBus {
126
- constructor() {
127
- super();
128
- }
129
- };
130
- NgEventEmitter = __decorate([
131
- Injectable({
132
- providedIn: 'root'
133
- }),
134
- __metadata("design:paramtypes", [])
135
- ], NgEventEmitter);
136
-
137
- /**
138
- * TokenManager - Manages authentication tokens
139
- * Framework-agnostic implementation using browser storage APIs
140
- * Handles storage, retrieval, and validation of JWT tokens
141
- *
142
- * @example
143
- * ```typescript
144
- * const tokenManager = new TokenManager();
145
- *
146
- * // Store a token
147
- * tokenManager.setToken('your-jwt-token');
148
- *
149
- * // Check if authenticated
150
- * if (tokenManager.isAuthenticated()) {
151
- * const userData = tokenManager.getUserFromToken();
152
- * }
153
- * ```
154
- */
155
- class TokenManager {
156
- TOKEN_KEY = 'auth_token';
157
- REFRESH_TOKEN_KEY = 'refresh_token';
158
- useSessionStorage = false;
159
- /**
160
- * Configure token manager
161
- */
162
- configure(config) {
163
- if (config.tokenKey) {
164
- this.TOKEN_KEY = config.tokenKey;
165
- }
166
- if (config.refreshTokenKey) {
167
- this.REFRESH_TOKEN_KEY = config.refreshTokenKey;
168
- }
169
- if (config.useSessionStorage !== undefined) {
170
- this.useSessionStorage = config.useSessionStorage;
171
- }
172
- }
173
- /**
174
- * Get the storage mechanism based on configuration
175
- */
176
- getStorage() {
177
- return this.useSessionStorage ? sessionStorage : localStorage;
178
- }
179
- /**
180
- * Set authentication token
181
- */
182
- setToken(token) {
183
- this.getStorage().setItem(this.TOKEN_KEY, token);
184
- }
185
- /**
186
- * Get authentication token
187
- */
188
- getToken() {
189
- return this.getStorage().getItem(this.TOKEN_KEY);
190
- }
191
- /**
192
- * Remove authentication token
193
- */
194
- removeToken() {
195
- this.getStorage().removeItem(this.TOKEN_KEY);
196
- }
197
- /**
198
- * Set refresh token
199
- */
200
- setRefreshToken(token) {
201
- this.getStorage().setItem(this.REFRESH_TOKEN_KEY, token);
202
- }
203
- /**
204
- * Get refresh token
205
- */
206
- getRefreshToken() {
207
- return this.getStorage().getItem(this.REFRESH_TOKEN_KEY);
208
- }
209
- /**
210
- * Remove refresh token
211
- */
212
- removeRefreshToken() {
213
- this.getStorage().removeItem(this.REFRESH_TOKEN_KEY);
214
- }
215
- /**
216
- * Clear all tokens
217
- */
218
- clearTokens() {
219
- this.removeToken();
220
- this.removeRefreshToken();
221
- }
222
- /**
223
- * Check if token exists
224
- */
225
- hasToken() {
226
- return !!this.getToken();
227
- }
228
- /**
229
- * Decode JWT token (without verification)
230
- * @param token - JWT token to decode
231
- * @returns Decoded token payload or null if invalid
232
- */
233
- decodeToken(token) {
234
- const tokenToDecode = token || this.getToken();
235
- if (!tokenToDecode)
236
- return null;
237
- try {
238
- const parts = tokenToDecode.split('.');
239
- if (parts.length !== 3)
240
- return null;
241
- const payload = parts[1];
242
- const decoded = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/')));
243
- return decoded;
244
- }
245
- catch (error) {
246
- console.error('Error decoding token:', error);
247
- return null;
248
- }
249
- }
250
- /**
251
- * Check if token is expired
252
- * @param token - Optional token to check (defaults to stored token)
253
- * @returns true if token is expired or invalid
254
- */
255
- isTokenExpired(token) {
256
- const decoded = this.decodeToken(token);
257
- if (!decoded || !decoded.exp)
258
- return true;
259
- const expirationDate = new Date(decoded.exp * 1000);
260
- return expirationDate <= new Date();
261
- }
262
- /**
263
- * Check if user is authenticated (has valid, non-expired token)
264
- */
265
- isAuthenticated() {
266
- return this.hasToken() && !this.isTokenExpired();
267
- }
268
- /**
269
- * Get token expiration date
270
- */
271
- getTokenExpirationDate(token) {
272
- const decoded = this.decodeToken(token);
273
- if (!decoded || !decoded.exp)
274
- return null;
275
- return new Date(decoded.exp * 1000);
276
- }
277
- /**
278
- * Get user data from token
279
- */
280
- getUserFromToken(token) {
281
- return this.decodeToken(token);
282
- }
283
- }
284
-
285
- /**
286
- * TokenService - Angular service wrapper for TokenManager
287
- * Provides Angular dependency injection support for the framework-agnostic TokenManager
288
- *
289
- * @example
290
- * ```typescript
291
- * import { Component, inject } from '@angular/core';
292
- * import { TokenService } from 'common-libs';
293
- *
294
- * export class AuthService {
295
- * private tokenService = inject(TokenService);
296
- *
297
- * login(token: string) {
298
- * this.tokenService.setToken(token);
299
- * }
300
- *
301
- * isAuthenticated(): boolean {
302
- * return this.tokenService.isAuthenticated();
303
- * }
304
- * }
305
- * ```
306
- */
307
- let TokenService = class TokenService extends TokenManager {
308
- constructor() {
309
- console.log("In TokenService of opensourcekd 2");
310
- super();
311
- }
312
- };
313
- TokenService = __decorate([
314
- Injectable({
315
- providedIn: 'root'
316
- }),
317
- __metadata("design:paramtypes", [])
318
- ], TokenService);
319
-
320
- /**
321
- * StorageManager - Type-safe wrapper for browser storage
322
- * Framework-agnostic implementation using browser storage APIs
323
- * Provides JSON serialization/deserialization and error handling
324
- *
325
- * @example
326
- * ```typescript
327
- * const storage = new StorageManager();
328
- *
329
- * // Store data
330
- * storage.setLocal('user-prefs', { theme: 'dark', lang: 'en' });
331
- *
332
- * // Retrieve data
333
- * const prefs = storage.getLocal('user-prefs');
334
- *
335
- * // With expiration
336
- * storage.setWithExpiration('temp-data', someData, 3600000); // 1 hour
337
- * ```
338
- */
339
- class StorageManager {
340
- /**
341
- * Set item in localStorage with JSON serialization
342
- */
343
- setLocal(key, value) {
344
- try {
345
- const serialized = JSON.stringify(value);
346
- localStorage.setItem(key, serialized);
347
- return true;
348
- }
349
- catch (error) {
350
- console.error('Error setting localStorage item:', error);
351
- return false;
352
- }
353
- }
354
- /**
355
- * Get item from localStorage with JSON deserialization
356
- */
357
- getLocal(key, defaultValue) {
358
- try {
359
- const item = localStorage.getItem(key);
360
- if (item === null) {
361
- return defaultValue !== undefined ? defaultValue : null;
362
- }
363
- return JSON.parse(item);
364
- }
365
- catch (error) {
366
- console.error('Error getting localStorage item:', error);
367
- return defaultValue !== undefined ? defaultValue : null;
368
- }
369
- }
370
- /**
371
- * Remove item from localStorage
372
- */
373
- removeLocal(key) {
374
- try {
375
- localStorage.removeItem(key);
376
- }
377
- catch (error) {
378
- console.error('Error removing localStorage item:', error);
379
- }
380
- }
381
- /**
382
- * Clear all localStorage items
383
- */
384
- clearLocal() {
385
- try {
386
- localStorage.clear();
387
- }
388
- catch (error) {
389
- console.error('Error clearing localStorage:', error);
390
- }
391
- }
392
- /**
393
- * Check if key exists in localStorage
394
- */
395
- hasLocal(key) {
396
- try {
397
- return localStorage.getItem(key) !== null;
398
- }
399
- catch (error) {
400
- console.error('Error checking localStorage key:', error);
401
- return false;
402
- }
403
- }
404
- /**
405
- * Get all localStorage keys
406
- */
407
- getLocalKeys() {
408
- try {
409
- return Object.keys(localStorage);
410
- }
411
- catch (error) {
412
- console.error('Error getting localStorage keys:', error);
413
- return [];
414
- }
415
- }
416
- /**
417
- * Set item in sessionStorage with JSON serialization
418
- */
419
- setSession(key, value) {
420
- try {
421
- const serialized = JSON.stringify(value);
422
- sessionStorage.setItem(key, serialized);
423
- return true;
424
- }
425
- catch (error) {
426
- console.error('Error setting sessionStorage item:', error);
427
- return false;
428
- }
429
- }
430
- /**
431
- * Get item from sessionStorage with JSON deserialization
432
- */
433
- getSession(key, defaultValue) {
434
- try {
435
- const item = sessionStorage.getItem(key);
436
- if (item === null) {
437
- return defaultValue !== undefined ? defaultValue : null;
438
- }
439
- return JSON.parse(item);
440
- }
441
- catch (error) {
442
- console.error('Error getting sessionStorage item:', error);
443
- return defaultValue !== undefined ? defaultValue : null;
444
- }
445
- }
446
- /**
447
- * Remove item from sessionStorage
448
- */
449
- removeSession(key) {
450
- try {
451
- sessionStorage.removeItem(key);
452
- }
453
- catch (error) {
454
- console.error('Error removing sessionStorage item:', error);
455
- }
456
- }
457
- /**
458
- * Clear all sessionStorage items
459
- */
460
- clearSession() {
461
- try {
462
- sessionStorage.clear();
463
- }
464
- catch (error) {
465
- console.error('Error clearing sessionStorage:', error);
466
- }
467
- }
468
- /**
469
- * Check if key exists in sessionStorage
470
- */
471
- hasSession(key) {
472
- try {
473
- return sessionStorage.getItem(key) !== null;
474
- }
475
- catch (error) {
476
- console.error('Error checking sessionStorage key:', error);
477
- return false;
478
- }
479
- }
480
- /**
481
- * Get all sessionStorage keys
482
- */
483
- getSessionKeys() {
484
- try {
485
- return Object.keys(sessionStorage);
486
- }
487
- catch (error) {
488
- console.error('Error getting sessionStorage keys:', error);
489
- return [];
490
- }
491
- }
492
- /**
493
- * Set item with expiration time
494
- * @param key - Storage key
495
- * @param value - Value to store
496
- * @param expirationMs - Expiration time in milliseconds
497
- * @param useSession - Use sessionStorage instead of localStorage
498
- */
499
- setWithExpiration(key, value, expirationMs, useSession = false) {
500
- const item = {
501
- value,
502
- expiration: Date.now() + expirationMs
503
- };
504
- return useSession
505
- ? this.setSession(key, item)
506
- : this.setLocal(key, item);
507
- }
508
- /**
509
- * Get item with expiration check
510
- * Returns null if item is expired
511
- */
512
- getWithExpiration(key, useSession = false) {
513
- const item = useSession
514
- ? this.getSession(key)
515
- : this.getLocal(key);
516
- if (!item)
517
- return null;
518
- if (Date.now() > item.expiration) {
519
- // Item expired, remove it
520
- if (useSession) {
521
- this.removeSession(key);
522
- }
523
- else {
524
- this.removeLocal(key);
525
- }
526
- return null;
527
- }
528
- return item.value;
529
- }
530
- }
531
-
532
- /**
533
- * StorageService - Angular service wrapper for StorageManager
534
- * Provides Angular dependency injection support for the framework-agnostic StorageManager
535
- *
536
- * @example
537
- * ```typescript
538
- * import { Component, inject } from '@angular/core';
539
- * import { StorageService } from 'common-libs';
540
- *
541
- * export class UserPreferencesService {
542
- * private storage = inject(StorageService);
543
- *
544
- * savePreferences(prefs: any) {
545
- * this.storage.setLocal('user-prefs', prefs);
546
- * }
547
- *
548
- * getPreferences() {
549
- * return this.storage.getLocal('user-prefs');
550
- * }
551
- * }
552
- * ```
553
- */
554
- let StorageService = class StorageService extends StorageManager {
555
- constructor() {
556
- super();
557
- }
558
- };
559
- StorageService = __decorate([
560
- Injectable({
561
- providedIn: 'root'
562
- }),
563
- __metadata("design:paramtypes", [])
564
- ], StorageService);
565
-
566
- /**
567
- * Log level enum
568
- */
569
- var LogLevel;
570
- (function (LogLevel) {
571
- LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
572
- LogLevel[LogLevel["INFO"] = 1] = "INFO";
573
- LogLevel[LogLevel["WARN"] = 2] = "WARN";
574
- LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
575
- LogLevel[LogLevel["NONE"] = 4] = "NONE";
576
- })(LogLevel || (LogLevel = {}));
577
- /**
578
- * Logger - Centralized logging utility
579
- * Framework-agnostic implementation using browser console APIs
580
- * Supports different log levels and can be configured globally
581
- *
582
- * @example
583
- * ```typescript
584
- * const logger = new Logger();
585
- *
586
- * // Configure
587
- * logger.configure({
588
- * level: LogLevel.DEBUG,
589
- * enableTimestamp: true,
590
- * prefix: 'MyApp'
591
- * });
592
- *
593
- * // Use
594
- * logger.info('User logged in', { userId: '123' });
595
- * logger.error('Failed to load data', error);
596
- * ```
597
- */
598
- class Logger {
599
- config = {
600
- level: LogLevel.INFO,
601
- enableTimestamp: true,
602
- enableStackTrace: false,
603
- prefix: ''
604
- };
605
- /**
606
- * Configure the logger
607
- */
608
- configure(config) {
609
- this.config = { ...this.config, ...config };
610
- }
611
- /**
612
- * Set log level
613
- */
614
- setLevel(level) {
615
- this.config.level = level;
616
- }
617
- /**
618
- * Get current log level
619
- */
620
- getLevel() {
621
- return this.config.level;
622
- }
623
- /**
624
- * Format log message with timestamp and prefix
625
- */
626
- formatMessage(message, level) {
627
- const parts = [];
628
- if (this.config.enableTimestamp) {
629
- parts.push(`[${new Date().toISOString()}]`);
630
- }
631
- if (this.config.prefix) {
632
- parts.push(`[${this.config.prefix}]`);
633
- }
634
- parts.push(`[${level}]`);
635
- parts.push(message);
636
- return parts.join(' ');
637
- }
638
- /**
639
- * Check if log level should be logged
640
- */
641
- shouldLog(level) {
642
- return level >= this.config.level;
643
- }
644
- /**
645
- * Log debug message
646
- */
647
- debug(message, ...args) {
648
- if (this.shouldLog(LogLevel.DEBUG)) {
649
- console.debug(this.formatMessage(message, 'DEBUG'), ...args);
650
- }
651
- }
652
- /**
653
- * Log info message
654
- */
655
- info(message, ...args) {
656
- if (this.shouldLog(LogLevel.INFO)) {
657
- console.info(this.formatMessage(message, 'INFO'), ...args);
658
- }
659
- }
660
- /**
661
- * Log warning message
662
- */
663
- warn(message, ...args) {
664
- if (this.shouldLog(LogLevel.WARN)) {
665
- console.warn(this.formatMessage(message, 'WARN'), ...args);
666
- }
667
- }
668
- /**
669
- * Log error message
670
- */
671
- error(message, error, ...args) {
672
- if (this.shouldLog(LogLevel.ERROR)) {
673
- console.error(this.formatMessage(message, 'ERROR'), ...args);
674
- if (error) {
675
- console.error(error);
676
- if (this.config.enableStackTrace && error?.stack) {
677
- console.error('Stack trace:', error.stack);
678
- }
679
- }
680
- }
681
- }
682
- /**
683
- * Log a group of messages
684
- */
685
- group(label, callback) {
686
- if (this.shouldLog(LogLevel.INFO)) {
687
- console.group(this.formatMessage(label, 'GROUP'));
688
- callback();
689
- console.groupEnd();
690
- }
691
- }
692
- /**
693
- * Log a collapsed group of messages
694
- */
695
- groupCollapsed(label, callback) {
696
- if (this.shouldLog(LogLevel.INFO)) {
697
- console.groupCollapsed(this.formatMessage(label, 'GROUP'));
698
- callback();
699
- console.groupEnd();
700
- }
701
- }
702
- /**
703
- * Log a table (useful for arrays of objects)
704
- */
705
- table(data, columns) {
706
- if (this.shouldLog(LogLevel.INFO)) {
707
- console.table(data, columns);
708
- }
709
- }
710
- /**
711
- * Log execution time of a function
712
- */
713
- async time(label, fn) {
714
- const start = performance.now();
715
- try {
716
- const result = await fn();
717
- const end = performance.now();
718
- const duration = (end - start).toFixed(2);
719
- this.info(`${label} completed in ${duration}ms`);
720
- return result;
721
- }
722
- catch (error) {
723
- const end = performance.now();
724
- const duration = (end - start).toFixed(2);
725
- this.error(`${label} failed after ${duration}ms`, error);
726
- throw error;
727
- }
728
- }
729
- }
730
-
731
- /**
732
- * LoggerService - Angular service wrapper for Logger
733
- * Provides Angular dependency injection support for the framework-agnostic Logger
734
- *
735
- * @example
736
- * ```typescript
737
- * import { Component, inject } from '@angular/core';
738
- * import { LoggerService, LogLevel } from 'common-libs';
739
- *
740
- * export class MyService {
741
- * private logger = inject(LoggerService);
742
- *
743
- * constructor() {
744
- * this.logger.configure({
745
- * level: LogLevel.DEBUG,
746
- * prefix: 'MyApp'
747
- * });
748
- * }
749
- *
750
- * doSomething() {
751
- * this.logger.info('Doing something');
752
- * }
753
- * }
754
- * ```
755
- */
756
- let LoggerService = class LoggerService extends Logger {
757
- constructor() {
758
- super();
759
- }
760
- };
761
- LoggerService = __decorate([
762
- Injectable({
763
- providedIn: 'root'
764
- }),
765
- __metadata("design:paramtypes", [])
766
- ], LoggerService);
767
-
768
- /**
769
- * PermissionService - Manages user permissions and roles
770
- */
771
- let PermissionService = class PermissionService {
772
- tokenService = inject(TokenService);
773
- /**
774
- * Check if user has a specific permission
775
- */
776
- hasPermission(permission) {
777
- const user = this.tokenService.getUserFromToken();
778
- const permissions = user?.permissions || [];
779
- return permissions.includes(permission);
780
- }
781
- /**
782
- * Check if user has any of the specified permissions
783
- */
784
- hasAnyPermission(permissions) {
785
- return permissions.some(permission => this.hasPermission(permission));
786
- }
787
- /**
788
- * Check if user has all of the specified permissions
789
- */
790
- hasAllPermissions(permissions) {
791
- return permissions.every(permission => this.hasPermission(permission));
792
- }
793
- /**
794
- * Check if user has a specific role
795
- */
796
- hasRole(role) {
797
- const user = this.tokenService.getUserFromToken();
798
- const roles = user?.roles || [];
799
- return roles.includes(role);
800
- }
801
- /**
802
- * Check if user has any of the specified roles
803
- */
804
- hasAnyRole(roles) {
805
- return roles.some(role => this.hasRole(role));
806
- }
807
- /**
808
- * Check if user has all of the specified roles
809
- */
810
- hasAllRoles(roles) {
811
- return roles.every(role => this.hasRole(role));
812
- }
813
- /**
814
- * Get all user permissions
815
- */
816
- getPermissions() {
817
- const user = this.tokenService.getUserFromToken();
818
- return user?.permissions || [];
819
- }
820
- /**
821
- * Get all user roles
822
- */
823
- getRoles() {
824
- const user = this.tokenService.getUserFromToken();
825
- return user?.roles || [];
826
- }
827
- /**
828
- * Get user ID from token
829
- */
830
- getUserId() {
831
- const user = this.tokenService.getUserFromToken();
832
- return user?.sub || user?.id || user?.userId || null;
833
- }
834
- /**
835
- * Get username from token
836
- */
837
- getUsername() {
838
- const user = this.tokenService.getUserFromToken();
839
- return user?.username || user?.name || user?.email || null;
840
- }
841
- /**
842
- * Get user email from token
843
- */
844
- getUserEmail() {
845
- const user = this.tokenService.getUserFromToken();
846
- return user?.email || null;
847
- }
848
- };
849
- PermissionService = __decorate([
850
- Injectable({
851
- providedIn: 'root'
852
- })
853
- ], PermissionService);
854
-
855
38
  function mitt(n){return {all:n=n||new Map,on:function(t,e){var i=n.get(t);i?i.push(e):n.set(t,[e]);},off:function(t,e){var i=n.get(t);i&&(e?i.splice(i.indexOf(e)>>>0,1):n.set(t,[]));},emit:function(t,e){var i=n.get(t);i&&i.slice().map(function(n){n(e);}),(i=n.get("*"))&&i.slice().map(function(n){n(t,e);});}}}
856
39
 
857
40
  /**
@@ -1490,404 +673,5 @@ AuthService = __decorate([
1490
673
  EventBusService])
1491
674
  ], AuthService);
1492
675
 
1493
- /**
1494
- * Factory function to create an auth guard with configuration
1495
- *
1496
- * @example
1497
- * ```typescript
1498
- * // In routes
1499
- * {
1500
- * path: 'dashboard',
1501
- * component: DashboardComponent,
1502
- * canActivate: [createAuthGuard({ redirectUrl: '/login' })]
1503
- * }
1504
- * ```
1505
- */
1506
- function createAuthGuard(config = {}) {
1507
- return (route, state) => {
1508
- const tokenService = inject(TokenService);
1509
- const router = inject(Router);
1510
- const redirectUrl = config.redirectUrl || '/login';
1511
- const checkExpiration = config.checkExpiration !== false;
1512
- const hasToken = tokenService.hasToken();
1513
- const isExpired = checkExpiration ? tokenService.isTokenExpired() : false;
1514
- if (hasToken && !isExpired) {
1515
- return true;
1516
- }
1517
- // Store the attempted URL for redirecting after login
1518
- const returnUrl = state.url;
1519
- router.navigate([redirectUrl], {
1520
- queryParams: { returnUrl },
1521
- queryParamsHandling: 'merge'
1522
- });
1523
- return false;
1524
- };
1525
- }
1526
- /**
1527
- * Default auth guard - redirects to '/login' if not authenticated
1528
- */
1529
- const authGuard = createAuthGuard();
1530
- /**
1531
- * Permission-based guard factory
1532
- * Checks if user has required permissions from token
1533
- *
1534
- * @example
1535
- * ```typescript
1536
- * {
1537
- * path: 'admin',
1538
- * component: AdminComponent,
1539
- * canActivate: [createPermissionGuard(['admin', 'editor'])]
1540
- * }
1541
- * ```
1542
- */
1543
- function createPermissionGuard(requiredPermissions, config = {}) {
1544
- return (route, state) => {
1545
- const tokenService = inject(TokenService);
1546
- const router = inject(Router);
1547
- const redirectUrl = config.redirectUrl || '/unauthorized';
1548
- // First check authentication
1549
- if (!tokenService.isAuthenticated()) {
1550
- router.navigate(['/login'], {
1551
- queryParams: { returnUrl: state.url }
1552
- });
1553
- return false;
1554
- }
1555
- // Check permissions
1556
- const user = tokenService.getUserFromToken();
1557
- const userPermissions = user?.permissions || user?.roles || [];
1558
- const hasPermission = requiredPermissions.some(permission => userPermissions.includes(permission));
1559
- if (!hasPermission) {
1560
- router.navigate([redirectUrl]);
1561
- return false;
1562
- }
1563
- return true;
1564
- };
1565
- }
1566
- /**
1567
- * Role-based guard factory
1568
- * Checks if user has required role from token
1569
- *
1570
- * @example
1571
- * ```typescript
1572
- * {
1573
- * path: 'admin',
1574
- * component: AdminComponent,
1575
- * canActivate: [createRoleGuard(['admin'])]
1576
- * }
1577
- * ```
1578
- */
1579
- function createRoleGuard(requiredRoles, config = {}) {
1580
- return createPermissionGuard(requiredRoles, config);
1581
- }
1582
-
1583
- const defaultConfig$1 = {
1584
- headerName: 'Authorization',
1585
- tokenPrefix: 'Bearer',
1586
- excludedUrls: []
1587
- };
1588
- let interceptorConfig = { ...defaultConfig$1 };
1589
- /**
1590
- * Configure the auth interceptor
1591
- */
1592
- function configureAuthInterceptor(config) {
1593
- interceptorConfig = { ...defaultConfig$1, ...config };
1594
- }
1595
- /**
1596
- * Auth Interceptor - Automatically adds authentication token to HTTP requests
1597
- *
1598
- * @example
1599
- * ```typescript
1600
- * // In app.config.ts
1601
- * export const appConfig: ApplicationConfig = {
1602
- * providers: [
1603
- * provideHttpClient(
1604
- * withInterceptors([authInterceptor])
1605
- * )
1606
- * ]
1607
- * };
1608
- * ```
1609
- */
1610
- const authInterceptor = (req, next) => {
1611
- const tokenService = inject(TokenService);
1612
- const config = interceptorConfig;
1613
- // Check if URL should be excluded
1614
- const isExcluded = config.excludedUrls?.some(url => req.url.includes(url));
1615
- if (isExcluded) {
1616
- return next(req);
1617
- }
1618
- // Get token and add to request if available
1619
- const token = tokenService.getToken();
1620
- if (token) {
1621
- const authReq = req.clone({
1622
- setHeaders: {
1623
- [config.headerName]: `${config.tokenPrefix} ${token}`
1624
- }
1625
- });
1626
- return next(authReq);
1627
- }
1628
- return next(req);
1629
- };
1630
-
1631
- const defaultConfig = {
1632
- enableLogging: true,
1633
- retryAttempts: 0,
1634
- retryDelay: 1000,
1635
- retryStatusCodes: [408, 429, 500, 502, 503, 504],
1636
- excludedUrls: []
1637
- };
1638
- let errorConfig = { ...defaultConfig };
1639
- /**
1640
- * Configure the error handling interceptor
1641
- */
1642
- function configureErrorHandling(config) {
1643
- errorConfig = { ...defaultConfig, ...config };
1644
- }
1645
- /**
1646
- * Error handling interceptor - Handles HTTP errors and retries
1647
- *
1648
- * @example
1649
- * ```typescript
1650
- * // In app.config.ts
1651
- * export const appConfig: ApplicationConfig = {
1652
- * providers: [
1653
- * provideHttpClient(
1654
- * withInterceptors([errorHandlingInterceptor])
1655
- * )
1656
- * ]
1657
- * };
1658
- *
1659
- * // Configure retry behavior
1660
- * configureErrorHandling({
1661
- * retryAttempts: 3,
1662
- * retryDelay: 2000,
1663
- * retryStatusCodes: [500, 502, 503]
1664
- * });
1665
- * ```
1666
- */
1667
- const errorHandlingInterceptor = (req, next) => {
1668
- const logger = inject(LoggerService);
1669
- const config = errorConfig;
1670
- // Check if URL should be excluded
1671
- const isExcluded = config.excludedUrls?.some(url => req.url.includes(url));
1672
- if (isExcluded) {
1673
- return next(req);
1674
- }
1675
- return next(req).pipe(
1676
- // Retry logic with exponential backoff
1677
- retry({
1678
- count: config.retryAttempts,
1679
- delay: (error, retryCount) => {
1680
- // Only retry for specific status codes
1681
- if (!config.retryStatusCodes?.includes(error.status)) {
1682
- return throwError(() => error);
1683
- }
1684
- const delay = config.retryDelay * Math.pow(2, retryCount - 1);
1685
- if (config.enableLogging) {
1686
- logger.warn(`Retrying request (attempt ${retryCount}) after ${delay}ms`, { url: req.url, status: error.status });
1687
- }
1688
- return timer(delay);
1689
- }
1690
- }),
1691
- // Error handling
1692
- catchError((error) => {
1693
- if (config.enableLogging) {
1694
- logger.error('HTTP request failed', error, {
1695
- url: req.url,
1696
- status: error.status,
1697
- message: error.message
1698
- });
1699
- }
1700
- return throwError(() => error);
1701
- }));
1702
- };
1703
- /**
1704
- * HTTP Error class with additional context
1705
- */
1706
- class HttpError extends Error {
1707
- status;
1708
- statusText;
1709
- url;
1710
- originalError;
1711
- constructor(status, statusText, url, originalError) {
1712
- super(`HTTP ${status} ${statusText}: ${url}`);
1713
- this.status = status;
1714
- this.statusText = statusText;
1715
- this.url = url;
1716
- this.originalError = originalError;
1717
- this.name = 'HttpError';
1718
- }
1719
- }
1720
- /**
1721
- * Parse HTTP error and return user-friendly message
1722
- */
1723
- function parseHttpError(error) {
1724
- if (error.error instanceof ErrorEvent) {
1725
- // Client-side error
1726
- return `Network error: ${error.error.message}`;
1727
- }
1728
- else {
1729
- // Server-side error
1730
- const errorMessage = error.error?.message || error.message || 'Unknown error';
1731
- return `Server error (${error.status}): ${errorMessage}`;
1732
- }
1733
- }
1734
- /**
1735
- * Check if error is a network error
1736
- */
1737
- function isNetworkError(error) {
1738
- return error.error instanceof ErrorEvent || error.status === 0;
1739
- }
1740
- /**
1741
- * Check if error is a server error (5xx)
1742
- */
1743
- function isServerError(error) {
1744
- return error.status >= 500 && error.status < 600;
1745
- }
1746
- /**
1747
- * Check if error is a client error (4xx)
1748
- */
1749
- function isClientError(error) {
1750
- return error.status >= 400 && error.status < 500;
1751
- }
1752
-
1753
- const defaultCacheConfig = {
1754
- enabled: true,
1755
- maxAge: 60000, // 1 minute
1756
- excludedUrls: [],
1757
- cacheableUrls: [],
1758
- cacheMethods: ['GET']
1759
- };
1760
- let cacheConfig = { ...defaultCacheConfig };
1761
- const cache = new Map();
1762
- const MAX_CACHE_SIZE = 100; // Maximum number of cached entries
1763
- /**
1764
- * Configure the caching interceptor
1765
- */
1766
- function configureCaching(config) {
1767
- cacheConfig = { ...defaultCacheConfig, ...config };
1768
- }
1769
- /**
1770
- * Clean up expired cache entries
1771
- */
1772
- function cleanupCache() {
1773
- const now = Date.now();
1774
- const keysToDelete = [];
1775
- cache.forEach((entry, key) => {
1776
- const age = now - entry.timestamp;
1777
- if (age >= cacheConfig.maxAge) {
1778
- keysToDelete.push(key);
1779
- }
1780
- });
1781
- keysToDelete.forEach(key => cache.delete(key));
1782
- }
1783
- /**
1784
- * Evict oldest cache entry if cache is full
1785
- */
1786
- function evictOldestIfFull() {
1787
- if (cache.size >= MAX_CACHE_SIZE) {
1788
- let oldestKey = null;
1789
- let oldestTimestamp = Infinity;
1790
- cache.forEach((entry, key) => {
1791
- if (entry.timestamp < oldestTimestamp) {
1792
- oldestTimestamp = entry.timestamp;
1793
- oldestKey = key;
1794
- }
1795
- });
1796
- if (oldestKey) {
1797
- cache.delete(oldestKey);
1798
- }
1799
- }
1800
- }
1801
- /**
1802
- * Clear all cached entries
1803
- */
1804
- function clearCache() {
1805
- cache.clear();
1806
- }
1807
- /**
1808
- * Clear cache entry for specific URL
1809
- */
1810
- function clearCacheEntry(url) {
1811
- cache.delete(url);
1812
- }
1813
- /**
1814
- * Caching interceptor - Caches HTTP GET requests
1815
- *
1816
- * @example
1817
- * ```typescript
1818
- * // In app.config.ts
1819
- * export const appConfig: ApplicationConfig = {
1820
- * providers: [
1821
- * provideHttpClient(
1822
- * withInterceptors([cachingInterceptor])
1823
- * )
1824
- * ]
1825
- * };
1826
- *
1827
- * // Configure caching
1828
- * configureCaching({
1829
- * enabled: true,
1830
- * maxAge: 300000, // 5 minutes
1831
- * cacheableUrls: ['/api/users', '/api/products']
1832
- * });
1833
- * ```
1834
- */
1835
- const cachingInterceptor = (req, next) => {
1836
- const logger = inject(LoggerService);
1837
- const config = cacheConfig;
1838
- // Only cache if enabled
1839
- if (!config.enabled) {
1840
- return next(req);
1841
- }
1842
- // Only cache specific methods (default: GET)
1843
- if (!config.cacheMethods?.includes(req.method)) {
1844
- return next(req);
1845
- }
1846
- // Check if URL should be excluded
1847
- const isExcluded = config.excludedUrls?.some(url => req.url.includes(url));
1848
- if (isExcluded) {
1849
- return next(req);
1850
- }
1851
- // Check if URL is explicitly cacheable (if list is provided)
1852
- if (config.cacheableUrls && config.cacheableUrls.length > 0) {
1853
- const isCacheable = config.cacheableUrls.some(url => req.url.includes(url));
1854
- if (!isCacheable) {
1855
- return next(req);
1856
- }
1857
- }
1858
- const cacheKey = req.urlWithParams;
1859
- // Check cache
1860
- const cached = cache.get(cacheKey);
1861
- if (cached) {
1862
- const age = Date.now() - cached.timestamp;
1863
- if (age < config.maxAge) {
1864
- logger.debug(`Cache hit for ${cacheKey}`, { age });
1865
- return new Observable(observer => {
1866
- observer.next(cached.response.clone());
1867
- observer.complete();
1868
- });
1869
- }
1870
- else {
1871
- // Cache expired
1872
- cache.delete(cacheKey);
1873
- }
1874
- }
1875
- // Clean up expired entries periodically
1876
- if (Math.random() < 0.1) { // 10% chance on each request
1877
- cleanupCache();
1878
- }
1879
- // Make request and cache response
1880
- return next(req).pipe(tap(event => {
1881
- if (event instanceof HttpResponse) {
1882
- evictOldestIfFull();
1883
- cache.set(cacheKey, {
1884
- response: event.clone(),
1885
- timestamp: Date.now()
1886
- });
1887
- logger.debug(`Cached response for ${cacheKey}`);
1888
- }
1889
- }));
1890
- };
1891
-
1892
- export { AUTH0_CONFIG, AuthService, EventBusService, HttpError, LogLevel, LoggerService, NgEventEmitter, PermissionService, STORAGE_CONFIG, STORAGE_KEYS, StorageService, TokenService, authGuard, authInterceptor, cachingInterceptor, clearCache, clearCacheEntry, configureAuth0, configureAuthInterceptor, configureCaching, configureErrorHandling, createAuthGuard, createPermissionGuard, createRoleGuard, errorHandlingInterceptor, getStorageItem, isClientError, isNetworkError, isServerError, parseHttpError, removeStorageItem, setStorageItem };
676
+ export { AUTH0_CONFIG, AuthService, EventBusService, STORAGE_CONFIG, STORAGE_KEYS, configureAuth0, getStorageItem, removeStorageItem, setStorageItem };
1893
677
  //# sourceMappingURL=index.mjs.map