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

@monstermann/signals-transform

v0.11.0

Published

Disposes the effects of @monstermann/signals during HMR and writes useSignal for React.

Readme

Disposes the effects of @monstermann/signals during HMR and writes useSignal for React.

  • During development, effects, watchers and emitters are disposed when the module that created them is replaced (HMR).
  • With react, reads of signals in components are wrapped with useSignal, see React.

A production build without react is left untouched.

Installation

bun add -D @monstermann/signals-transform

Usage

Vite, Rolldown, tsdown

import { signals } from "@monstermann/signals-transform";

export default defineConfig({
    plugins: [signals()],
});

| Option | Default | Description | | --------- | -------------- | --------------------------------------------------------------------------------- | | hmr | false | true in the dev server of Vite. Relies on import.meta.hot. | | react | false | Wraps reads of signals in React components with useSignal, see React. | | include | /\.[jt]sx?$/ | RegExp(s), only files whose path matches are transformed. | | exclude | | RegExp(s), files whose path matches are skipped. | | enforce | | "pre" or "post". |

Bun

Bun.build only uses the first onLoad that returns something, so call transform from your own:

import { transform } from "@monstermann/signals-transform";

await Bun.build({
    entrypoints: ["./src/index.ts"],
    plugins: [
        {
            name: "transforms",
            setup(build) {
                build.onLoad(
                    { filter: /\.tsx?$/ },
                    async ({ loader, path }) => {
                        const code = await Bun.file(path).text();
                        return {
                            contents: transform(code, path)?.code ?? code,
                            loader,
                        };
                    },
                );
            },
        },
    ],
});

React

With react: true, reads of signals inside of components and hooks are wrapped with useSignal from @monstermann/signals-react:

signals({ react: true });

Before:

export function Component({ className }) {
    const style = $style();
    return (
        <div style={style} className={$class() + className}>
            {$content()}
        </div>
    );
}

After:

import { useSignal } from "@monstermann/signals-react";
export function Component({ className }) {
    const style = useSignal($style);
    return (
        <div style={style} className={useSignal(() => $class() + className)}>
            {useSignal($content)}
        </div>
    );
}
  • Signals are recognized by their name, which has to start with a $: $count(), state.$count().
  • A call with arguments counts as a read too, which is what functions that read signals look like: $t("key") becomes useSignal(() => $t("key")). Writes belong in callbacks and effects, where nothing is wrapped.
  • Requires the React Compiler. Expressions such as $class() + className become useSignal(() => …), and without the compiler memoizing that function, it is a new one on every render and gets subscribed to again each time.
  • Only functions that look like components or hooks are transformed: a name starting with an uppercase letter or use, or a body containing JSX.
  • A read becomes a hook call in the place where it is written, so the rules of hooks apply: no reads inside conditions, loops, callbacks or after an early return.
  • A read inside the arguments of another hook (useThing($count())) wraps the argument, not the hook.
  • Reads that are already inside useSignal(…) are left alone.
  • Files without a $ are skipped by this step without being parsed.

HMR

When a module is replaced during development, the effects, watchers and emitters its previous version created would keep running. With hmr, they are disposed right before the module runs again, and when it is removed.

import { effect } from "@monstermann/signals";

effect(() => {});
import { effect } from "@monstermann/signals";
const hmr = import.meta.hot
    ? (import.meta.hot.data["@monstermann/meta"] ??= new globalThis.Set())
    : undefined;
// …calls and clears `hmr` when the module is replaced or removed
const meta = { hmr: hmr };

effect(() => {}, meta);
  • Enabled by default in the dev server of Vite, and off for builds.
  • It relies on import.meta.hot.
  • Calls are found through their import, renamed imports (import { effect as e }) and namespace imports (import * as S) included.
  • Files that do not mention @monstermann/signals are skipped without being parsed.
  • Built on @monstermann/meta.