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 🙏

© 2024 – Pkg Stats / Ryan Hefner

socket-activation

v3.2.0

Published

Native socket activation for launchd, systemd et al.

Downloads

51

Readme

node-socket-activation

npm

node-socket-activation is a socket activation library for Node.js.

Supported systems

| Service management framework | OS | Supported? | |---------------------------------|-------------------------|---------------------| | launchd | macOS 10.9 or later | :thumbsup: :bowtie: | | systemd | Compatible Linux distro | :thumbsup: :bowtie: |

Installation

Using yarn:

yarn add socket-activation

Using npm:

npm install --save socket-activation

Usage

How your app should look like

app.js

const net = require('net')

const sockets = require('socket-activation')

// There may be more than one fd, e.g. if you select the "IPv4v6"
// SockFamily which listens to both IPv4 and IPv6. Up to you to
// decide if you want to error out or setup multiple servers as
// follows.
for (const fd of sockets.collect('app')) {
  const server = net.createServer(conn => {
    conn.end('hello!\n')
  })

  server.on('error', err => {
    throw err
  })

  server.listen({ fd }, () => {
    const addr = server.address()
    console.log('Listening on', addr)
  })
}

See the examples directory for more examples incl. supporting both socket activation and direct execution.

Launchd configuration

Normally you'd put this in ~/Library/LaunchAgents.

org.example.app.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>org.example.app</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/bin/node</string>
            <string>ABSOLUTE_PATH_TO_YOUR_JS_FILE</string>
        </array>
        <key>Sockets</key>
        <dict>
            <key>app</key>
            <array>
                <dict>
                    <key>SockFamily</key>
                    <string>IPv4</string>
                    <key>SockServiceName</key>
                    <string>3000</string>
                </dict>
            </array>
        </dict>
        <key>StandardErrorPath</key>
        <string>/tmp/org.example.app.err</string>
        <key>StandardOutPath</key>
        <string>/tmp/org.example.app.out</string>
    </dict>
</plist>

There's no need to set RunAtLoad, launchd will start your app on the first request.

Enable and start listening by running:

launchctl load ~/Library/LaunchAgents/org.example.app.plist

Systemd configuration

Normally you'd put these in /etc/systemd/system.

app.service

[Unit]
RefuseManualStart=true

[Service]
Restart=always
ExecStart=/usr/local/bin/node ABSOLUTE_PATH_TO_YOUR_JS_FILE

app.socket

[Socket]
ListenStream=127.0.0.1:3000
NoDelay=true
FileDescriptorName=app

[Install]
WantedBy=sockets.target

Enable and start listening by running:

systemctl enable app.socket
systemctl start app.socket

There's no need to enable the service, systemd will start it on the first request.

API

.collect(String name) → [Number]

Returns the list of fds the system has managed for us. This operation consumes the list and can therefore only be performed once per launch. Subsequent calls with the same name throw an Error. It's your responsibility not to do that.

The name is case sensitive and must match the name of the socket. Under systemd, the setting is FileDescriptorName=. Under launchd, the <key>...</key> of the socket definition defines the name.

Note that the method returns an Array of fds. For example, there may be more than one fd if you select the "IPv4v6" SockFamily in launchd.plist which listens to both IPv4 and IPv6, or if several ListenStream are given in systemd.socket. Up to you to decide if you want to error out when given multiple fds or setup multiple listeners.

The API is the same for all supported service managers.

This method throws an Error if:

  • The process was not launched by the service management framework (or with launchd, if there's no matching socket).
    • Error .code is 'ESRCH'
  • There is no matching socket.
    • Error .code is 'ENOENT'
  • The fd list has already been collected previously.
    • Error .code is 'EALREADY'
  • An internal system error occurred.

License

See LICENSE.