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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@se-ng/signal-utils

v21.0.2

Published

This library provides some utilities to make it easier to work with signals in Angular.

Readme

SignalUtils

This library provides some utilities to make it easier to work with signals in Angular.

Installation

To install this library, run:

pnpm install @se-ng/signal-utils --save

Utilities (exports)

This section lists the package exports with brief one-line type indications, examples, and source links.

Reactive / Signals helpers ✅

  • asyncComputed — async helper to populate a Signal from promises, observables, or async-iterables.

    Example:

    const userSignal = asyncComputed(async () => {
      const res = await fetch('/api/user');
      return await res.json();
    });
    // userSignal() === undefined initially, later contains the fetched object
  • computedResource — resource wrapper exposing { value: Signal, status, stream, error }.

    Example:

    const resource = computedResource(async () =>
      fetch('/items').then(r => r.json())
    );
    // access current value: resource().value(); resource().status
  • debouncedSignal / debouncedComputed — debounce helpers for signals.

    Example:

    const debounced = debouncedSignal(() => searchTerm(), { delay: 200 });
    // debounced.asReadonly() or debounced() to read
  • injectAwaitSignal / awaitSignal — wait for a signal to satisfy a predicate.

    • awaitSignal<T>(signalFn, predicate) => Promise<T>
    • injectAwaitSignal(injector?) => <T>(signalFn, predicate) => Promise<T>
    • Source: src/reactive/await-signal.ts

    Example:

    await awaitSignal(
      () => readyFlag(),
      v => v === true
    );
    // resolves when readyFlag() becomes true

Async & control helpers ✅

  • Deferred — a simple deferred promise container (useful for awaiting conditions).

    • class Deferred<T> { promise: Promise<T>; resolve: (v: T) => void; reject: (e: any) => void; }
    • Source: src/async/deferred.ts

    Example:

    const d = new Deferred<number>();
    setTimeout(() => d.resolve(42), 100);
    const answer = await d.promise; // 42

HTTP client ✅

  • HttpActionClient — small HttpClient wrapper exposing async methods and per-method busy Signals.

    Example:

    const data = await httpActionClient.get('/api/items');
    if (httpActionClient.isBusy()) {
      /* show spinner */
    }

Runtime type guards & helpers ✅

  • isAsyncIterableisAsyncIterable(x): x is AsyncIterable<any>

    Example:

    if (isAsyncIterable(x)) {
      for await (const v of x) {
        console.log(v);
      }
    }
  • isPromiseisPromise<T>(x): x is Promise<T>

    Example:

    async function handle(p: unknown) {
      if (isPromise(p)) {
        const value = await p;
        console.log(value);
      }
    }
  • isDateisDate(x): x is Date

    Example:

    if (isDate(val)) {
      console.log(val.toISOString());
    }
  • isObjectisObject<T>(x: T): boolean (object, not null/array/date)

    Example:

    if (isObject(obj)) {
      for (const key of Object.keys(obj)) {
        console.log(key, (obj as Record<string, unknown>)[key]);
      }
    }
  • isIntegerStringisIntegerString(str): boolean (digits-only integer check)

    Example:

    if (isIntegerString('01')) {
      const idx = parseInt('01', 10);
      // use idx to index into an array safely
    }

Deep & structural utilities ✅

  • cloneDeep — deep clone handling circular refs, Maps, Sets, Dates, RegExp.

    Example: const copy = cloneDeep(original); // no shared references

  • deepEqual — deep structural equality check for: objects, arrays, maps, sets, dates and typed arrays.

    Example: deepEqual({ a: 1 }, { a: 1 }) // true

  • mergeDeep — deep merge with configurable iterable strategies (concat|replace|merge).

    Example:

    mergeDeep({ items: [1] }, { items: [2] }, { iterableMergeStrategy: 'merge' });
    // -> { items: [2] } (source values at indices take precedence)
  • deepDiff — compute a minimal patch object with changed keys between two objects.

    Example: deepDiff({a:1,b:2}, {a:1,b:3}) // -> { b: 3 }


Path & flatten utilities ✅

  • objFromPath — builds an object or array from a dot/bracket path and a value.

    Example: objFromPath('a[0].b', 5) // -> { a: [ { b: 5 } ] }

  • flattenRecord / unFlattenRecord — flatten/unflatten nested objects/arrays to/from dot-path records.

    Example:

    flattenRecord({ user: { name: 'Alice' } }); // -> { 'user.name': 'Alice' }
    unFlattenRecord({ 'user.name': 'Alice' }); // -> { user: { name: 'Alice' } }

Notes & Edge Cases ⚠️

  • Guards:

    • isPromise detects thenables by checking for a .then method. Objects that merely implement then will be considered promises.
    • isAsyncIterable checks for Symbol.asyncIterator and will only return true for true async iterables.
    • isDate checks for a getMonth method; objects exposing a similarly named function may be misclassified in fringe cases.
  • flattenRecord / unFlattenRecord:

    • flattenRecord can mark or throw on circular references depending on the onCircular option.
    • unFlattenRecord uses integer-like path segments to build arrays; it will produce sparse arrays when indices are non-contiguous.
  • deepDiff:

    • The function produces a reconstructed patch containing only changed keys. For arrays it will reconstruct sparse changes (only changed indices are present) — be mindful when applying patches or merging results.
  • mergeDeep:

    • Array/iterable strategy options (concat, replace, merge) change behavior substantially:
      • merge performs index-wise merging (source indices take precedence)
      • concat appends
      • replace overwrites
    • Merging Set or Map with a non-matching type will throw unless replace is used.
  • cloneDeep / deepEqual:

    • cloneDeep preserves circular references and copies Dates, RegExp and TypedArrays appropriately. Functions and prototype chains are not deeply cloned.
    • deepEqual covers most builtin types (including Maps/Sets) but can be surprised by objects with custom valueOf/toString behavior.
  • Async helpers (asyncComputed, computedResource):

    • Both use an AbortController for cancellation when re-run and rely on a DestroyRef for cleanup. When used outside injection context you must provide a DestroyRef explicitly.
  • HttpActionClient:

    • Per-method busy counters are incremented before the request and decremented in finally. Consult busyMethods to reflect per-method busy state in the UI.
  • Deferred:

    • Handy for externally resolving a promise — remember to resolve or reject to avoid leaving pending promises and potential memory leaks.

License

This project is licensed under the MIT License - see the LICENSE file for details.