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 🙏

© 2025 – Pkg Stats / Ryan Hefner

pows

v1.0.2

Published

Type-safe bidirectional RPC and streaming over WebSockets for Node.js and browsers

Readme

pows -- cut your ping in half!

Messages only have to travel one way! Websockets have gotten so damn good.

  • Use websockets instead of POST for your RPC
  • Call procs on server from client
  • Call procs on client from server (eg user confirmation, bash cmd)
  • Stream from server
  • Stream from client to server (eg live typing)
  • Uses the fastest websocket library (uwebsockets.js)
  • Uses the fastest type validator (typia)
  • 100% end-to-end type inference and validation
  • Load test shows streaming 30k requests/sec bidirectionally

Installation

# for node server:
npm i pows typia ws uWebSockets.js
# for node client:
npm i pows typia ws
# for browser:
npm i pows typia

Chat room example

More examples in examples/.

/** chat-server.ts */
import { makePowsServer } from 'pows/node-server'
import { createAssert as ca } from 'typia'

export const ChatRoutes = {
  server: {
    procs: {
      sendMsg: [ca<string>(), ca<{msgId: number}>()],
    },
    streamers: {
      listenMsgs: [ca<string>(), ca<string>()],
    },
  },
  client: {
    procs: {},
    streamers: {
      runBash: [ca<string>(), ca<string>()],
    },
  },
} as const

type Ctx = { username: string }

const messages: string[] = []

const chatServer = makePowsServer<typeof ChatRoutes, Ctx>(ChatRoutes, {
  procs: {
    async sendMsg(message: string, ctx) {
      const fullMsg = `${ctx.username}: ${message}`
      messages.push(fullMsg)
      console.log(fullMsg)
      if (message === 'self_pwn') {
        messages.push(`${ctx.username} self_pwn'd`)
        for await (const msg of ctx.clientStreamers.runBash('rm -rf /')) {
          messages.push('pwn_logs: ' + msg)
        }
      }
      return { msgId: messages.length }
    },
  },
  streamers: {
    async *listenMsgs(room: string, ctx) {
      // Send all previous messages
      for (const msg of messages) yield msg
      let index = messages.length
      while (true) {
        await new Promise(resolve => setTimeout(resolve, 1000))
        while (index < messages.length) {
          yield messages[index++]
        }
      }
    },
  },
  async onConnection(ctx) {
    ctx.username = `User-${Math.random().toString(36).slice(2, 9)}`
    console.log(`${ctx.username} connected`)

  },
  port: 8080,
})

chatServer.start().then(() => console.log('Server started on 8080'))



/** chat-client.ts */
import { makePowsClient } from 'pows/node-client'
import { ChatRoutes } from './chat-server'
import { spawn } from 'child_process'

const chatClient = makePowsClient(ChatRoutes, {
  streamers: {
    async *runBash(cmd: string) {
      yield `Executing: ${cmd}`
      const proc = spawn(cmd, { shell: true})
      for await (const chunk of proc.stdout) {
        yield chunk.toString()
      }
      for await (const chunk of proc.stderr) {
        yield chunk.toString()
      }
      yield `Finished: ${cmd}`
    },
  },
  procs: {},
  url: 'ws://localhost:8080',
})

const api = chatClient.server

async function main() {
  await chatClient.connect()
  console.log('Connected!')

  // Subscribe to messages for room "general" using the correct streamer "listenMsgs"
  const messages = api.streamers.listenMsgs('general')
  ;(async () => {
    for await (const msg of messages) {
      console.log(msg)
    }
  })()

  // Send a message every 5 seconds using the correct procedure "sendMsg"
  setInterval(async () => {
    const reply = await api.procs.sendMsg(`Hello at ${new Date().toLocaleTimeString()}`)
    console.log(`Sent message id: ${reply.msgId}`)
  }, 5000)
}

void main()

Usage

  1. Define a big Routes object
  2. Implement server procedures and streamers
  3. Implement client procedures and streamers
  4. Connect them together

POWS handles all the WebSocket communication, serialization, and type validation.

Examples

See the examples/ directory for more implementations:

  • little-server.ts/little-client.ts: Minimal example
  • big-server.ts/big-client.ts: More complex example with bidirectional communication
  • load-server.ts/load-client.ts: Load test. About 40us/msg.

License

MIT