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

@alkemist-17/ropes

v1.0.0

Published

A TypeScript library for generating cryptographically secure random strings with configurable alphabets, sizes, and formatting options.

Readme

Ropes

npm version license TypeScript

Ropes is a TypeScript library for generating cryptographically secure random strings. It provides a simple, functional API with configurable alphabets, size options, and formatting features.

Features

  • Cryptographically Secure - Uses Node.js crypto.randomBytes() for true randomness
  • Multiple Alphabets - 7 built-in presets (base64, base64url, hex, alphanumeric, etc.)
  • Custom Alphabets - Use your own character sets
  • Password-Safe - Built-in alphabet excluding ambiguous characters (I, l, 1, O, 0)
  • Flexible Sizing - Fixed size or range (min/max) modes
  • Formatting - Prefix/suffix, chunking with delimiters, pattern templates
  • Bulk Generation - Generate multiple strings at once
  • Seeded Mode - Deterministic generation for testing (non-crypto)

Installation

npm i @alkemist-17/ropes

Usage

Basic Usage

import ropes from 'ropes';

// Generate a 31-character random string (default)
const token = ropes.generate();

// Custom size
const id = ropes.generate({ size: 16 });

// Custom alphabet
const hex = ropes.generate({ size: 32, alphabet: ropes.alphabets.hex });

Alphabets

Ropes includes several built-in alphabet presets:

import { alphabets } from 'ropes';

// Standard Base64 (RFC 4648)
ropes.generate({ alphabet: alphabets.base64 });
// A-Za-z0-9+/

// URL-safe Base64 (RFC 4648 §5)
ropes.generate({ alphabet: alphabets.base64url });
// A-Za-z0-9-_

// Hexadecimal
ropes.generate({ alphabet: alphabets.hex });
// 0-9a-f

// Alphanumeric
ropes.generate({ alphabet: alphabets.alphanumeric });
// A-Za-z0-9

// Lowercase alphanumeric
ropes.generate({ alphabet: alphabets.alphanumericLower });
// a-z0-9

// Numeric only
ropes.generate({ alphabet: alphabets.numeric });
// 0-9

// Password-safe (excludes I, l, 1, O, 0)
ropes.generate({ alphabet: alphabets.password });

Custom Password Alphabet

Create password alphabets with custom exclusions and symbols:

import { createPasswordAlphabet } from 'ropes';

// Exclude additional ambiguous characters
const strictPassword = createPasswordAlphabet({
  exclude: ['I', 'l', '1', 'O', '0', 'S', '5', 'B', '8']
});

// Include symbols
const symbolPassword = createPasswordAlphabet({
  includeSymbols: true,
  symbolSet: '!@#$%^&*'
});

// Use the custom alphabet
ropes.generate({ size: 16, alphabet: symbolPassword });

Size Modes

// Fixed size (default: 31)
ropes.generate({ size: 32 });

// Range mode - random size between min and max
ropes.generate({ size: { min: 24, max: 32 } });

Prefix and Suffix

Add static text before and after the random string. Prefix and suffix do NOT count toward the size.

// Generates: user_ABCDEFGHIJKLMNOP_suffix (16 random chars)
ropes.generate({ 
  size: 16, 
  prefix: 'user_', 
  suffix: '_suffix' 
});

Chunking

Split the output into chunks with delimiters. The last chunk can be shorter than chunkSize.

// Generates: abcd-efgh-ijkl-mnop (16 chars, 4 per chunk)
ropes.generate({ 
  size: 16, 
  delimiter: '-', 
  chunkSize: 4 
});

// With size=10, chunkSize=4: aaaa-bbbb-cc
ropes.generate({ size: 10, delimiter: '-', chunkSize: 4 });

Pattern Templates

Use patterns with X as a placeholder for random characters. The size is determined by the number of X characters in the pattern.

// Generates: aB-cD-eF-gH (8 random chars in XX-XX-XX-XX format)
ropes.generate({ pattern: 'XX-XX-XX-XX' });

// Product key style
ropes.generate({ pattern: 'XXX-XXX-XXX-XXX' });

// Mixed with prefix
ropes.generate({ pattern: 'XX-XX', prefix: 'KEY_' });
// Generates: KEY_aB-cD

Note: If your alphabet contains characters that appear in the pattern (e.g., using base64url alphabet with a - delimiter pattern), the output will include both the pattern delimiters and any matching characters from the random string. For guaranteed formatting, use an alphabet that doesn't include your pattern delimiters:

// Safe: hex doesn't contain '-'
ropes.generate({ 
  pattern: 'XX-XX-XX-XX', 
  alphabet: ropes.alphabets.hex 
});

// Unsafe: base64url contains '-' which may appear in output
ropes.generate({ 
  pattern: 'XX-XX-XX-XX', 
  alphabet: ropes.alphabets.base64url 
});
// May produce: aB--cD-eF-gH (extra hyphens from random chars)

Bulk Generation

Generate multiple strings at once:

// Synchronous
const tokens = ropes.generateMany(10, { size: 32 });

// Asynchronous
const ids = await ropes.generateManyAsync(5, { 
  size: 16, 
  alphabet: ropes.alphabets.hex 
});

Async API

All generation functions have async variants:

// Single string
const token = await ropes.generateAsync({ size: 32 });

// Multiple strings
const tokens = await ropes.generateManyAsync(10, { size: 32 });

Seeded Generation (Testing Only)

⚠️ WARNING: Seeded generation uses a pseudo-random number generator and is NOT cryptographically secure. Use this only for testing, development, or demos.

// Same seed produces same output
const str1 = ropes.generateSeeded({ seed: 'my-test-seed', size: 16 });
const str2 = ropes.generateSeeded({ seed: 'my-test-seed', size: 16 });
console.log(str1 === str2); // true

