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

@momics/dns-sd-node

v0.1.0

Published

Node.js runtime adapter for @momics/dns-sd-shared: a UDP-multicast DatagramTransport (via node:dgram) driving the shared, standards-compliant mDNS / DNS-SD engine.

Readme

@momics/dns-sd-node

The Node.js runtime package for the @momics/dns-sd family. It supplies a UDP-multicast DatagramTransport (built on Node's node:dgram) to the runtime-agnostic @momics/dns-sd-shared mDNS engine and re-exports the identical public API. No native dependencies, no Rust — Node has everything needed for raw multicast built in.

  • Standards-compliant mDNS / DNS-SD (RFC 6762 + RFC 6763) via the shared engine (probing, conflict resolution, known-answer suppression, TTL cache, goodbyes — all of it).
  • Thin adapter: this package is just the socket layer; all protocol logic lives in the shared package and is proven by a common conformance suite.
  • Continuous by default: browse never times out unless you ask it to.

Install

npm i @momics/dns-sd-node

Node desktop / server only. This package needs raw UDP multicast sockets and therefore does not work in browsers, and is not intended for mobile (iOS/Android), where the OS owns the mDNS resolver — use a Tauri/native adapter there instead. Node 18+ is required (ships with the built-in test runner and modern dgram).

Usage

Browse

import { browse } from "@momics/dns-sd-node";

for await (
  const svc of browse({ service: { type: "http", protocol: "tcp" } })
) {
  // svc.kind is "found" | "resolved" | "updated" | "removed"
  console.log(svc.kind, svc.name, svc.addresses, svc.port);
}

Stop a browse by break-ing the loop, calling the generator's .return(), passing an AbortSignal, or setting timeoutMs:

const ac = new AbortController();
setTimeout(() => ac.abort(), 10_000);
for await (
  const svc of browse({
    service: { type: "ipp", protocol: "tcp" },
    signal: ac.signal,
  })
) {
  console.log(svc);
}

Advertise

import { advertise, close } from "@momics/dns-sd-node";

const handle = await advertise({
  service: {
    type: "http",
    protocol: "tcp",
    name: "My Web Server",
    port: 8080,
    txt: { path: "/", version: "1.0" },
  },
});

console.log("Advertising as", handle.fullName);

// Later — sends a goodbye so peers drop the service promptly:
await handle.stop();
await close();

Managing the transport yourself

The module-level browse / advertise / close wrap a lazily-created default transport. For finer control (a specific IP family, host name, interface set, or engine timing), build your own instance:

import { createNodeDnsSd, NodeTransport } from "@momics/dns-sd-node";

// Convenience factory:
const dnsSd = createNodeDnsSd({ family: "IPv4", hostname: "my-device" });

// Or wire the transport into the shared factory directly:
import { createDnsSd } from "@momics/dns-sd-node";
const custom = createDnsSd({ transport: new NodeTransport({ multicastTtl: 4 }) });

NodeTransport options:

| Option | Default | Description | | ------------------- | ------------------ | ------------------------------------------------------------------ | | family | "IPv4" | "IPv4" (224.0.0.251) or "IPv6" (ff02::fb). | | hostname | os.hostname() | Advertised host label; a .local suffix is ensured. | | port | 5353 | mDNS port to bind. | | multicastTtl | 255 | Outgoing multicast TTL (IPv4). | | multicastLoopback | true | Loop our multicast back to this host (needed for same-host peers). | | localAddresses | auto-detected | Our own addresses; [] disables the engine's address-based self-filter. | | interfaces | all non-internal | Restrict group membership to these interface addresses. |

Networking notes

mDNS uses UDP multicast on port 5353 (group 224.0.0.251 for IPv4, ff02::fb for IPv6). For discovery to work:

  • Firewall: allow inbound/outbound UDP on port 5353. On macOS the built-in firewall usually permits it; on Linux with firewalld/ufw you may need to open it (e.g. mdns service). Corporate/VPN firewalls frequently block multicast entirely.
  • Multicast-capable network: many cloud VMs, containers, and Wi-Fi guest networks disable multicast; discovery will silently find nothing there.
  • Multiple hosts: peers on different machines are distinguished by source address automatically, so cross-host discovery and advertising work out of the box with the default settings (real interface addresses are advertised in the A/AAAA records).
  • Same host, multiple instances: the shared engine ignores datagrams whose source is one of our own addresses, so by default a browse in one process won't discover an advertisement made by another process on the same machine (they share the host's IP). For local-only testing where that is desired, construct transports with localAddresses: []: this disables the address-based self-filter (the transport still suppresses each socket's own echoes) at the cost of advertising loopback addresses. This is exactly how the conformance suite runs many nodes on one host.

Testing

# Always-on transport unit tests (no network needed):
npm run test:node --workspace @momics/dns-sd-node

# Also run the shared conformance suite over REAL UDP multicast:
DNS_SD_NETWORK_TESTS=1 npm run test:node --workspace @momics/dns-sd-node

The conformance cases come straight from @momics/dns-sd-shared/testing and are run against real NodeTransport sockets, proving this runtime behaves identically to every other.

Examples

node packages/dns-sd-node/examples/browse.mjs           # browse _http._tcp
node packages/dns-sd-node/examples/advertise.mjs "Demo" 8080

License

Dual-licensed under MIT or Apache-2.0, at your option.