npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

luftborn-rxjs-takeuntil-destroy

v1.0.7

Published

ESLint plugin that enforces the use of takeUntilDestroyed operator in RxJS subscription pipes to prevent memory leaks in Angular applications

Readme

luftborn-rxjs-takeuntil-destroy

An ESLint plugin that enforces the use of takeUntilDestroyed or other take operators in RxJS subscription pipes to prevent memory leaks in Angular applications.

Description

This ESLint rule helps prevent memory leaks in Angular applications by ensuring that all Observable subscriptions use either the takeUntilDestroyed operator from @angular/core/rxjs-interop or one of the RxJS take operators (takeUntil, takeWhile, take, takeLast). These operators ensure that subscriptions are properly terminated, preventing memory leaks.

Installation

npm install luftborn-rxjs-takeuntil-destroy --save-dev

Requirements

  • ESLint 6.0.0 or higher (compatible with ESLint 9+)
  • Node.js 14.0.0 or higher
  • Angular 16.0.0 or higher (for @angular/core/rxjs-interop)
  • RxJS 7.0.0 or higher

Usage

Add the plugin to your ESLint configuration:

ESLint Config (eslintrc.js / eslintrc.json)

{
  "plugins": ["luftborn-rxjs-takeuntil-destroy"],
  "rules": {
    "luftborn-rxjs-takeuntil-destroy/require-take-until-destroyed": "error"
  }
}

ESLint Flat Config (eslint.config.js)

const luftbornRxjsTakeuntilDestroy = require('luftborn-rxjs-takeuntil-destroy');

module.exports = [
  {
    plugins: {
      'luftborn-rxjs-takeuntil-destroy': luftbornRxjsTakeuntilDestroy
    },
    rules: {
      'luftborn-rxjs-takeuntil-destroy/require-take-until-destroyed': 'error'
    }
  }
];

Rule Details

The require-take-until-destroyed rule enforces that all Observable subscriptions use either the takeUntilDestroyed operator or one of the RxJS take operators (takeUntil, takeWhile, take, takeLast) to ensure subscriptions are properly terminated, preventing memory leaks.

This rule is auto-fixable. When you run ESLint with the --fix option, it will automatically add takeUntilDestroyed() to your subscription pipes where needed.

Examples

❌ Incorrect

// Missing takeUntilDestroyed operator
this.observable.subscribe(result => {
  console.log(result);
});

// Using pipe but missing takeUntilDestroyed
this.observable.pipe(
  map(data => data)
).subscribe(result => {
  console.log(result);
});

✅ Correct

import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

// Using takeUntilDestroyed in pipe
this.observable.pipe(
  map(data => data),
  takeUntilDestroyed()
).subscribe(result => {
  console.log(result);
});

// Using renamed import
import { takeUntilDestroyed as tud } from '@angular/core/rxjs-interop';

this.observable.pipe(
  map(data => data),
  tud()
).subscribe(result => {
  console.log(result);
});

// Using a variable with 'destroy' in the name
const destroyRef = inject(DestroyRef);
const untilDestroyed = takeUntilDestroyed(destroyRef);

this.observable.pipe(
  map(data => data),
  untilDestroyed
).subscribe(result => {
  console.log(result);
});

// Using takeUntil from RxJS
import { takeUntil } from 'rxjs';

destroy$ = new Subject<void>();

this.observable.pipe(
  map(data => data),
  takeUntil(this.destroy$)
).subscribe(result => {
  console.log(result);
});

// Using takeWhile from RxJS
import { takeWhile } from 'rxjs';

alive = true;

this.observable.pipe(
  map(data => data),
  takeWhile(() => this.alive)
).subscribe(result => {
  console.log(result);
});

// Using take from RxJS
import { take } from 'rxjs';

this.observable.pipe(
  map(data => data),
  take(1)
).subscribe(result => {
  console.log(result);
});

// Using takeLast from RxJS
import { takeLast } from 'rxjs';

this.observable.pipe(
  map(data => data),
  takeLast(1)
).subscribe(result => {
  console.log(result);
});

Rule Options

This rule has no options.

Auto-fix Behavior

When auto-fix is applied:

  1. For subscriptions without a pipe call, it adds a pipe with takeUntilDestroyed() before the subscribe call.
  2. For subscriptions with a pipe call but missing a take operator, it adds takeUntilDestroyed() as the last operator in the pipe.

Note: The auto-fix assumes that takeUntilDestroyed is imported from @angular/core/rxjs-interop. If it's not imported, you'll need to add the import manually.

Implementation Details

The rule checks for:

  1. Observable subscriptions without a pipe call
  2. Observable subscriptions with a pipe call but missing any of the supported take operators
  3. Proper import and usage of the takeUntilDestroyed operator from @angular/core/rxjs-interop
  4. Proper import and usage of RxJS take operators (takeUntil, takeWhile, take, takeLast) from 'rxjs'

The rule recognizes:

  • Renamed imports for all supported operators
  • Variables that might contain any of the supported operators
  • Various patterns for subscription cleanup

License

MIT © Luftborn

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository https://github.com/Arigatouz/luftborn-rxjs-takeuntil-destroy
  2. Create your feature branch (git switch -c 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