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

@opensourceframework/seeded-rng

v0.2.0

Published

Seeded random number generator for reproducible randomness - NOT cryptographically secure

Readme

@opensourceframework/seeded-rng

npm version License: MIT

Seeded random number generator for reproducible randomness in games, simulations, and testing.

⚠️ SECURITY WARNING: The default SeededRNG class is NOT cryptographically secure!

Use SecureSeededRNG for security-sensitive operations (see below).

Two RNG Implementations

This library provides two RNG classes:

| Class | Algorithm | Secure? | Use Case | |-------|-----------|---------|----------| | SeededRNG | LCG | ❌ No | Games, testing, simulations | | SecureSeededRNG | ISAAC | ✅ Yes | Passwords, tokens, keys |

When to use which?

// ❌ NOT secure - Use for games, testing, simulations
import { SeededRNG } from '@opensourceframework/seeded-rng';
const gameRng = new SeededRNG(42);

// ✅ Secure - Use for security-sensitive operations
import { SecureSeededRNG } from '@opensourceframework/seeded-rng';
const secureRng = new SecureSeededRNG(42);

Features

  • 🎲 Deterministic Randomness - Same seed always produces the same sequence
  • 🔄 Reproducible Results - Perfect for testing, debugging, and replays
  • 🎮 Game Development - Procedural generation, AI behavior, loot tables
  • 🧪 Testing - Deterministic test data generation
  • 📊 Simulations - Reproducible simulation results
  • 🔐 Secure Option - Cryptographically secure version available
  • 🪶 Zero Dependencies - Lightweight and self-contained

Installation

npm install @opensourceframework/seeded-rng
# or
yarn add @opensourceframework/seeded-rng
# or
pnpm add @opensourceframework/seeded-rng

Quick Start

Basic Usage (Not Secure)

import { SeededRNG } from '@opensourceframework/seeded-rng';

// Create with a specific seed for reproducibility
const rng = new SeededRNG(42);

// Basic random values
console.log(rng.next());           // Float [0, 1)
console.log(rng.nextInt(1, 100));  // Integer [1, 100]
console.log(rng.nextFloat(0, 10)); // Float [0, 10)

// Game mechanics
const diceRoll = rng.nextInt(1, 6);
const isCritical = rng.chance(0.05); // 5% chance
const coinFlip = rng.nextBool();

// Array operations
const colors = ['red', 'green', 'blue'];
const randomColor = rng.pick(colors);
const shuffled = rng.shuffle([1, 2, 3, 4, 5]);

// Weighted selection (loot tables)
const loot = rng.weightedPick([
  { item: 'common', weight: 70 },
  { item: 'rare', weight: 20 },
  { item: 'legendary', weight: 1 },
]);

// Reset to replay the same sequence
rng.reset();
console.log(rng.nextInt(1, 100)); // Same as first call

Secure Usage (Cryptographically Secure)

import { SecureSeededRNG } from '@opensourceframework/seeded-rng';

// Create with a specific seed (reproducible AND secure)
const rng = new SecureSeededRNG(42);

// Generate secure random values
console.log(rng.nextInt(1, 100));  // Secure integer
console.log(rng.nextHex(32));      // Secure hex string (64 chars)

// Generate truly random (non-seeded) secure values
const randomRng = new SecureSeededRNG();
const sessionToken = randomRng.nextHex(32); // Each run = different
const apiKey = randomRng.nextBase64(32);    // Base64 encoded

// Generate proper UUID v4
const uuid = rng.nextUUID(); // Cryptographically secure UUID

// Fork for independent but deterministic streams
const fork1 = rng.fork();
const fork2 = rng.fork();

API Reference

SeededRNG Class (Fast, NOT Secure)

Constructor

new SeededRNG(seed?: number)

Creates a new RNG instance. If no seed is provided, a random seed is generated.

Methods

| Method | Description | |--------|-------------| | next() | Returns random float [0, 1) | | nextInt(min, max) | Returns random integer [min, max] | | nextFloat(min, max) | Returns random float [min, max) | | nextBool(probability?) | Returns random boolean (default 50%) | | nextSign() | Returns -1 or 1 | | chance(probability) | Returns true with given probability | | pick(array) | Returns random element from array | | shuffle(array) | Returns shuffled copy of array | | weightedPick(items) | Weighted random selection | | nextHex(length) | Returns random hex string | | nextUUID() | Returns UUID-like string | | fork() | Creates new independent RNG | | reset() | Resets to initial state | | getInitialSeed() | Gets the initial seed | | getCurrentSeed() | Gets current state | | setSeed(seed) | Sets current state | | getStats() | Gets RNG statistics |

SecureSeededRNG Class (Cryptographically Secure)

Constructor

new SecureSeededRNG(seed?: number)

Creates a cryptographically secure RNG. If no seed is provided, uses crypto.getRandomValues().

Security Methods

| Method | Description | |--------|-------------| | nextHex(length) | Secure random hex string | | nextBytes(length) | Secure random byte array | | nextBase64(length) | Secure Base64 encoded string | | nextUUID() | Secure UUID v4 |

