@telperion/ng-pack 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @telperion/ng-pack
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@telperion/ng-pack.svg)](https://www.npmjs.com/package/@telperion/ng-pack)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@telperion/ng-pack.svg)](https://www.npmjs.com/package/@telperion/ng-pack)
5
+ [![License](https://img.shields.io/npm/l/@telperion/ng-pack.svg)](https://github.com/telperiontech/telperion/blob/main/libs/ng-pack/LICENSE)
6
+
3
7
  A collection of Angular utilities and libraries
4
8
 
5
9
  ## Installation
@@ -127,7 +131,7 @@ export class StockTickerComponent {
127
131
  }
128
132
  ```
129
133
 
130
- [Full documentation →](./sse-client/README.md)
134
+ [Full documentation →](https://github.com/telperiontech/telperion/tree/main/libs/ng-pack/sse-client)
131
135
 
132
136
  ---
133
137
 
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "@telperion/ng-pack",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
+ "description": "Collection of Angular utilities and libraries organized as secondary entry points. Includes signal-based storage (localStorage/sessionStorage), SSE client with HttpClient-inspired interceptors, event modifier plugins, and more. Built with TypeScript, RxJS, and Angular Signals for modern Angular applications.",
5
+ "keywords": [
6
+ "angular",
7
+ "angular-signals",
8
+ "rxjs",
9
+ "sse",
10
+ "server-sent-events",
11
+ "eventsource",
12
+ "localstorage",
13
+ "sessionstorage",
14
+ "storage",
15
+ "signals",
16
+ "interceptors",
17
+ "event-modifiers",
18
+ "utilities",
19
+ "typescript",
20
+ "reactive",
21
+ "real-time",
22
+ "httpclient",
23
+ "secondary-entrypoint",
24
+ "angular-utilities",
25
+ "event-manager"
26
+ ],
4
27
  "peerDependencies": {
5
28
  "@angular/common": "^21.0.0",
6
29
  "@angular/core": "^21.0.0",
@@ -5,7 +5,7 @@ Angular service for Server-Sent Events (SSE) with RxJS Observables and HttpClien
5
5
  ## Features
6
6
 
7
7
  - 🚀 **Observable-based API** - Seamlessly integrate with RxJS ecosystem
8
- - 🔗 **HttpClient-inspired interceptors** - Familiar pattern for request/response manipulation
8
+ - 🔗 **HttpClient-inspired interceptors** - Functional and class-based interceptors (shareable with HttpClient)
9
9
  - 🎯 **Type-safe** - Full TypeScript support with generic typing
10
10
  - ⚡ **EventSource wrapper** - Clean abstraction over native EventSource API
11
11
  - 🔄 **Reactive streaming** - Real-time data updates with automatic cleanup
@@ -163,6 +163,84 @@ export const appConfig: ApplicationConfig = {
163
163
 
164
164
  **Interceptor execution order:** Interceptors are executed in the order they are provided. In the example above, the chain is: logging → auth → retry → EventSource connection.
165
165
 
166
+ #### Class-based Interceptors
167
+
168
+ For more complex scenarios, you can create class-based interceptors and provide them directly using the `SSE_INTERCEPTORS` token. This is particularly useful when you need dependency injection or want to share logic between HTTP and SSE interceptors.
169
+
170
+ **Using SSE_INTERCEPTORS token:**
171
+
172
+ ```typescript
173
+ import { Injectable } from '@angular/core';
174
+ import { SseInterceptor, SseRequest, SseNextFn, SSE_INTERCEPTORS } from '@telperion/ng-pack/sse-client';
175
+ import { Observable } from 'rxjs';
176
+
177
+ @Injectable()
178
+ export class ApiUrlInterceptor implements SseInterceptor<unknown> {
179
+ sseIntercept<T = unknown>(request: SseRequest, next: SseNextFn<T>): Observable<T> {
180
+ const url = request.url.replace(/^@/, 'https://api.example.com');
181
+ return next({ ...request, url });
182
+ }
183
+ }
184
+
185
+ // Provide directly using the token
186
+ export const appConfig: ApplicationConfig = {
187
+ providers: [
188
+ provideSseClient(),
189
+ { provide: SSE_INTERCEPTORS, useClass: ApiUrlInterceptor, multi: true }
190
+ ]
191
+ };
192
+ ```
193
+
194
+ **Unified HTTP and SSE Interceptor:**
195
+
196
+ You can create a single interceptor class that handles both HTTP and SSE requests, allowing you to share authentication, URL rewriting, or other common logic:
197
+
198
+ ```typescript
199
+ import { Injectable } from '@angular/core';
200
+ import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HTTP_INTERCEPTORS } from '@angular/common/http';
201
+ import { SseInterceptor, SseRequest, SseNextFn, SSE_INTERCEPTORS } from '@telperion/ng-pack/sse-client';
202
+ import { localStorageSignal } from '@telperion/ng-pack/storage-signals';
203
+ import { Observable } from 'rxjs';
204
+
205
+ @Injectable()
206
+ export class BaseApiInterceptor implements HttpInterceptor, SseInterceptor<unknown> {
207
+
208
+ // Handle HTTP requests
209
+ intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
210
+ return next.handle(req.clone({ url: this.#replaceUrl(req.url) }));
211
+ }
212
+
213
+ // Handle SSE requests
214
+ sseIntercept<T = unknown>(request: SseRequest, next: SseNextFn<T>): Observable<T> {
215
+ return next({ ...request, url: this.replaceUrl(request.url)});
216
+ }
217
+
218
+ #replaceUrl(url: string): string {
219
+ return `https://my-api.domain.com/${url}`;
220
+ }
221
+ }
222
+
223
+ // Register for both HTTP and SSE
224
+ export const appConfig: ApplicationConfig = {
225
+ providers: [
226
+ // Provide the same interceptor for both HTTP and SSE
227
+ { provide: HTTP_INTERCEPTORS, useClass: BaseApiInterceptor, multi: true },
228
+ { provide: SSE_INTERCEPTORS, useClass: BaseApiInterceptor, multi: true },
229
+
230
+ provideHttpClient(withFetch(), withInterceptorsFromDi()),
231
+ provideSseClient(),
232
+ ]
233
+ };
234
+ ```
235
+
236
+ This pattern is especially useful when you want to:
237
+ - Share authentication logic between HTTP and SSE
238
+ - Apply consistent URL transformations
239
+ - Reuse common error handling
240
+ - Maintain a single source of truth for API configuration
241
+
242
+ **Note:** You can combine both approaches - use the `SSE_INTERCEPTORS` token for class-based interceptors and `withSseInterceptors()` for functional interceptors. Class-based interceptors provided via the token will execute before functional interceptors provided via `withSseInterceptors()`.
243
+
166
244
  ### Advanced Usage
167
245
 
168
246
  #### Real-time Notifications
@@ -402,6 +480,41 @@ interface SseInterceptor<T = unknown> {
402
480
  }
403
481
  ```
404
482
 
483
+ **Example:**
484
+ ```typescript
485
+ @Injectable()
486
+ class MyInterceptor implements SseInterceptor<unknown> {
487
+ sseIntercept<T>(request: SseRequest, next: SseNextFn<T>): Observable<T> {
488
+ console.log('Intercepting:', request.url);
489
+ return next(request);
490
+ }
491
+ }
492
+ ```
493
+
494
+ ---
495
+
496
+ ### `SSE_INTERCEPTORS`
497
+
498
+ Injection token for providing class-based SSE interceptors directly.
499
+
500
+ ```typescript
501
+ const SSE_INTERCEPTORS: InjectionToken<SseInterceptor<unknown>[]>
502
+ ```
503
+
504
+ **Usage:**
505
+ ```typescript
506
+ import { SSE_INTERCEPTORS } from '@telperion/ng-pack/sse-client';
507
+
508
+ export const appConfig: ApplicationConfig = {
509
+ providers: [
510
+ provideSseClient(),
511
+ { provide: SSE_INTERCEPTORS, useClass: MyInterceptor, multi: true }
512
+ ]
513
+ };
514
+ ```
515
+
516
+ **Note:** This token allows you to provide class-based interceptors that can leverage dependency injection. It's particularly useful for creating interceptors that implement both `HttpInterceptor` and `SseInterceptor` to share logic between HTTP and SSE requests.
517
+
405
518
  ## Best Practices
406
519
 
407
520
  ### 1. Always Unsubscribe
@@ -504,6 +617,37 @@ export const appConfig: ApplicationConfig = {
504
617
  };
505
618
  ```
506
619
 
620
+ ### 7. Share Logic with HTTP Interceptors
621
+
622
+ When you need the same logic for both HTTP and SSE (auth, URL rewriting, etc.), create a unified interceptor class:
623
+
624
+ ```typescript
625
+ @Injectable()
626
+ class UnifiedInterceptor implements HttpInterceptor, SseInterceptor<unknown> {
627
+ intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
628
+ // HTTP logic
629
+ }
630
+
631
+ sseIntercept<T>(request: SseRequest, next: SseNextFn<T>): Observable<T> {
632
+ // SSE logic (can reuse same helper methods)
633
+ }
634
+ }
635
+
636
+ // ✅ Good - shared interceptor for both
637
+ providers: [
638
+ { provide: HTTP_INTERCEPTORS, useClass: UnifiedInterceptor, multi: true },
639
+ { provide: SSE_INTERCEPTORS, useClass: UnifiedInterceptor, multi: true },
640
+ ]
641
+
642
+ // ❌ Bad - duplicated logic in separate interceptors
643
+ ```
644
+
645
+ This approach:
646
+ - Reduces code duplication
647
+ - Ensures consistent behavior across HTTP and SSE
648
+ - Makes configuration and API changes easier to manage
649
+ - Allows sharing of injected dependencies
650
+
507
651
  ## Common Use Cases
508
652
 
509
653
  ### Real-time Chat