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

@data-vegle/network

v3.1.1

Published

Typed, batched networking layer for roblox-ts, multiplexing every event and request over a fixed set of RemoteEvents with compile-time identifiers generated by the Flamework transformer.

Readme

@data-vegle/network

Typed, batched networking layer for roblox-ts. Every event and request of a NetworkDefinition is multiplexed over a fixed set of RemoteEvents, arguments are packed with @data-vegle/serial, and the identifiers are generated at compile time by the Flamework transformer.

npm install @data-vegle/network @data-vegle/serial @flamework/core @rbxts/hash rbxts-transformer-flamework

The library needs rbxts-transformer-flamework in the consumer's tsconfig.json: the ServerNet/ClientNet constructors are Flamework macros that receive the serializer metadata and the identifier of the definition.

{
	"compilerOptions": {
		"experimentalDecorators": true,
		"plugins": [{ "transform": "rbxts-transformer-flamework" }]
	}
}
// shared/network.ts
import type { CallbackNetEvent, NetworkDefinition, SingleNetEvent } from "@data-vegle/network";

export interface GameNet extends NetworkDefinition {
	id: "game";
	calls: {
		buy: CallbackNetEvent<[itemId: number, count: number], boolean>;
		notify: SingleNetEvent<[message: string]>;
	};
}
// server
import { ServerNet } from "@data-vegle/network";

const net = new ServerNet<GameNet>();
net.on("buy", (player, itemId, count) => shop.buy(player, itemId, count));

// client
import { ClientNet } from "@data-vegle/network";

const net = new ClientNet<GameNet>();
const bought = await net.call("buy", 12, 3);

The serde transformer (optional)

Every packet starts with a token identifying its namespace. By default that token is a hash of the definition id and the namespace: it costs 3 bytes, needs nothing outside the library, and the server and the client compute the same value on their own.

The package also ships a second, optional roblox-ts transformer at @data-vegle/network/transformer. It assigns a dense token to every endpoint at compile time, so the first 128 endpoints of a game cost 1 byte per packet instead of 3. Nothing changes in the code: the transformer finds every new ServerNet<Def>() / new ClientNet<Def>() of the program and appends the token table as the last constructor argument.

Setup

  1. Make sure typescript is installed in the game (it already is in any roblox-ts project). It is an optional peer dependency of this package, used only by the transformer.

  2. List the transformer in the plugins of the game's tsconfig.json, next to Flamework:

{
	"compilerOptions": {
		"experimentalDecorators": true,
		"plugins": [
			{ "transform": "rbxts-transformer-flamework" },
			{ "transform": "@data-vegle/network/transformer" }
		]
	}
}

Either order works. Flamework treats an explicit undefined argument like an omitted macro parameter, and the network transformer recognizes a call Flamework already rewrote.

  1. Build once (rbxtsc or rbxtsc -w). The transformer writes network.build next to the tsconfig:
{
	"version": 1,
	"serdes": {
		"game": {
			"buy": 0,
			"notify": 1
		}
	}
}
  1. Commit network.build, like flamework.build. It is what keeps the server and the client in agreement across incremental compiles: in watch mode roblox-ts only re-emits the files that changed, so a token must not move just because another file was recompiled. An endpoint keeps its token for as long as it exists, a removed endpoint frees its token, and a new one gets the smallest free token. Deleting the file only regenerates dense tokens on the next full build, which is safe as long as the server and the client are rebuilt together.

Options

The plugin entry accepts two settings:

{ "transform": "@data-vegle/network/transformer", "buildFile": "network.build", "verbose": true }
  • buildFile: where the tokens are persisted, relative to the directory of the tsconfig. Default network.build.
  • verbose: prints every id.namespace -> token assignment when compiling.

What gets a generated token

An endpoint is resolved only when the definition's id is a string literal type and its calls has fixed property names, which is the case for any definition written as an interface like the one above. The definition type is read from the explicit type argument (new ServerNet<GameNet>()) or inferred from the declared variable type.

Anything the transformer cannot resolve is silently skipped and falls back to the hashed token, which lives in a disjoint range: generated tokens stay below 16384, hashed tokens start there, so both kinds coexist at runtime. The transformer is also a no-op on a library version whose constructors have no serdes parameter, and it leaves a serdes argument written by hand alone.

Rules

  • Only the game runs the transformer. Generated tokens start at 0 in every program that runs it, so a package that instantiates its own nets and compiles with the transformer would collide with the game's tokens. The library detects this and throws at startup with a dedicated message. A package should compile without the transformer and rely on the hashed fallback.
  • Rebuild the server and the client together after changing a definition. Both sides read the same network.build, so a single build of the whole project is enough.
  • One definition id per ServerNet. Two ServerNet instances for the same id throw, with or without the transformer.

Without the transformer

Nothing to do: every namespace uses its hashed token. The only cost is up to 2 extra bytes per packet (3 instead of 1 for the first 128 endpoints). A definition compiled with the transformer on one side and without it on the other does not work, since the two sides would use different tokens for the same namespace.