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

@neondatabase/functions

v0.7.0

Published

Runtime helpers for Neon Functions: `waitUntil` for deferring async work past a response, and `upgradeWebSocket` for serving WebSockets from a fetch handler.

Readme

@neon/functions

Runtime helpers for Neon Functions:

  • waitUntil — defer background work past a response.
  • upgradeWebSocket — serve WebSockets from a fetch handler.

Install

npm install @neon/functions

Requirements: Node.js >= 20.19.

waitUntil

The API mirrors @vercel/functions: import waitUntil and call it directly with the promise you want to keep alive.

import { waitUntil } from "@neon/functions";

export default {
	async fetch(req: Request): Promise<Response> {
		// Fire-and-forget background work that should outlive the response.
		waitUntil(logRequest(req));
		return new Response("ok");
	},
};

waitUntil(promise) forwards the promise to the Neon Functions runtime, which keeps the invocation alive until the promise settles (up to the 15-minute waitUntil limit). When no invocation context is in scope — local dev, tests, or any non-Neon host — it is a no-op: the promise is accepted and ignored (it still runs on its own, it just isn't tracked), so the same code runs everywhere without branching. Passing a non-Promise throws a TypeError.

upgradeWebSocket

Turn an incoming WebSocket handshake into a live connection from inside your normal fetch handler. The API mirrors Deno.upgradeWebSocket:

import { upgradeWebSocket } from "@neon/functions";

export default {
	async fetch(req: Request): Promise<Response> {
		if (req.headers.get("upgrade")?.toLowerCase() !== "websocket") {
			return new Response("expected a websocket upgrade", { status: 426 });
		}

		const { socket, response } = upgradeWebSocket(req);
		socket.addEventListener("message", (event) => socket.send(event.data));
		return response;
	},
};

socket is a standard WebSocket, so both addEventListener and the onmessage/onopen/onclose/onerror properties work. It is still CONNECTING when you get it: the runtime writes the 101 only once your handler returns response, and the socket opens (firing open) at that point.

Return response unchanged. A 101 cannot be expressed as a plain Response — the fetch spec restricts constructed responses to statuses 200–599 — so the runtime hands back a response object that carries the pending upgrade. Cloning it, or rebuilding it (new Response(res.body, res), which response-rewriting middleware does), discards the upgrade; the runtime detects that and fails the request loudly rather than leaving your client waiting on a connection nobody upgraded.

Subprotocols

Pass protocol to select one of the subprotocols the client offered, which is echoed back in Sec-WebSocket-Protocol:

const { socket, response } = upgradeWebSocket(req, { protocol: "chat.v2" });

Per RFC 6455 §4.2.2 a server may only select a protocol the client offered, so passing one the client did not offer throws a TypeError instead of producing a handshake the client will reject. Omit it and no protocol is negotiated: the response header is absent and socket.protocol is "".

Notes

  • binaryType defaults to "arraybuffer" rather than the browser default of "blob", matching Deno and other server runtimes. Setting it to "blob" is supported.
  • extensions is always "". No extensions — including permessage-deflate — are negotiated.
  • Unlike waitUntil, this throws a TypeError off-platform (and on a request that is not a WebSocket handshake). There is no meaningful degraded WebSocket, so an error that says so beats a socket that could never open.

Requires a runtime with WebSocket support

upgradeWebSocket needs a Neon Functions runtime that provides the upgrade — deployed, or locally under neon dev. On an older runtime it throws the "only available inside a Neon Functions invocation" TypeError rather than misbehaving.

Runtime integration

The runtime publishes the active invocation context on globalThis.NEON_REQUEST_CONTEXT as a getter that returns the live context object directly — { waitUntil } during an invocation, undefined outside one. waitUntil reads that value straight off the global, so there is nothing for application code to wire up.

upgradeWebSocket works the same way, reading a bridge the runtime publishes under Symbol.for("neon.websocket.bridge"). All of the protocol work — the handshake, framing, fragmentation, ping/pong and the close handshake — lives in the runtime; this package is only a typed facade over it.