shuffrand
Version:
Cryptographically secure randomizer and shuffler.
142 lines (96 loc) • 8.22 kB
Markdown
<!-- /shuffrand/README.md -->
`shuffrand` offers three micro-tools: integer/double <mark>yielding</mark>, Fisher–Yates <mark>shuffling</mark>, and entropy-driven <mark>scrambling</mark>. Replaces "random enough" (step aside, `Math.random()`!) with runtime-validated fairness in a <mark>featherlight ESM bundle</mark>. For enterprise R&D teams and solo OSS maintainers alike — `shuffrand` seamlessly slips into <mark>Node/browser envs</mark> to provide <mark>rock-solid randomness</mark> exactly when and where needed.
shuffle + random = shuffrand
---
The modern JavaScript ecosystem suffers from a dangerous legacy: the pervasive use of `Math.random()`. This insecure, predictable pseudo-random number generator is a ticking time bomb in applications that silently rely on it for sensitive operations.
`shuffrand` was forged from the conviction that secure randomness should not be an afterthought; it should be the **default**. It provides a lean, powerful, and developer-friendly API that makes leveraging a true Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) simple, safe, and standard.
## An Uncompromising Approach to Randomness
`shuffrand` is built on a foundation of core principles that manifest as powerful, developer-friendly features.
#### ✔️ Secure by Default & Design
**Our Principle:** Security is non-negotiable. We exclusively use cryptographically secure primitives. There will never be an option for insecure methods like `Math.random` or seeded generators.<br>
**Your Feature:** Leverage `globalThis.crypto.getRandomValues()` (CSPRNG) for **truly** unpredictable numbers, strings, and array permutations. Our `calculateStringEntropy` utility even lets you quantify this cryptographic strength in bits.
#### ✔️ A Superior Developer Experience
**Our Principle:** A powerful API that is difficult to use is a failed API. We prioritize clarity and safety to make security the path of least resistance.<br>
**Your Features:** A fully-typed TypeScript API, plus robust runtime validation via **ArkType**, which provides clear, descriptive error messages and prevents unexpected behavior from invalid inputs.
#### ✔️ Modern, Lean, and Performant
**Our Principle:** We embrace the future of JavaScript. The library is architected with a pure ESM, future-forward mindset.<br>
**Your Features:** A pure ESM package that is optimized for Node.js v20+ and supports modern bundlers for optimal tree-shaking, keeping your application's footprint lean.
#### ✔️ Flexible & Precise by Design
**Our Principle:** A secure tool should also be a flexible one. We provide granular control over the output to fit your exact use case.<br>
**Your Features:**
- **Numbers:** Generate integers or doubles with precise bounds and advanced exclusion logic.
- **Strings:** Create random strings from predefined (`alphanumeric`, `hex`, etc.) or custom Unicode-aware character sets, with a powerful `noRepeat` option.
- **Arrays:** Perform secure Fisher–Yates shuffles, with support for both in-place (destructive) and non-destructive modes, as well as shuffling a specific **subarray**.
## `shuffrand` vs. The World
Why choose `shuffrand` over common alternatives? The difference is **security**.
| Feature | `shuffrand` | Vanilla JS (`Math.random()`) | Lodash (`_.random`, `_.shuffle`) |
| :----------------- | :--------------------------- | :--------------------------- | :------------------------------- |
| **Entropy Source** | ✅ Cryptographic (CSPRNG) | ❌ **Insecure** (PRNG) | ❌ **Insecure** (PRNG) |
| **Bias** | ✅ Unbiased | ⚠️ Potentially biased | ✅ Unbiased (but insecure) |
| **Error Handling** | ✅ Robust runtime validation | ❌ None (fails silently) | ⚠️ Minimal type checks |
## Installation
• **pnpm**: `pnpm install shuffrand`<br>• **npm**: `npm install shuffrand`<br>• **Deno**: `import { cryptoRandom, cryptoShuffle, cryptoString } from "npm:shuffrand@1.4.0"` — <small>no dedicated `install`/`add` command</small><br>• **Yarn**: `yarn add shuffrand`<br>• **Bun**: `bun add shuffrand`
Using `shuffrand` is designed to be lean and intuitive.
```js
import { cryptoRandom, cryptoShuffle, cryptoString } from 'shuffrand'
// A secure d20 dice roll for your TTRPG.
const diceRoll = cryptoRandom({ lowerBound: 1, upperBound: 20 })
// → e.g., 17
// A 6-character, unique hex code for a color.
const hexCode = cryptoString({ length: 6, characterSet: 'hex', noRepeat: true })
// → e.g., "3a9f0c"
// Securely shuffle a deck of cards, leaving the original unchanged.
const deck = ['A', 'K', 'Q', 'J', '10', '9']
const shuffledDeck = cryptoShuffle(deck)
// → e.g., ['9', 'J', 'A', '10', 'Q', 'K']
```
`shuffrand` is a powerful utility for real-world scenarios where unpredictability and fairness are paramount.
Generate cryptographically strong session tokens, API keys, verification codes, and unique identifiers. Create robust, high-entropy salts for hashing algorithms.
Implement truly fair dice rolls, coin flips, and virtual card shuffles. Create unpredictable loot drops, map layouts, or event sequences for games and statistical models.
Select unbiased random subsets from large datasets for analysis. Efficiently shuffle and assign users to different variations for A/B testing or randomized content.
`shuffrand` is the foundational engine of a larger, ambitious ecosystem named `monorand`. While `shuffrand` remains focused on providing the core, un-opinionated primitives of randomness, it will power a new companion library:
- **`datrand`** (data-randomization): A future synthetic data maker that will heavily rely on `shuffrand`’s robust and secure primitives to generate everything from secure UUIDs and passcodes to complex, themed mock data.
`shuffrand` is a pure ES Module. To use it directly in a browser without a build step, you need an **Import Map** to tell the browser where to find the module on a CDN.
```html
<!DOCTYPE html>
<html>
<head>
<title>shuffrand in the Browser</title>
<!-- 1. Define the Import Map -->
<script type="importmap">
{
"imports": {
"shuffrand": "https://unpkg.com/shuffrand@1.4.0/dist/index.es.js",
"arktype": "https://esm.sh/arktype@2.1.20",
"@ark/schema": "https://esm.sh/@ark/schema@0.46.0",
"@ark/util": "https://esm.sh/@ark/util@0.46.0"
}
}
</script>
</head>
<body>
<h1>Check the console (F12)</h1>
<!-- 2. Use the import in your module script -->
<script type="module">
import { cryptoRandom } from 'shuffrand'
const secureRoll = cryptoRandom({ lowerBound: 1, upperBound: 6 })
console.log(`Your secure dice roll is: ${secureRoll}`)
</script>
</body>
</html>
```
**Note:** Due to browser security (CORS), you must serve this HTML file from a local web server, not by opening the file directly. A simple way is to run `python -m http.server 8000` in the file's directory.
## A Note on Craftsmanship
This repository is intentionally structured to serve not only as a high-quality library but also as a reference implementation. From the rigorous, "test the final product" CI/CD pipelines to the dual-layer validation strategy and our comprehensive project **[DOCTRINE](DOCTRINE.md)**, every aspect has been designed with professional-grade software engineering principles in mind.
## Community & Contribution
- **Found a defect? Have a good idea?** Please open an issue on our **[GitHub Issues](https://github.com/DoronBrayer/monorand/issues)**.
- **Want to contribute code?** Please read our **[Contributing Guidelines](CONTRIBUTING.md)** and **[Code of Conduct](CODE_OF_CONDUCT.md)** first.