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

sds-signals

v2.1.0

Published

[# SDS Signal -- Reactive Action/Selector Framework for Angular

Downloads

2

Readme

[# SDS Signal -- Reactive Action/Selector Framework for Angular

A lightweight signal-based state & event system for Angular.
Works seamlessly in both Standalone and NgModule-based applications.
No boilerplate. No global store. Just @Action() + @Selector() + @Message() + @Error().


Features

  • Works with Standalone Components and Modules
  • Simple @Action() / @Selector() / @Message() / @Error() decorators
  • Built on Angular's Signal API
  • Global and Feature-level scopes
  • Automatic cleanup (no memory leaks)
  • No 3rd-party dependencies

Installation

Install via npm:

npm install sds-signal

Or if using a local library:

npm install file:../dist/sds-signal

Setup

Standalone Applications

import { bootstrapApplication } from '@angular/platform-browser';
import { provideSdsSignal } from 'sds-signal';
import { AppComponent } from './app/app.component';
import { JobActions } from './app/actions/job.actions';

bootstrapApplication(AppComponent, {
  providers: [
    provideSdsSignal([JobActions]), // register global actions
  ],
});

Module-based Applications

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { SdsSignalModule } from 'sds-signal';
import { AppComponent } from './app.component';
import { JobActions } from './actions/job.actions';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    SdsSignalModule.forRoot([JobActions]), // global registration
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

Defining Actions

import { Injectable } from '@angular/core';
import { Action, SdsSignalService } from 'sds-signal';
import { JobSelector, LegService } from '@sdsSignals';
import { catchError, of, tap } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class JobActions {
  constructor(private sdsSignal: SdsSignalService, private defaultService: LegService) {}

  @Action(JobSelector.List)
  updateJob({ id }: JobSelector.List) {
    return this.defaultService.fetch(id).pipe(
      tap((result: any) => {
        if (result.status === 1) {
          return result;
        } else {
          throw new Error(result.error);
        }
      }),
      catchError((error) => {
        this.sdsSignal.onError(JobSelector.List, error?.error?.message);
        return of('');
      })
    );
  }
}

Defining Action Classes / Namespaces

import { ServicesResponseInterface } from '@sdsSignals';

export namespace JobSelector {
  export class Insert {
    static readonly type = '[Job] Insert';
    constructor(public payload: ServicesResponseInterface) {}
  }

  export class List {
    static readonly type = '[Job] List';
    constructor(public id: string) {}
  }

  export class Delete {
    static readonly type = '[Job] Delete';
    constructor(public payload: ServicesResponseInterface) {}
  }

  export class Error {
    static readonly type = '[Job] Error';
  }
}

Using Selectors

import { Component, OnInit } from '@angular/core';
import { Selector, Message, SdsSignalService } from 'sds-signal';
import { JobSelector } from '@sdsSignals';

@Component({
  selector: 'app-job-list',
  standalone: true,
  template: `
    <h3>Jobs</h3>
    <button (click)="reload()">Reload</button>
    <ul>
      <li *ngFor="let job of jobs">{{ job.name }}</li>
    </ul>
  `,
})
export class JobListComponent implements OnInit {
  jobs: any[] = [];

  constructor(private sdsSignal: SdsSignalService) {}

  ngOnInit() {
    this.sdsSignal.dispatch(new JobSelector.List({ id: '123' }));
  }
  
  @Dispatch(JobSelector.List)
    dispatch() {
        this.loader = true;
        this.selection.clear();
        return {
            params: this.pageParams.paramString,
            filters: this.activeFilters
        }
    }

  @Selector(JobSelector.List)
  onJobsList(data: any) {
    console.log('Jobs List:', data);
  }

  @Message(JobSelector)
  meg(msg: { messageType: 'success' | 'error'; message: string }) {
    console.log('Message received:', msg);
  }

  @Message([JobSelector.List, JobSelector.Insert])
  specificMsg(msg: { messageType: 'success' | 'error'; message: string }) {
    console.log('Specific messages:', msg);
  }

  @Error(JobSelector)
  errorMessage(error: any) {
    console.log('Error:', error);
  }

  @Error([JobSelector.List, JobSelector.Insert])
  errorMessage2(error: any) {
    console.log('Error:', error);
  }
}

Dispatching & Notifications


Method Description


dispatch(new className(), ...args) Run an action and notify all selectors

notify(className, value) Push data directly without running an action

onError(className, message) Send error message

onSuccess(className, message) Send success message

Example:

const sds = inject(SdsSignalService);

// Run async action
await sds.dispatch(new JobSelector.Insert({ payload: {} }));

// Push a value directly
sds.notify(JobSelector.List, [{ name: 'Job1' }]);

// Trigger messages manually
sds.onSuccess(JobSelector.List, 'Jobs loaded successfully');
sds.onError(JobSelector.Delete, 'Failed to delete job');

Feature Modules / Lazy Routes

Lazy Modules

@NgModule({
  imports: [SdsSignalModule.forFeature([FeatureActions])],
})
export class FeatureModule {}

Standalone Lazy Routes

{
  path: 'feature',
  loadComponent: () =>
    import('./feature.component').then((c) => c.FeatureComponent),
  providers: [
    provideSdsFeature([FeatureActions]),
  ],
}

Lifecycle Handling

  • Selectors are auto-registered on ngOnInit
  • Selectors auto-unregister on ngOnDestroy
  • No manual subscription cleanup required

Decorator & Method Reference Table

| Feature | Decorator / Method | Applies To | Description | Example Usage | |--------|---------------------|------------|-------------|----------------| | Action | @Action(ActionClass) | Action Service (Injectable) | Defines a reactive command. Executes your async logic (HTTP, business logic, etc.). | @Action(JobSelector.List) | | Selector | @Selector(ActionClass \| ActionClasses[]) | Component | Listens to data updates pushed by an Action or manual notify. Auto-unsubscribes. | @Selector(JobSelector.List) | | Message | @Message(Namespace \| ActionClass \| ActionClasses[]) | Component | Listens to success messages triggered via onSuccess(). | @Message(JobSelector) | | Error | @Error(Namespace \| ActionClass \| ActionClasses[]) | Component | Listens to errors triggered via onError(). Supports wildcard error handler. | @Error(JobSelector) | | Dispatch | @Dispatch(ActionClass) | Component | Auto-creates & dispatches an action from method’s returned object. Constructor-aware. | @Dispatch(JobSelector.List) | | Manual Dispatch | sds.dispatch(new ActionClass(...)) | Anywhere | Runs an Action manually without the decorator. | sds.dispatch(new JobSelector.List(params)) | | Notify | sds.notify(ActionClass, value) | Anywhere | Pushes data directly to selectors without executing an Action. | sds.notify(JobSelector.List, data) | | Success Message | sds.onSuccess(ActionClass, msg) | Anywhere | Triggers a success message received by @Message. | sds.onSuccess(JobSelector.Insert, 'Inserted!') | | Error Message | sds.onError(ActionClass, msg) | Anywhere | Triggers an error message received by @Error. | sds.onError(JobSelector.List, 'Load failed') | | Global Setup | provideSdsSignal([Actions]) | Root | Registers actions globally. | provideSdsSignal([JobActions]) | | Feature Setup | provideSdsFeature([Actions]) | Lazy/Feature Routes | Registers feature-scoped actions. | provideSdsFeature([FeatureActions]) |

Quick Reference


Concept Decorator / Function Purpose


Action @Action('key') Defines a reactive command

Selector @Selector('key') Listens to signal updates

Message @Message(namespace \| actions[]) Listens to success messages

Error @Error(namespace \| actions[]) Listens to error messages

Dispatch @Dispatch() Simplified action caller

Dispatch sds.dispatch(new className(), value?) Runs an action

Notify sds.notify('key', value) Manually trigger selectors

onSuccess sds.onSuccess(className, message) Trigger success message

onError sds.onError(className, message) Trigger error message

Global provideSdsSignal() / forRoot() Root setup Setup

Feature provideSdsFeature() / forFeature() Feature or lazy Setup scope


Project Structure Example

src/
├── actions/
│   └── job.actions.ts
├── components/
│   └── job-list.component.ts
├── app.component.ts
└── main.ts

Action → Selector → Message Flow Diagram

+-------------+       dispatch       +-------------+       notify/message       +-------------+
|  @Action()  | ------------------>  | SdsSignal   | --------------------------> | @Selector() |
|   (method)  |                      | Service     |                             | / @Message()|
+-------------+                      +-------------+                             | / @Error()  |
                                                                                +-------------+

License

MIT © 2025 --- SDS Signal Authors ]()