@telperion/ng-pack
v3.1.0
Published
Collection of Angular utilities and libraries organized as secondary entry points. Includes signal-based storage (localStorage/sessionStorage/cookieStorage), SSE client with HttpClient-inspired interceptors, event modifier plugins, and more. Built with Ty
Maintainers
Readme
@telperion/ng-pack
A collection of Angular utilities and libraries
Installation
npm install @telperion/ng-packAvailable Modules
Common
Import: @telperion/ng-pack/common
Common Angular pipes and directives for key-value data structures (Map, Set, plain objects), template iteration, and element observation.
Key Features
- 🔑
keyspipe — extract keys from any key-value structure - 📦
valuespipe — extract values from any key-value structure - 📋
entriespipe — extract entries as{ key, value }objects - 🔁
timespipe — generate[0, 1, ..., n-1]array for repeating template blocks - 📐
tngObserveSizedirective — observe element size viaResizeObserverwith signal-based API - �
*tngUnlessstructural directive — render a template when the expression is falsy (inverse of*ngIf) - �🗺️ Supports
Map,Set, and plain objects - 🎯 Full type inference with overloaded signatures
- 🛡️ Null-safe — returns
[]fornull/undefined
Quick Start
import { Component } from '@angular/core';
import { EntriesPipe } from '@telperion/ng-pack/common';
@Component({
selector: 'app-example',
standalone: true,
imports: [EntriesPipe],
template: `
@for (entry of user | entries; track entry.key) {
<div>{{ entry.key }}: {{ entry.value }}</div>
}
`
})
export class ExampleComponent {
user = { name: 'Alice', role: 'Admin' };
}Storage Signals
Import: @telperion/ng-pack/storage-signals
Angular signals-based wrapper for browser's localStorage, sessionStorage, and cookies with reactive updates.
Key Features
- 🚀 Signal-based API integrated with Angular's signal system
- 🔄 Reactive updates automatically synced across components
- 🎯 Nested property access using dot notation
- 🏪 Support for localStorage, sessionStorage, and cookies
- 🔑 Namespaced storage organization
- 🍪 Full cookie configuration (secure, sameSite, maxAge, etc.)
- 🔗 Cross-instance synchronization for cookie storage
Quick Start
import { ApplicationConfig } from '@angular/core';
import { provideLocalStorage } from '@telperion/ng-pack/storage-signals';
export const appConfig: ApplicationConfig = {
providers: [
provideLocalStorage('my-app'),
]
};import { Component } from '@angular/core';
import { localStorageSignal } from '@telperion/ng-pack/storage-signals';
@Component({
selector: 'app-settings',
template: `
<div>
<p>Theme: {{ theme() }}</p>
<button (click)="theme.set('dark')">Dark Mode</button>
</div>
`
})
export class SettingsComponent {
// Access nested properties with dot notation
theme = localStorageSignal<string>('settings', 'ui.theme');
}Cookie Storage:
import { ApplicationConfig } from '@angular/core';
import { provideCookieStorage } from '@telperion/ng-pack/storage-signals';
export const appConfig: ApplicationConfig = {
providers: [
provideCookieStorage('my-app', {
secure: true,
sameSite: 'strict',
maxAge: 86400 // 24 hours
}),
]
};import { Component } from '@angular/core';
import { cookieStorageSignal } from '@telperion/ng-pack/storage-signals';
@Component({
selector: 'app-auth',
template: `
<div>
@if (authToken()) {
<button (click)="authToken.delete()">Logout</button>
} @else {
<button (click)="authToken.set('token123')">Login</button>
}
</div>
`
})
export class AuthComponent {
// Cookie with custom expiry
authToken = cookieStorageSignal<string>('auth', 'token', {
maxAge: 3600 // 1 hour
});
}SSE Client
Import: @telperion/ng-pack/sse-client
Angular service for Server-Sent Events (SSE) with RxJS Observables and HttpClient-inspired interceptors.
Key Features
- 🚀 Observable-based API integrated with RxJS ecosystem
- 🔗 HttpClient-inspired interceptor chain for request manipulation
- 🎯 Type-safe with full generic support
- ⚡ EventSource wrapper with automatic cleanup
- 🔄 Real-time streaming data updates
- 🎨 Feature-based configuration
Quick Start
import { ApplicationConfig } from '@angular/core';
import { provideSseClient, withSseInterceptors, withBaseInit } from '@telperion/ng-pack/sse-client';
export const appConfig: ApplicationConfig = {
providers: [
provideSseClient(
withBaseInit({ withCredentials: true }),
withSseInterceptors(loggingInterceptor, authInterceptor)
),
]
};import { Component, inject } from '@angular/core';
import { SseClient } from '@telperion/ng-pack/sse-client';
import { AsyncPipe } from '@angular/common';
interface StockUpdate {
symbol: string;
price: number;
change: number;
}
@Component({
selector: 'app-stock-ticker',
template: `
<div>
<h2>Live Stock Prices</h2>
@if (stockUpdates$ | async; as update) {
<div class="stock-card">
<span>{{ update.symbol }}: \${{ update.price }}</span>
<span [class.positive]="update.change > 0">
{{ update.change > 0 ? '+' : '' }}{{ update.change }}%
</span>
</div>
}
</div>
`,
standalone: true,
imports: [AsyncPipe]
})
export class StockTickerComponent {
private sseClient = inject(SseClient);
// Start SSE connection and get Observable stream
stockUpdates$ = this.sseClient.start<StockUpdate>('/api/stocks/stream');
}Fetcher Signal
Import: @telperion/ng-pack/fetcher-signal
Reactive, signal-based HTTP fetcher for Angular built on top of HttpClient and Angular signals.
Key Features
- 🚦 Signal-first API — the result is a
Signal<T>you read directly in templates - 🔁 Reactive options — pass signals, observables, or promises and the request re-runs automatically
- 🛣️ Declarative
:namepath parameters and query parameters (RecordorHttpParams) - ⚠️ Built-in
errorandloadingsignals - 🧯
fallbackvalue used as initial state and on error - 🔄 Manual
reload()to re-run the current request — returns aPromise<void>that resolves with the next response - ⏳
loadedpromise —awaitthe next response without subscribing to signals
Quick Start
import { Component, computed, signal } from '@angular/core';
import { fetcherSignal } from '@telperion/ng-pack/fetcher-signal';
interface User { id: number; name: string; }
@Component({
selector: 'app-users',
standalone: true,
template: `
<input [value]="search()" (input)="search.set($any($event.target).value)" />
@if (users.loading()) {
<p>Loading…</p>
} @else {
<ul>
@for (user of users(); track user.id) {
<li>{{ user.name }}</li>
}
</ul>
}
`
})
export class UsersComponent {
search = signal('');
users = fetcherSignal<User[]>({
url: '/api/users',
queryParams: computed(() => ({ q: this.search() })),
fallback: []
});
}Template Signal Forms
Import: @telperion/ng-pack/template-signal-forms
🚧 Under Construction
Signal-based forms utilities for Angular template-driven forms.
Utils
Import: @telperion/ng-pack/utils
Angular utility functions and plugins for enhanced development experience.
Key Features
- 🎯 Event modifier syntax for templates (
.pd,.sp) - 🔗 Directive-as-service provider utility
- 🌐 Promise-based HTTP client with tuple error handling
- � Unified
toSignal— convert values, Promises, or Observables to Signals - �📦 Tree-shakeable and type-safe
- ⚡ Zero dependencies
Quick Start
Event Modifiers Plugin
import { provideEventModifiersPlugin } from '@telperion/ng-pack/utils';
bootstrapApplication(AppComponent, {
providers: [provideEventModifiersPlugin()]
});<!-- Prevent default and stop propagation with modifiers -->
<form (submit.pd)="onSubmit()">...</form>
<div (click.sp)="handleClick()">...</div>
<button (click.pd.sp)="handleButtonClick()">Click me</button>Construct Fetcher
import { Component } from '@angular/core';
import { constructFetcher } from '@telperion/ng-pack/utils';
@Component({
selector: 'app-example',
template: `<button (click)="fetchData()">Fetch Data</button>`
})
export class ExampleComponent {
private fetcher = constructFetcher();
async fetchData() {
const [error, response] = await this.fetcher.get('/api/data');
if (error) {
console.error('Error:', error);
return;
}
console.log('Data:', response);
}
}Provide Service Directive
import { provideServiceDirective } from '@telperion/ng-pack/utils';
// Create an injection token
export const ParentService = new InjectionToken<ParentDirective>("ParentService");
// Provide directive as service
@Directive({
selector: '[parent]',
providers: [provideServiceDirective(ParentService, ParentDirective)],
})
export class ParentDirective { }
// Inject in child
@Directive({ selector: '[child]' })
export class ChildDirective {
private parent = inject(ParentService);
}Development
Running Unit Tests
Run pnpm nx test ng-pack to execute the unit tests.
Building
Run pnpm nx build ng-pack to build the library.
License
This library is part of the Telperion monorepo.
