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/serial

v1.4.1

Published

Serialize roblox-ts types into buffers.

Readme

@rbxts/serial

Serialize roblox-ts types into buffers.

Status: scaffolding only. The toolchain is set up and verified; the serializer itself is not written yet.

Toolchain

| Piece | Why it's here | | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | roblox-ts 3.0 | TypeScript → Luau compiler | | Flamework 1.3 | its transformer exposes compile-time type metadata (user macros) | | Rojo 7 | syncs the compiled output into Studio | | Prettier | formatting, enforced in CI |

Flamework is the reason this project isn't a plain roblox-ts package. Its transformer can hand you a type's identity, a printed form of the type, and a generated runtime guard — all derived from a TypeScript type at build time. That is what the serializer templates will be generated from, instead of asking callers to hand-write a schema next to every interface.

Setup

npm install
npm run build

Studio-side tooling is pinned in rokit.toml:

rokit install   # installs Rojo

Scripts

| Script | What it does | | --------------------- | ----------------------------------------------------------------------- | | npm run build | compile src/out/ as a package | | npm run watch | same, in watch mode | | npm run build:place | compile as a game instead, emitting the include/ runtime | | npm run place | build the place and pack it into serial-test.rbxl for Studio | | npm run clean | remove out/ and include/ | | npm run format | run Prettier over src/ |

build and build:place write to the same out/ directory, so build:place cleans first. Run npm run build again before publishing.

Layout

src/                  library source, compiled to out/
default.project.json  Rojo project for the package itself
bench/                benchmark: its own roblox-ts project (src/ → out/) plus the Lune and Studio runners
bench/test.project.json  Rojo place used to run the benchmark (and try the library) in Studio
flamework.build       Flamework's identifier table — commit it, don't edit it

flamework.build holds the stable ids the transformer hands out. It is tracked in git and shipped in the published package on purpose; deleting it makes previously generated ids drift.

Writing a type macro

Flamework user macros need two things: the plugins entry in tsconfig.json (already there), and a @metadata macro JSDoc tag on the function. Without the tag the transformer silently skips the call and the parameter arrives as undefined.

src/index.ts has the minimal working example:

/** @metadata macro */
export function typeIdOf<T>(id?: Modding.Generic<T, "id">): string {
	assert(id !== undefined, "typeIdOf<T>() was called without the Flamework transformer");
	return id;
}

Callers just write typeIdOf<PlayerState>() and the transformer rewrites it to typeIdOf("@rbxts/serial:src/index@PlayerState"). Swapping "id" for "text" or "guard" in Modding.Generic gives the printed type or a runtime type guard instead — those are the hooks the buffer serializer will be built from.

Benchmark

bench/src/bench.ts serializes and deserializes a set of representative types against the compiled library in out/ and prints bytes per payload, microseconds per call and a round-trip check. It is a roblox-ts project of its own (bench/tsconfig.json, compiled to bench/out/): every schema is generated by the Flamework transformer from a real TypeScript type, and the library is imported through the declarations in out/, so the benchmark exercises the package exactly the way a consumer does. The compiled module is then required from plain Luau:

| Command | Where it runs | | ---------------------- | ------------------------------------------------------------------------------ | | npm run build:bench | compiles bench/src/bench/out/ (needs out/ from npm run build) | | npm run bench | builds both, then Lune runs bench/lune.luau | | npm run bench:lune | same, without rebuilding the library first | | npm run bench:studio | builds serial-test.rbxl and runs bench/studio.server.luau through run-in-roblox | | npm run test | builds both, then Lune runs only the test suite (bench/src/test.ts) | | npm run test:lune | same, without rebuilding the library first |

Both runners execute the test suite before the benchmark and stop when a case fails. The suite round-trips deliberately awkward values (NaN, negative zero, NUL bytes, varuint boundaries, empty and table-keyed collections, blobs, serializers and serialized payloads used as data) and asserts the error text of invalid inputs; npm run test:lune -- <text> keeps only matching cases.

Both runners need rokit install (Lune and run-in-roblox are pinned in rokit.toml). Pass a filter to keep only matching cases: npm run bench:lune -- list. Pass native to run with Luau native code generation (npm run bench:lune -- native); the results then go to <version>-lune-native.md and must not be compared with interpreted files.

bench/test.project.json describes the Studio place and doubles as the Rojo project roblox-ts uses to resolve the ../../out import: serial (out/) and bench (bench/out/) sit side by side under ReplicatedStorage, so the compiled bench reaches the library through script.Parent.Parent.serial. The Lune runner mirrors that tree with fake instances. The compiled bench is loaded with a stand-in for the roblox-ts runtime that only implements TS.import, so bench.ts must avoid anything that needs RuntimeLib (try/catch, async, generators, instanceof, spread).

A full Lune run writes its table to bench/bench_results/<version>-lune.md, keyed on the version in package.json and stamped with the commit hash, so the numbers for each release stay in the repository. The Studio run prints the same Markdown to the Output window for pasting into bench/bench_results/<version>-studio.md.

Lune numbers are good for comparing one commit against another. Use the Studio run for absolute numbers: Studio has a native vector type and Lune does not, so Vector3/CFrame heavy cases are slower under Lune than they will be in game.

License

MIT