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

@beastjs/use-rng

v0.1.25

Published

A deterministic random number generator with Octane hook and standalone APIs

Readme

@beastjs/use-rng

Deterministic random-number generation for Octane applications and standalone TypeScript. Seed pairs are hashed with SHA-512, and generated seeds use Web Crypto.

Verify a seed in your browser

Features

  • Reproducible output from a client seed, server seed, and nonce
  • Octane hook with compiler-independent hook slots
  • Standalone manager with concurrency-safe nonce reservation
  • Unbiased inclusive integer generation for dice, lotteries, and selections
  • Rounded floating-point ranges with configurable precision
  • ESM, CommonJS, and TypeScript declarations

Installation

For the Octane hook:

bun add @beastjs/use-rng octane

For the standalone entry, octane is not required:

bun add @beastjs/use-rng

The package requires Node.js 20 or newer. Browser usage requires the Web Crypto API.

Octane hook

import { useRNG } from '@beastjs/use-rng'

export function DiceRoller() {
  const { result, nonce, generateSeeds, rollInt } = useRNG()

  return (
    <section>
      <button onClick={generateSeeds}>New seeds</button>
      <button onClick={() => rollInt({ range: [1, 6] })}>Roll d6</button>
      <p>Result: {result ?? '—'}</p>
      <p>Next nonce: {nonce}</p>
    </section>
  )
}

rollDice, rollInt, and setSeedPair return their generated value, so they can also be awaited directly:

const percentage = await rollDice({
  range: [0, 100],
  decimalPlaces: 2
})

The hook uses its current seeds and nonce by default. Pass seedPair to reproduce an exact external input:

const value = await rollInt({
  seedPair: {
    clientSeed: 'player-42',
    serverSeed: 'round-7',
    nonce: 3
  },
  range: [1, 20]
})

Hook API

useRNG() returns:

  • clientSeed, serverSeed, nonce — current deterministic input
  • result — last rounded or integer result
  • seedPairNumber — last normalized seed-pair result
  • generateSeeds() — creates new 128-bit seeds and clears prior results
  • rollDice(options?) — generates a rounded number and reserves a nonce
  • rollInt(options?) — generates an unbiased inclusive integer and reserves a nonce
  • setSeedPair() — evaluates the current seed pair as a normalized number
  • getCurrentSeedPair() — returns the latest seed values, including updates made in the current event
  • setClientSeed, setServerSeed, setNonce — manual state setters

Options:

interface RandomWithPrecise {
  seedPair?: SeedPair
  range?: readonly [min: number, max: number]
  decimalPlaces?: number
}

interface RandomIntegerOptions {
  seedPair?: SeedPair
  range?: readonly [min: number, max: number]
}

Standalone API

import { RNGManager } from '@beastjs/use-rng/standalone'

const rng = new RNGManager('player-42', 'round-7')

const d6 = await rng.rollInt(1, 6)
const percentage = await rng.roll(0, 100, 2)
const nextD20 = await rng.peekInt(1, 20)

console.log({ d6, percentage, nextD20, seedPair: rng.getSeedPair() })

RNGManager

new RNGManager(clientSeed?, serverSeed?, nonce?)
  • roll(min?, max?, decimalPlaces?) — rounded result; increments the nonce
  • peek(min?, max?, decimalPlaces?) — rounded result; leaves the nonce unchanged
  • rollInt(min, max) — unbiased inclusive integer; increments the nonce
  • peekInt(min, max) — unbiased inclusive integer; leaves the nonce unchanged
  • generateSeeds() — replaces both seeds and resets the nonce
  • getSeedPair() — returns a snapshot of the current seed pair
  • setSeeds(clientSeed, serverSeed, nonce?) — replaces the seed pair
  • incrementNonce() / resetNonce() — manually manages the nonce

Concurrent roll() and rollInt() calls reserve their nonces before hashing, so a Promise.all batch produces the same ordered sequence as sequential calls.

Direct functions

Use the standalone entry when no UI framework is needed:

import {
  getRandomInt,
  getRandomSeedPair,
  getRandomWithPrecision,
  type SeedPair
} from '@beastjs/use-rng/standalone'

const seedPair: SeedPair = {
  clientSeed: 'client',
  serverSeed: 'server',
  nonce: 0
}

const normalized = await getRandomSeedPair(seedPair)
const d20 = await getRandomInt(seedPair, 1, 20)
const amount = await getRandomWithPrecision(seedPair, 10, 20, 3)

Also exported are hashSeed, bytesToInt, getRandomSeed, getRandomInRange, getRandomRange, and generateId.

Determinism and security

The same seed pair always produces the same output. Changing the nonce creates a reproducible sequence. getRandomInt uses rejection sampling over SHA-512 output to avoid modulo bias.

This library is suitable for simulations, games, deterministic assignments, and independently reproducible draws. It is not a replacement for Web Crypto when generating keys, passwords, session tokens, or other security credentials.

Development

bun install
bun run check

bun run check type-checks the library, runs the test suite, and builds both package entries.

License

MIT