Package Exports
- @fivexlabs/ng-terminus
- @fivexlabs/ng-terminus/package.json
Readme
@fivexlabs/ng-terminus

Angular Subscription Management Library
Comprehensive utilities for managing RxJS subscriptions and preventing memory leaks in Angular applications
Made with โค๏ธ by Fivex Labs
๐ก 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-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:
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.
Made with โค๏ธ by Fivex Labs
ยฉ 2025 Fivex Labs. All rights reserved.