UNPKG

@fivexlabs/ng-terminus

Version:

A comprehensive Angular library for managing RxJS subscriptions and preventing memory leaks with advanced features

481 lines (372 loc) โ€ข 15.6 kB
# @fivexlabs/ng-terminus <div align="center"> <img src="https://fivexlabs.com/assets/icon/logos/icon-logo-square.jpeg" alt="Fivex Labs" width="80" height="80" /> <h3>Angular Subscription Management Library</h3> <p>Comprehensive utilities for managing RxJS subscriptions and preventing memory leaks in Angular applications</p> <p>Made with โค๏ธ by <a href="https://fivexlabs.com">Fivex Labs</a></p> [![npm version](https://badge.fury.io/js/@fivexlabs%2Fng-terminus.svg)](https://www.npmjs.com/package/@fivexlabs/ng-terminus) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) </div> ## ๐Ÿ’ก Why ng-terminus? ### ๐Ÿšจ **The Problem** Angular applications commonly suffer from **memory leaks** caused by unmanaged RxJS subscriptions. These issues lead to: - ๐Ÿ“ˆ **Gradual Performance Degradation**: Memory usage increases over time as subscriptions accumulate - ๐Ÿ› **Difficult-to-Debug Issues**: Memory leaks cause seemingly random performance problems - ๐Ÿ”„ **Repetitive Boilerplate**: Manual `unsubscribe()` calls in every component's `ngOnDestroy` - โŒ **Human Error**: Easy to forget unsubscription, especially in complex components - ๐Ÿง  **Cognitive Load**: Developers must remember subscription management instead of focusing on business logic ### โœ… **The Solution** **ng-terminus** eliminates these issues by providing: - **๐ŸŽฏ Zero Memory Leaks**: Automatic subscription cleanup tied to Angular's lifecycle - **๐Ÿ“ Declarative API**: Clean, RxJS-native operators that integrate seamlessly - **๐Ÿš€ Developer Experience**: Write less code, focus on features, not cleanup - **๐Ÿ›ก๏ธ Type Safety**: Full TypeScript support prevents runtime errors - **โšก Performance**: Optimized cleanup strategies with minimal overhead ## โœจ Features ### ๐ŸŽฏ **Core Features** - **๐Ÿ”š takeUntilDestroyed Operator**: RxJS operator that automatically completes observables when components are destroyed - **๐Ÿ“ฆ SubscriptionManager Service**: Injectable service for managing multiple subscriptions with automatic cleanup - **๐Ÿ›ก๏ธ Type Safety**: Full TypeScript support with comprehensive type definitions - **๐Ÿš€ Modern Angular**: Built for Angular 14+ using the latest DestroyRef patterns - **โšก Zero Dependencies**: Only peer dependencies on Angular and RxJS - **๐ŸŒณ Tree Shakable**: Optimized for minimal bundle size impact ### ๐Ÿ”ฅ **Enhanced Features** - **๐Ÿ›ฃ๏ธ Route-based Management**: Automatically manage subscriptions based on route navigation - **๐ŸŒ HTTP Request Control**: Advanced HTTP request cancellation and retry mechanisms - **๐Ÿ‘๏ธ Visibility-based Subscriptions**: Pause/resume subscriptions based on page visibility - **๐Ÿ“ Reactive Forms Integration**: Seamless integration with Angular reactive forms - **๐Ÿง  Memory Optimization**: Advanced memory management and leak detection - **๐Ÿ” Enhanced Debugging**: Comprehensive debugging tools with performance metrics - **๐Ÿงช Testing Utilities**: Complete testing framework for subscription management ### ๐Ÿ”ง **Advanced Features** - **๐Ÿ” Debugging Tools**: Built-in utilities for tracking subscription lifecycle in development - **๐Ÿ› ๏ธ Utility Functions**: Helper functions for safe unsubscription and batch management - **๐Ÿ“Š Subscription Tracking**: Monitor active subscriptions and get insights - **๐Ÿ”„ Method Chaining**: Fluent API for managing multiple subscriptions - **โš™๏ธ Flexible Configuration**: Support for both automatic and explicit lifecycle management ## ๐Ÿ“ฆ Installation ```bash npm install @fivexlabs/ng-terminus # or yarn add @fivexlabs/ng-terminus ``` > **Note**: This library requires Angular 14+ and RxJS 7+. For enhanced features, you may also need @angular/router, @angular/forms, and @angular/common. ## ๐Ÿš€ Quick Start ### The takeUntilDestroyed Way (Recommended) Transform your subscription management with a single operator: ```typescript import { Component } from '@angular/core'; import { takeUntilDestroyed } from '@fivexlabs/ng-terminus'; import { DataService } from './data.service'; @Component({ selector: 'app-user-dashboard', template: `<div>Welcome {{ user?.name }}!</div>` }) export class UserDashboardComponent { user: User | null = null; constructor(private dataService: DataService) { // โœจ This subscription automatically cleans itself up! this.dataService.getCurrentUser() .pipe(takeUntilDestroyed()) .subscribe(user => this.user = user); // โœจ Multiple streams? No problem! this.dataService.getNotifications() .pipe( debounceTime(1000), takeUntilDestroyed() // Always last in the pipe ) .subscribe(notifications => this.handleNotifications(notifications)); } } ``` ## ๐Ÿ”ฅ Enhanced Features ### ๐Ÿ›ฃ๏ธ Route-based Subscription Management Automatically manage subscriptions based on route navigation: ```typescript import { takeUntilRoute, takeWhileOnRoute } from '@fivexlabs/ng-terminus'; @Component({...}) export class DashboardComponent { constructor(private dataService: DataService) { // Unsubscribe when navigating away from any route this.dataService.getLiveData() .pipe(takeUntilRoute()) .subscribe(data => this.updateDashboard(data)); // Only active while on dashboard routes this.dataService.getDashboardMetrics() .pipe(takeWhileOnRoute('/dashboard/**')) .subscribe(metrics => this.updateMetrics(metrics)); } } ``` ### ๐ŸŒ HTTP Request Management Advanced HTTP request cancellation and retry mechanisms: ```typescript import { HttpRequestManager, cancelOnDestroy, retryWithBackoff, logHttpRequests } from '@fivexlabs/ng-terminus'; @Component({ providers: [HttpRequestManager] }) export class ApiComponent { constructor( private http: HttpClient, private httpManager: HttpRequestManager ) { // Cancellable requests const { request$, cancel } = this.httpManager.createCancellableRequest( () => this.http.get('/api/data'), 'user-data' ); request$ .pipe( logHttpRequests('User Data'), retryWithBackoff(3, 1000), cancelOnDestroy() ) .subscribe(data => this.handleData(data)); // Cancel after 5 seconds if needed setTimeout(() => cancel(), 5000); } } ``` ### ๐Ÿ‘๏ธ Visibility-based Subscriptions Pause/resume subscriptions based on page visibility: ```typescript import { takeWhileVisible, bufferWhileHidden, throttleWhileHidden } from '@fivexlabs/ng-terminus'; @Component({...}) export class LiveDataComponent { constructor(private dataService: DataService) { // Pause when page is hidden this.dataService.getLiveUpdates() .pipe(takeWhileVisible()) .subscribe(update => this.processUpdate(update)); // Buffer notifications while hidden this.dataService.getNotifications() .pipe(bufferWhileHidden(10)) .subscribe(notifications => this.showNotifications(notifications)); // Throttle heartbeat when hidden this.dataService.getHeartbeat() .pipe(throttleWhileHidden(30000)) .subscribe(heartbeat => this.updateStatus(heartbeat)); } } ``` ### ๐Ÿ“ Reactive Forms Integration Seamless integration with Angular reactive forms: ```typescript import { takeUntilFormDestroyed, takeWhileFormValid, FormSubscriptionManager } from '@fivexlabs/ng-terminus'; @Component({ providers: [FormSubscriptionManager] }) export class FormComponent { form = this.fb.group({ name: ['', Validators.required], email: ['', [Validators.required, Validators.email]] }); constructor( private fb: FormBuilder, private formManager: FormSubscriptionManager ) { // Auto-cleanup form subscriptions this.form.valueChanges .pipe(takeUntilFormDestroyed()) .subscribe(value => this.handleFormChange(value)); // Only emit when form is valid this.form.valueChanges .pipe(takeWhileFormValid(() => this.form.valid)) .subscribe(value => this.saveValidForm(value)); // Managed form subscriptions this.formManager.manage( this.form.get('email')!.valueChanges, 'email-validation' ).subscribe(email => this.validateEmail(email)); } } ``` ### ๐Ÿง  Memory Optimization Advanced memory management and leak detection: ```typescript import { MemoryOptimizer, optimizeMemory, shareWithAutoCleanup, MemoryUtils } from '@fivexlabs/ng-terminus'; @Component({...}) export class OptimizedComponent { constructor(private dataService: DataService) { // Enable memory optimization MemoryOptimizer.getInstance().enable(); // Optimized observable with sharing const optimizedData$ = this.dataService.getData() .pipe(optimizeMemory({ share: true, name: 'user-data' })); // Auto-cleanup sharing const sharedStream$ = this.dataService.getLiveStream() .pipe(shareWithAutoCleanup(5000)); // Monitor memory usage MemoryUtils.logMemoryStats(); } } ``` ### ๐Ÿ” Enhanced Debugging Comprehensive debugging tools with performance metrics: ```typescript import { SubscriptionDebuggerService } from '@fivexlabs/ng-terminus'; @Component({...}) export class DebugComponent { constructor(private debugger: SubscriptionDebuggerService) { // Enable debugging this.debugger.enable(); // Create debuggable subscription const debugObs = this.debugger.debugSubscription( this.dataService.getData(), { name: 'UserData', componentName: 'DebugComponent', logEmissions: true, captureStackTrace: true } ); debugObs.subscribe(data => this.handleData(data)); // Monitor performance setTimeout(() => { this.debugger.logStatus(); const metrics = this.debugger.getPerformanceMetrics(); console.log('Performance:', metrics); }, 5000); } } ``` ### ๐Ÿงช Testing Utilities Complete testing framework for subscription management: ```typescript import { TestObservable, SubscriptionTester, MemoryLeakDetector, TestScenarios } from '@fivexlabs/ng-terminus'; describe('SubscriptionComponent', () => { let tester: SubscriptionTester; let leakDetector: MemoryLeakDetector; beforeEach(() => { tester = new SubscriptionTester(); leakDetector = new MemoryLeakDetector(); leakDetector.startMonitoring(); }); it('should manage subscriptions correctly', async () => { const testObs = new TestObservable<string>(); tester.subscribe(testObs, 'test-stream'); testObs.emit('test-value'); await tester.waitForEmissions('test-stream', 1); expect(tester.getEmissionCount('test-stream')).toBe(1); testObs.complete(); await tester.waitForCompletion('test-stream'); const leakCheck = leakDetector.checkForLeaks(); expect(leakCheck.hasLeaks).toBeFalsy(); }); }); ``` ## ๐Ÿ“š Complete API Reference ### Core Operators - `takeUntilDestroyed()` - Automatic cleanup on component destruction - `untilDestroyed()` - Simplified alias with auto-injection ### Route-based Operators - `takeUntilRoute(route?)` - Unsubscribe on route change - `takeWhileOnRoute(pattern)` - Active only on specific routes ### HTTP Operators - `cancelOnDestroy()` - Cancel HTTP requests on destruction - `cancelPrevious()` - Cancel previous requests when new ones start - `retryWithBackoff(retries, delay, maxDelay)` - Exponential backoff retry - `logHttpRequests(name?)` - Log HTTP request lifecycle ### Visibility Operators - `takeWhileVisible()` - Pause when page is hidden - `takeUntilHidden()` - Unsubscribe when page becomes hidden - `bufferWhileHidden(size)` - Buffer emissions while hidden - `throttleWhileHidden(ms)` - Throttle when page is hidden ### Forms Operators - `takeUntilFormDestroyed()` - Form-specific cleanup - `takeWhileFormValid(validator)` - Emit only when form is valid ### Memory Operators - `optimizeMemory(options)` - Memory-optimized observables - `shareWithAutoCleanup(delay)` - Auto-cleanup sharing - `limitEmissionRate(rate)` - Rate limiting for memory efficiency ### Services - `SubscriptionManager` - Centralized subscription management - `HttpRequestManager` - HTTP request lifecycle management - `FormSubscriptionManager` - Form-specific subscription management - `SubscriptionDebuggerService` - Advanced debugging capabilities ### Testing Utilities - `TestObservable<T>` - Controllable test observable - `SubscriptionTester` - Subscription testing framework - `MemoryLeakDetector` - Memory leak detection - `TestScenarios` - Pre-built test scenarios ## ๐Ÿ”ง Configuration Configure ng-terminus for your application: ```typescript import { NgTerminusModule } from '@fivexlabs/ng-terminus'; @NgModule({ imports: [ NgTerminusModule.forRoot({ enableDebugger: !environment.production, enableMemoryOptimization: true, debugMode: !environment.production }) ] }) export class AppModule {} ``` ## ๐Ÿงช Testing ```bash npm test ``` ## ๐Ÿ“– API Reference ### Core Operators | Function | Parameters | Returns | Description | |----------|------------|---------|-------------| | `takeUntilDestroyed<T>` | `destroyRef?: DestroyRef` | `OperatorFunction<T, T>` | Automatically completes observable on component destroy | | `untilDestroyed<T>` | None | `OperatorFunction<T, T>` | Alias for `takeUntilDestroyed()` with auto-injection | ### Services | Service | Key Methods | Description | |---------|-------------|-------------| | `SubscriptionManager` | `add()`, `remove()`, `activeCount` | Manages multiple subscriptions with automatic cleanup | ### Utility Functions | Function | Parameters | Returns | Description | |----------|------------|---------|-------------| | `safeUnsubscribe` | `Subscription \| null \| undefined` | `boolean` | Safely unsubscribe without errors | | `createManagedObservable<T>` | `Observable<T>, DestroyRef?` | `Observable<T>` | Create auto-managed observable | | `manageManyObservables<T>` | `T[], DestroyRef?` | `T[]` | Batch manage multiple observables | ## ๐Ÿ“‹ Changelog See [CHANGELOG.md](CHANGELOG.md) for a detailed history of all changes and new features. ## ๐Ÿค Contributing We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## ๐Ÿ“„ License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## ๐Ÿข About Fivex Labs [Fivex Labs](https://fivexlabs.com) is a technology company focused on building innovative tools and libraries for modern web development. We believe in creating solutions that are both powerful and developer-friendly. ### Other Libraries by Fivex Labs - [**conform-react**](https://github.com/fivex-labs/conform-react) - Dynamic, conditional forms for React with JSON schemas - [**react-use-file-system**](https://github.com/fivex-labs/react-use-file-system) - File System Access API hook for React with TypeScript support Visit us at [fivexlabs.com](https://fivexlabs.com) to learn more about our work and other open-source projects. --- <div align="center"> <p>Made with โค๏ธ by <a href="https://fivexlabs.com">Fivex Labs</a></p> <p>ยฉ 2025 Fivex Labs. All rights reserved.</p> </div>