@opensourcekd/ng-common-libs 1.1.8

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OpensourceKD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,437 @@
1
+ # ng-common-libs
2
+
3
+ Angular 18 shareable utility library with framework-agnostic core and Angular wrappers for event handling, authorization, storage management, logging, and HTTP operations.
4
+
5
+ ## 🎯 Dual-Layer Architecture
6
+
7
+ This library features a **dual-layer architecture**:
8
+
9
+ - **Core Layer** (`@opensourcekd/ng-common-libs/core`): Framework-agnostic utilities using only RxJS and browser APIs. Use these in React, Vue, Svelte, or vanilla JavaScript projects.
10
+ - **Angular Layer** (`@opensourcekd/ng-common-libs` or `/angular`): Angular-specific wrappers with dependency injection, plus guards and interceptors that require Angular.
11
+
12
+ ## 🚀 Features
13
+
14
+ - **Event Bus**: Centralized event communication (framework-agnostic)
15
+ - **Token Manager**: JWT token management and validation (framework-agnostic)
16
+ - **Storage Manager**: Type-safe localStorage/sessionStorage wrapper (framework-agnostic)
17
+ - **Logger**: Configurable logging with multiple levels (framework-agnostic)
18
+ - **Authorization**: Angular guards, interceptors, and permission handling
19
+ - **HTTP Utilities**: Error handling, caching, and retry logic for Angular HTTP requests
20
+
21
+ ## 📦 Installation
22
+
23
+ ```bash
24
+ npm install @opensourcekd/ng-common-libs
25
+ ```
26
+
27
+ ## 🔧 Usage
28
+
29
+ ### For Angular Projects
30
+
31
+ Use the Angular-specific imports that provide dependency injection:
32
+
33
+ ```typescript
34
+ import { Component, OnInit, inject } from '@angular/core';
35
+ import { NgEventEmitter } from '@opensourcekd/ng-common-libs';
36
+
37
+ @Component({
38
+ selector: 'app-example',
39
+ template: `...`
40
+ })
41
+ export class ExampleComponent implements OnInit {
42
+ private eventEmitter = inject(NgEventEmitter);
43
+
44
+ ngOnInit() {
45
+ // Subscribe to events
46
+ this.eventEmitter.on('user:login').subscribe(data => {
47
+ console.log('User logged in:', data);
48
+ });
49
+ }
50
+
51
+ login() {
52
+ // Emit events
53
+ this.eventEmitter.emit('user:login', {
54
+ userId: '123',
55
+ username: 'john'
56
+ });
57
+ }
58
+ }
59
+ ```
60
+
61
+ ### Authorization
62
+
63
+ #### Token Service
64
+
65
+ Manage authentication tokens with ease:
66
+
67
+ ```typescript
68
+ import { inject } from '@angular/core';
69
+ import { TokenService } from '@opensourcekd/ng-common-libs';
70
+
71
+ export class AuthService {
72
+ private tokenService = inject(TokenService);
73
+
74
+ login(token: string) {
75
+ this.tokenService.setToken(token);
76
+ }
77
+
78
+ logout() {
79
+ this.tokenService.clearTokens();
80
+ }
81
+
82
+ isAuthenticated(): boolean {
83
+ return this.tokenService.isAuthenticated();
84
+ }
85
+
86
+ getUserData() {
87
+ return this.tokenService.getUserFromToken();
88
+ }
89
+ }
90
+ ```
91
+
92
+ #### Auth Guard
93
+
94
+ Protect routes with authentication guards:
95
+
96
+ ```typescript
97
+ import { Routes } from '@angular/router';
98
+ import { authGuard, createRoleGuard } from '@opensourcekd/ng-common-libs';
99
+
100
+ export const routes: Routes = [
101
+ {
102
+ path: 'dashboard',
103
+ component: DashboardComponent,
104
+ canActivate: [authGuard]
105
+ },
106
+ {
107
+ path: 'admin',
108
+ component: AdminComponent,
109
+ canActivate: [createRoleGuard(['admin'], { redirectUrl: '/unauthorized' })]
110
+ }
111
+ ];
112
+ ```
113
+
114
+ #### Auth Interceptor
115
+
116
+ Automatically add authentication tokens to HTTP requests:
117
+
118
+ ```typescript
119
+ import { ApplicationConfig } from '@angular/core';
120
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
121
+ import { authInterceptor, configureAuthInterceptor } from '@opensourcekd/ng-common-libs';
122
+
123
+ // Configure the interceptor (optional)
124
+ configureAuthInterceptor({
125
+ headerName: 'Authorization',
126
+ tokenPrefix: 'Bearer',
127
+ excludedUrls: ['/auth/login', '/auth/register']
128
+ });
129
+
130
+ export const appConfig: ApplicationConfig = {
131
+ providers: [
132
+ provideHttpClient(
133
+ withInterceptors([authInterceptor])
134
+ )
135
+ ]
136
+ };
137
+ ```
138
+
139
+ #### Permission Service
140
+
141
+ Check user permissions and roles:
142
+
143
+ ```typescript
144
+ import { inject } from '@angular/core';
145
+ import { PermissionService } from '@opensourcekd/ng-common-libs';
146
+
147
+ export class MyComponent {
148
+ private permissionService = inject(PermissionService);
149
+
150
+ canEditPost(): boolean {
151
+ return this.permissionService.hasPermission('posts:edit');
152
+ }
153
+
154
+ isAdmin(): boolean {
155
+ return this.permissionService.hasRole('admin');
156
+ }
157
+ }
158
+ ```
159
+
160
+ ### Storage Service
161
+
162
+ Type-safe storage operations with JSON serialization:
163
+
164
+ ```typescript
165
+ import { inject } from '@angular/core';
166
+ import { StorageService } from '@opensourcekd/ng-common-libs';
167
+
168
+ export class UserPreferencesService {
169
+ private storage = inject(StorageService);
170
+
171
+ savePreferences(prefs: UserPreferences) {
172
+ this.storage.setLocal('user-prefs', prefs);
173
+ }
174
+
175
+ getPreferences(): UserPreferences | null {
176
+ return this.storage.getLocal<UserPreferences>('user-prefs');
177
+ }
178
+
179
+ // With expiration (1 hour)
180
+ saveTempData(data: any) {
181
+ this.storage.setWithExpiration('temp-data', data, 3600000);
182
+ }
183
+
184
+ getTempData() {
185
+ return this.storage.getWithExpiration('temp-data');
186
+ }
187
+ }
188
+ ```
189
+
190
+ ### Logger Service
191
+
192
+ Centralized logging with configurable levels:
193
+
194
+ ```typescript
195
+ import { inject } from '@angular/core';
196
+ import { LoggerService, LogLevel } from '@opensourcekd/ng-common-libs';
197
+
198
+ export class MyService {
199
+ private logger = inject(LoggerService);
200
+
201
+ constructor() {
202
+ // Configure logger
203
+ this.logger.configure({
204
+ level: LogLevel.DEBUG,
205
+ enableTimestamp: true,
206
+ prefix: 'MyApp'
207
+ });
208
+ }
209
+
210
+ doSomething() {
211
+ this.logger.debug('Debug message');
212
+ this.logger.info('Info message');
213
+ this.logger.warn('Warning message');
214
+ this.logger.error('Error message', new Error('Something went wrong'));
215
+
216
+ // Measure execution time
217
+ this.logger.time('fetchData', async () => {
218
+ return await this.fetchData();
219
+ });
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### HTTP Utilities
225
+
226
+ #### Error Handling Interceptor
227
+
228
+ Handle HTTP errors with automatic retry:
229
+
230
+ ```typescript
231
+ import { ApplicationConfig } from '@angular/core';
232
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
233
+ import { errorHandlingInterceptor, configureErrorHandling } from '@opensourcekd/ng-common-libs';
234
+
235
+ // Configure error handling
236
+ configureErrorHandling({
237
+ enableLogging: true,
238
+ retryAttempts: 3,
239
+ retryDelay: 1000,
240
+ retryStatusCodes: [500, 502, 503, 504]
241
+ });
242
+
243
+ export const appConfig: ApplicationConfig = {
244
+ providers: [
245
+ provideHttpClient(
246
+ withInterceptors([errorHandlingInterceptor])
247
+ )
248
+ ]
249
+ };
250
+ ```
251
+
252
+ #### Caching Interceptor
253
+
254
+ Cache HTTP responses:
255
+
256
+ ```typescript
257
+ import { ApplicationConfig } from '@angular/core';
258
+ import { provideHttpClient, withInterceptors } from '@angular/common/http';
259
+ import { cachingInterceptor, configureCaching } from '@opensourcekd/ng-common-libs';
260
+
261
+ // Configure caching
262
+ configureCaching({
263
+ enabled: true,
264
+ maxAge: 300000, // 5 minutes
265
+ cacheableUrls: ['/api/users', '/api/products']
266
+ });
267
+
268
+ export const appConfig: ApplicationConfig = {
269
+ providers: [
270
+ provideHttpClient(
271
+ withInterceptors([cachingInterceptor])
272
+ )
273
+ ]
274
+ };
275
+ ```
276
+
277
+ ### For Non-Angular Projects (React, Vue, Svelte, Vanilla JS)
278
+
279
+ Use the framework-agnostic core utilities:
280
+
281
+ ```typescript
282
+ // Import from /core
283
+ import { EventBus, TokenManager, StorageManager, Logger, LogLevel } from '@opensourcekd/ng-common-libs/core';
284
+
285
+ // Event Bus
286
+ const eventBus = new EventBus();
287
+ eventBus.emit('user:login', { userId: '123' });
288
+ eventBus.on('user:login').subscribe(data => {
289
+ console.log('User logged in:', data);
290
+ });
291
+
292
+ // Token Manager
293
+ const tokenManager = new TokenManager();
294
+ tokenManager.setToken('your-jwt-token');
295
+ if (tokenManager.isAuthenticated()) {
296
+ const user = tokenManager.getUserFromToken();
297
+ }
298
+
299
+ // Storage Manager
300
+ const storage = new StorageManager();
301
+ storage.setLocal('preferences', { theme: 'dark' });
302
+ const prefs = storage.getLocal('preferences');
303
+
304
+ // Logger
305
+ const logger = new Logger();
306
+ logger.configure({ level: LogLevel.DEBUG, prefix: 'MyApp' });
307
+ logger.info('Application started');
308
+ ```
309
+
310
+ #### React Example
311
+
312
+ ```typescript
313
+ import { useEffect } from 'react';
314
+ import { EventBus } from '@opensourcekd/ng-common-libs/core';
315
+
316
+ const eventBus = new EventBus();
317
+
318
+ function MyComponent() {
319
+ useEffect(() => {
320
+ const subscription = eventBus.on('user:login').subscribe(data => {
321
+ console.log('User logged in:', data);
322
+ });
323
+ return () => subscription.unsubscribe();
324
+ }, []);
325
+
326
+ const handleLogin = () => {
327
+ eventBus.emit('user:login', { userId: '123' });
328
+ };
329
+
330
+ return <button onClick={handleLogin}>Login</button>;
331
+ }
332
+ ```
333
+
334
+ #### Vue Example
335
+
336
+ ```typescript
337
+ import { onMounted, onUnmounted } from 'vue';
338
+ import { EventBus } from '@opensourcekd/ng-common-libs/core';
339
+
340
+ const eventBus = new EventBus();
341
+
342
+ export default {
343
+ setup() {
344
+ let subscription;
345
+
346
+ onMounted(() => {
347
+ subscription = eventBus.on('user:login').subscribe(data => {
348
+ console.log('User logged in:', data);
349
+ });
350
+ });
351
+
352
+ onUnmounted(() => {
353
+ subscription?.unsubscribe();
354
+ });
355
+
356
+ const handleLogin = () => {
357
+ eventBus.emit('user:login', { userId: '123' });
358
+ };
359
+
360
+ return { handleLogin };
361
+ }
362
+ };
363
+ ```
364
+
365
+ ## 📚 Documentation
366
+
367
+ - **[Usage Guide](./docs/USAGE.md)** - Complete usage examples for all utilities
368
+ - **[API Reference](./docs/API.md)** - Detailed API documentation
369
+ - **[Deployment Guide](./docs/DEPLOYMENT.md)** - Publishing, versioning, and consumption
370
+ - **[Architecture Decisions](./ARCHITECTURE_DECISIONS.md)** - Detailed architecture and design decisions
371
+
372
+ ## 📝 API Documentation
373
+
374
+ ### NgEventEmitter
375
+
376
+ - `emit<T>(eventType: string, data?: T): void` - Emit an event
377
+ - `on<T>(eventType: string): Observable<T>` - Subscribe to an event
378
+ - `onMultiple(eventTypes: string[]): Observable<EventPayload>` - Subscribe to multiple events
379
+ - `onAll(): Observable<EventPayload>` - Subscribe to all events
380
+
381
+ ### TokenService
382
+
383
+ - `setToken(token: string): void` - Store authentication token
384
+ - `getToken(): string | null` - Retrieve authentication token
385
+ - `removeToken(): void` - Remove authentication token
386
+ - `clearTokens(): void` - Clear all tokens
387
+ - `isAuthenticated(): boolean` - Check if user is authenticated
388
+ - `isTokenExpired(token?: string): boolean` - Check if token is expired
389
+ - `getUserFromToken(token?: string): any` - Extract user data from token
390
+
391
+ ### StorageService
392
+
393
+ - `setLocal<T>(key: string, value: T): boolean` - Set item in localStorage
394
+ - `getLocal<T>(key: string, defaultValue?: T): T | null` - Get item from localStorage
395
+ - `removeLocal(key: string): void` - Remove item from localStorage
396
+ - `setSession<T>(key: string, value: T): boolean` - Set item in sessionStorage
397
+ - `getSession<T>(key: string, defaultValue?: T): T | null` - Get item from sessionStorage
398
+ - `setWithExpiration<T>(key, value, expirationMs, useSession?): boolean` - Set item with expiration
399
+ - `getWithExpiration<T>(key, useSession?): T | null` - Get item with expiration check
400
+
401
+ ### LoggerService
402
+
403
+ - `debug(message: string, ...args: any[]): void` - Log debug message
404
+ - `info(message: string, ...args: any[]): void` - Log info message
405
+ - `warn(message: string, ...args: any[]): void` - Log warning message
406
+ - `error(message: string, error?: any, ...args: any[]): void` - Log error message
407
+ - `time<T>(label: string, fn: () => Promise<T> | T): Promise<T>` - Measure execution time
408
+
409
+ ## 🛠️ Development
410
+
411
+ ```bash
412
+ # Install dependencies
413
+ npm install
414
+
415
+ # Build the library
416
+ npm run build
417
+
418
+ # Run linter
419
+ npm run lint
420
+ ```
421
+
422
+ ## 📄 License
423
+
424
+ MIT
425
+
426
+ ## 👤 Author
427
+
428
+ Koustubh Desai <jobs.koustubh@gmail.com>
429
+
430
+ ## 🤝 Contributing
431
+
432
+ Contributions, issues, and feature requests are welcome!
433
+
434
+ ## ⭐ Show your support
435
+
436
+ Give a ⭐️ if this project helped you!
437
+