@fivexlabs/ng-terminus v2.0.0
@fivexlabs/ng-terminus
๐ก 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'sngOnDestroy - โ 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
npm install @fivexlabs/ng-terminus
# or
yarn add @fivexlabs/ng-terminusNote: 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:
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:
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:
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:
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:
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:
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:
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:
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 destructionuntilDestroyed()- Simplified alias with auto-injection
Route-based Operators
takeUntilRoute(route?)- Unsubscribe on route changetakeWhileOnRoute(pattern)- Active only on specific routes
HTTP Operators
cancelOnDestroy()- Cancel HTTP requests on destructioncancelPrevious()- Cancel previous requests when new ones startretryWithBackoff(retries, delay, maxDelay)- Exponential backoff retrylogHttpRequests(name?)- Log HTTP request lifecycle
Visibility Operators
takeWhileVisible()- Pause when page is hiddentakeUntilHidden()- Unsubscribe when page becomes hiddenbufferWhileHidden(size)- Buffer emissions while hiddenthrottleWhileHidden(ms)- Throttle when page is hidden
Forms Operators
takeUntilFormDestroyed()- Form-specific cleanuptakeWhileFormValid(validator)- Emit only when form is valid
Memory Operators
optimizeMemory(options)- Memory-optimized observablesshareWithAutoCleanup(delay)- Auto-cleanup sharinglimitEmissionRate(rate)- Rate limiting for memory efficiency
Services
SubscriptionManager- Centralized subscription managementHttpRequestManager- HTTP request lifecycle managementFormSubscriptionManager- Form-specific subscription managementSubscriptionDebuggerService- Advanced debugging capabilities
Testing Utilities
TestObservable<T>- Controllable test observableSubscriptionTester- Subscription testing frameworkMemoryLeakDetector- Memory leak detectionTestScenarios- Pre-built test scenarios
๐ง Configuration
Configure ng-terminus for your application:
import { NgTerminusModule } from '@fivexlabs/ng-terminus';
@NgModule({
imports: [
NgTerminusModule.forRoot({
enableDebugger: !environment.production,
enableMemoryOptimization: true,
debugMode: !environment.production
})
]
})
export class AppModule {}๐งช Testing
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 for a detailed history of all changes and new features.
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ข About Fivex Labs
Fivex Labs 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 - Dynamic, conditional forms for React with JSON schemas
- react-use-file-system - File System Access API hook for React with TypeScript support
Visit us at fivexlabs.com to learn more about our work and other open-source projects.