Standard Methods (Same as SeededRNG)

| Method | Description | |--------|-------------| | next() | Returns random float [0, 1) | | nextInt(min, max) | Returns random integer [min, max] | | nextFloat(min, max) | Returns random float [min, max) | | nextBool(probability?) | Returns random boolean | | chance(probability) | Returns true with given probability | | pick(array) | Returns random element from array | | shuffle(array) | Returns shuffled copy of array | | weightedPick(items) | Weighted random selection | | fork() | Creates new independent RNG | | reset() | Resets to initial state |

Convenience Functions

import { 
  createRNG, 
  createSecureRNG,
  seededInt, 
  seededFloat, 
  seededShuffle, 
  seededPick,
  seededSecureInt,
  seededSecureHex
} from '@opensourceframework/seeded-rng';

// Fast RNG (not secure)
const rng = createRNG(42);
const value = seededInt(42, 1, 100);

// Secure RNG
const secureRng = createSecureRNG(42);
const secureHex = seededSecureHex(42, 32);

Usage Examples

Secure Token Generation

import { SecureSeededRNG } from '@opensourceframework/seeded-rng';

// Generate session tokens (secure!)
function generateSessionToken(): string {
  const rng = new SecureSeededRNG();
  return rng.nextHex(32); // 64-character hex string
}

// Generate API keys
function generateApiKey(): string {
  const rng = new SecureSeededRNG();
  return `sk_${rng.nextHex(24)}`;
}

// Generate password reset tokens
function generateResetToken(): string {
  const rng = new SecureSeededRNG();
  return rng.nextBase64(32);
}

// Generate secure UUIDs
function generateSecureId(): string {
  const rng = new SecureSeededRNG();
  return rng.nextUUID(); // Real UUID v4
}

Procedural Generation

import { SeededRNG } from '@opensourceframework/seeded-rng';

function generateTerrain(seed: number, width: number, height: number) {
  const rng = new SeededRNG(seed);
  const terrain = [];
  
  for (let y = 0; y < height; y++) {
    const row = [];
    for (let x = 0; x < width; x++) {
      row.push({
        elevation: rng.nextFloat(0, 1),
        moisture: rng.nextFloat(0, 1),
        hasTree: rng.chance(0.1),
      });
    }
    terrain.push(row);
  }
  
  return terrain;
}

// Same seed always produces same terrain
const world1 = generateTerrain(12345, 100, 100);
const world2 = generateTerrain(12345, 100, 100);
// world1 === world2 (same data)

Game Loot System

import { SeededRNG } from '@opensourceframework/seeded-rng';

class LootSystem {
  private rng: SeededRNG;

  constructor(seed: number) {
    this.rng = new SeededRNG(seed);
  }

  dropLoot() {
    const rarity = this.rng.weightedPick([
      { item: 'common', weight: 60 },
      { item: 'uncommon', weight: 25 },
      { item: 'rare', weight: 12 },
      { item: 'epic', weight: 2.5 },
      { item: 'legendary', weight: 0.5 },
    ]);

    const itemCount = this.rng.nextInt(1, 3);
    const items = [];

    for (let i = 0; i < itemCount; i++) {
      items.push(this.generateItem(rarity));
    }

    return { rarity, items };
  }

  private generateItem(rarity: string) {
    return {
      id: this.rng.nextUUID(),
      name: `${rarity} item`,
      stats: {
        power: this.rng.nextInt(10, 100),
        defense: this.rng.nextInt(5, 50),
      },
    };
  }
}

Testing with Deterministic Data

import { SeededRNG } from '@opensourceframework/seeded-rng';

describe('User Processing', () => {
  let rng: SeededRNG;

  beforeEach(() => {
    rng = new SeededRNG(42); // Consistent seed for all tests
  });

  function generateTestUser() {
    return {
      id: rng.nextUUID(),
      name: `User_${rng.nextInt(1000, 9999)}`,
      email: `test${rng.nextInt(1, 100)}@example.com`,
      age: rng.nextInt(18, 80),
      active: rng.nextBool(),
    };
  }

  it('should process user correctly', () => {
    const user = generateTestUser();
    // Same user data every test run
    expect(user.age).toBe(58); // Deterministic!
  });
});

Algorithm

SeededRNG (Fast, Not Secure)

Uses the Linear Congruential Generator (LCG) algorithm:

seed = (seed * a + c) % m

With parameters from Numerical Recipes:

  • a = 9301
  • c = 49297
  • m = 233280

SecureSeededRNG (Cryptographically Secure)

Uses the ISAAC (Indirection, Shift, Accumulate, Add, and Count) cipher algorithm:

  • Designed by Bob Jenkins (1996)
  • Passes statistical tests for randomness
  • Suitable for cryptographic applications
  • Deterministic like SeededRNG (same seed = same sequence)

For random bytes without a seed, uses:

  • Browser: crypto.getRandomValues()
  • Node.js: crypto.webcrypto.getRandomValues()

Contributing

See Contributing Guide for details.

License

MIT © OpenSource Framework Contributors