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

@hexlet/chat-server

v3.0.0

Published

HTTP and Socket.IO server for the Hexlet chat project

Readme

Backend Chat

HTTP and Socket.IO server for the Hexlet chat project. User accounts, channels and messages are stored in memory and reset when the server restarts.

Requirements

Node.js 22.12 or newer.

Install and run

npm install @hexlet/chat-server
npx start-server -s ./dist

The server listens on port 5001. It serves the client files from the directory passed with --static and returns its index.html for client routes such as /login.

Usage: start-server [OPTIONS]

Options:
  -v, --version            output the version number
  -a, --address <address>  address to listen on (default: "0.0.0.0")
  -p, --port <port>        port to listen on (default: 5001 or PORT)
  -s, --static <path>      path to static assets files (default: "./build")
  -h, --help               display help for command

REST API

All API endpoints exchange JSON. The following examples use the browser's Fetch API. This helper checks the HTTP status and parses the response.

const request = async (method, path, { token, body } = {}) => {
  const response = await fetch(`/api/v1${path}`, {
    method,
    headers: {
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    ...(body ? { body: JSON.stringify(body) } : {}),
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  return response.json();
};

Create a user and log in

const user = await request('POST', '/signup', {
  body: { username: 'newuser', password: '123456' },
});
// { token: '...', username: 'newuser' }

const { token } = await request('POST', '/login', {
  body: { username: 'admin', password: 'admin' },
});

Signup returns status 201, or 409 if the username already exists. Login returns status 200, or 401 if the credentials are invalid. Channel and message endpoints require the returned token in the Authorization header.

Channels

const channels = await request('GET', '/channels', { token });
// [{ id: '1', name: 'general', removable: false }, ...]

const channel = await request('POST', '/channels', {
  token,
  body: { name: 'new channel' },
});
// { id: '...', name: 'new channel', removable: true }

const renamedChannel = await request('PATCH', `/channels/${channel.id}`, {
  token,
  body: { name: 'renamed channel' },
});

const removedChannel = await request('DELETE', `/channels/${channel.id}`, { token });
// { id: '...' }

Messages

const messages = await request('GET', '/messages', { token });

const message = await request('POST', '/messages', {
  token,
  body: { body: 'hello', channelId: channels[0].id, username: 'admin' },
});
// { id: '...', body: 'hello', channelId: '1', username: 'admin', removable: true }

const editedMessage = await request('PATCH', `/messages/${message.id}`, {
  token,
  body: { body: 'updated message' },
});

const removedMessage = await request('DELETE', `/messages/${message.id}`, { token });
// { id: '...' }

Socket.IO events

Mutations through the REST API broadcast the same JSON response to connected Socket.IO clients.

| Event | Payload | | --- | --- | | newChannel | Created channel | | renameChannel | Updated channel | | removeChannel | { id } | | newMessage | Created message | | renameMessage | Updated message | | removeMessage | { id } |

import { io } from 'socket.io-client';

const socket = io();
socket.on('newMessage', (message) => {
  console.log(message);
});

Development and releases

The source lives in the server/ directory of the chat project. Run these commands from that directory.

make install
make lint
make test
npm audit

Version 3 uses Fastify 5 and requires Node.js 22.12 or newer. The REST endpoints and Socket.IO event names are unchanged. Applications that import the Fastify plugin must also use Fastify 5.

GitLab CI tests the server on pushes. Releases are published by hand with release-it and need an npm account with publish rights in the @hexlet scope.

npm login
make release                    # asks for patch / minor / major
npx release-it --no-increment   # publishes the version already in package.json

release-it requires a clean working tree. It bumps the version in package.json and package-lock.json, commits, tags the commit chat-server-v<version>, pushes the tag and publishes the package to npm.