@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 +5 -1
- package/package.json +24 -1
- package/sse-client/README.md +145 -1
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @telperion/ng-pack
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@telperion/ng-pack)
|
|
4
|
+
[](https://www.npmjs.com/package/@telperion/ng-pack)
|
|
5
|
+
[](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 →](
|
|
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.
|
|
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",
|
package/sse-client/README.md
CHANGED
|
@@ -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** -
|
|
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
|