// Different seeds produce different outputs
const str3 = ropes.generateSeeded({ seed: 'other-seed', size: 16 });
console.log(str1 === str3); // false

API Reference

Functions

generate(options?)

Generate a cryptographically secure random string.

Parameters:

interface GenerateOptions {
  size?: number | { min: number; max: number };  // Default: 31
  alphabet?: string;                            // Default: base64url
  prefix?: string;                              // Does NOT count toward size
  suffix?: string;                              // Does NOT count toward size
  delimiter?: string;                           // Requires chunkSize
  chunkSize?: number;                          // Requires delimiter
  pattern?: string;                             // Uses X as placeholder
}

Returns: string

Example:

ropes.generate({ size: 16, alphabet: ropes.alphabets.hex });

generateAsync(options?)

Async variant of generate().

Returns: Promise<string>

generateMany(count, options?)

Generate multiple random strings.

Parameters:

  • count: number - Number of strings to generate
  • options?: GenerateOptions - Same as generate()

Returns: string[]

Throws: If count is not positive

generateManyAsync(count, options?)

Async variant of generateMany().

Returns: Promise<string[]>

generateSeeded(options)

Generate a deterministic random string using a seed. NOT CRYPTOGRAPHICALLY SECURE - FOR TESTING ONLY

Parameters:

interface SeededOptions {
  seed: string;                                 // Required
  size?: number | { min: number; max: number };
  alphabet?: string;
  prefix?: string;
  suffix?: string;
}

Returns: string

Throws: If seed is not provided

Alphabets

Built-in Presets

| Alphabet | Characters | Size | Notes | |----------|------------|------|-------| | base64 | A-Za-z0-9+/ | 64 | RFC 4648 | | base64url | A-Za-z0-9-_ | 64 | URL-safe, RFC 4648 §5 | | hex | 0-9a-f | 16 | Hexadecimal | | alphanumeric | A-Za-z0-9 | 62 | All alphanumeric | | alphanumericLower | a-z0-9 | 36 | Lowercase only | | numeric | 0-9 | 10 | Digits only | | password | A-Za-z0-9 (excl. I,l,1,O,0) | 57 | Password-safe |

createPasswordAlphabet(options?)

Create a custom password alphabet.

Parameters:

interface PasswordAlphabetOptions {
  exclude?: string[];        // Characters to exclude
  includeSymbols?: boolean;   // Add symbol characters
  symbolSet?: string;        // Custom symbol set (default: '!@#$%^&*();:{}[]')
}

Returns: string - The custom alphabet

Example:

const custom = createPasswordAlphabet({
  exclude: ['I', 'l', '1', 'O', '0'],
  includeSymbols: true,
  symbolSet: '!@#$%'
});

Security Notes

Cryptographic Security

  • Default generation uses node:crypto.randomBytes() which provides cryptographically secure randomness
  • Rejection sampling is used to ensure uniform distribution across the alphabet, avoiding modulo bias
  • All built-in alphabets have been analyzed for security properties

Entropy Analysis

| Alphabet | Bits/Char | 32-char string | |----------|-----------|----------------| | base64 | 6.0 | 192 bits | | hex | 4.0 | 128 bits | | alphanumeric | ~5.95 | ~190 bits | | password | ~5.81 | ~186 bits |

All configurations provide sufficient entropy for most use cases. Collision probability is astronomically low for practical applications.

⚠️ Seeded Generation Warning

The generateSeeded() function uses a seeded pseudo-random number generator (seedrandom library). This is NOT cryptographically secure and should only be used for:

  • Unit testing
  • Development and debugging
  • Demos and examples
  • Non-security sensitive applications

Never use seeded generation for:

  • Authentication tokens
  • Session IDs
  • Passwords
  • API keys
  • Any security-sensitive randomness

Examples

Token Generation

import ropes from 'ropes';

// API token
const apiToken = ropes.generate({ size: 64 });

// Session ID
const sessionId = ropes.generate({ 
  size: 32, 
  alphabet: ropes.alphabets.alphanumeric 
});

// Short ID
const shortId = ropes.generate({ size: 8 });

URL-Safe Tokens

// For URLs, use base64url alphabet
const urlToken = ropes.generate({ 
  size: 48, 
  alphabet: ropes.alphabets.base64url 
});
// Example: xY7jKmLpQrStUvWxYz1234567890AbCdEfGh

Formatted IDs

// UUID-like format
const uuidLike = ropes.generate({ 
  size: 32, 
  delimiter: '-', 
  chunkSize: 8 
});
// Example: abcdefgh-ijklmnop-qrstuvwx-yz012345

// Product key format
const productKey = ropes.generate({ 
  pattern: 'XXXX-XXXX-XXXX-XXXX' 
});
// Example: aBcD-EfGh-IjKl-MnOp

Bulk Operations

// Generate 100 tokens for a batch process
const tokens = ropes.generateMany(100, { 
  size: 32, 
  prefix: 'batch_' 
});

// Process asynchronously
const results = await Promise.all([
  ropes.generateAsync({ size: 16 }),
  ropes.generateAsync({ size: 16 }),
  ropes.generateAsync({ size: 16 })
]);

Testing with Seeded Generation

import { describe, it, expect } from 'vitest';
import ropes from 'ropes';

describe('token generation', () => {
  it('generates consistent tokens for testing', () => {
    const token1 = ropes.generateSeeded({ seed: 'test-1', size: 16 });
    const token2 = ropes.generateSeeded({ seed: 'test-1', size: 16 });
    
    expect(token1).toBe(token2);
    // Token will always be the same for seed 'test-1'
  });
});

Contributing

Contributions are welcome! Please open an issue or submit a pull request. Be sure that all your tests are all green.

License

MIT © Eduardo Velazco Romero