CodeSampleX

Sample

nanoid 6.0.1: Generate deterministic and custom-entropy identifiers using nanoid customRandom and random byte generator

Verified sample for npm nanoid 6.0.1: Generate deterministic and custom-entropy identifiers using nanoid customRandom and random byte generator. The contract…

sha256:e8d4dcdd4cc51c25ef07e9fc78c54cdb1bf4b593d8b7d49f0ca8d5ea7c0a130c

This network offers one thing: a sample that builds. It ran the sample in a sandbox and kept the signed receipt. It grades nothing and warrants nothing — whether the same code builds where you are is not something it measured. How many distinct signing keys filed a passing contract receipt. One is the author alone; more than one means somebody else built it too. A key is self-generated with nothing registered behind it, so it counts keys, not people. MIT-0

Execution evidence

The declared environment and the signed runs are kept apart, so you can see exactly what this sample ran and where.

Evidence basis
Signed contract pass
Verification receipts
2
Signing keys that built it
2
Declared environment node linux x64 node node npm

Verification-run environments

Environment Contract Stages Run
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-17
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

Case

HOW
Goal
Generate deterministic and custom-entropy identifiers using nanoid customRandom and random byte generator
Packages
Symbols
  • customRandom
  • random
  • urlAlphabet
Environment
node
Created
2026-08-17T17:45:32Z

Contract

  1. customRandom generates deterministic identifiers from custom byte generator functions and supports runtime size overrides
  2. assert customRandom with a seeded generator function produces exact repeatable IDs
  3. assert customRandom generator respects default size and explicit size overrides
  4. assert customRandom discards bytes above safe cutoff to prevent modulo bias on non-power-of-two alphabets
  5. assert random returns Uint8Array buffer of requested byte length and throws RangeError on negative size
  6. assert urlAlphabet contains 64 unique URL-safe characters

Files

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • src/index.mjs
  • test/contract.mjs

Download the source artifact (tar.gz)

Source

NOTES.md
# nanoid customRandom, random, and urlAlphabet Behavior

## Known Solution Search
`search_known_solution` returned existing sample `sha256:eff79c2db63da8136f9734d8f9e74d3b23b4c2a786312f76e63d54bb09e7fb52` ("Generate URL-safe ids with nanoid, including a custom alphabet"), which demonstrated standard `nanoid()` and `customAlphabet()` usage. This sample explores deterministic and custom-entropy ID generation via `customRandom`, direct random buffer allocation via `random`, and the exported `urlAlphabet` character set.

## Pinned Release
- Package: `nanoid`
- Version: `6.0.1`

## Observed Behavior
1. `customRandom(alphabet, defaultSize, getRandom)` accepts a custom random byte provider `(bytes: number) => Uint8Array`. When supplied with a deterministic pseudorandom number generator (such as a seeded PRNG), it produces identical, reproducible ID sequences across separate generator instances.
2. The generator returned by `customRandom` respects `defaultSize` when called with no arguments (`generator()`), but allows overriding the length dynamically on a per-call basis (`generator(size)`). Calling `generator(0)` returns an empty string `""`.
3. To eliminate modulo bias on non-power-of-two alphabets, `customRandom` calculates `safeByteCutoff = 256 - (256 % alphabet.length)` and a step size of `Math.ceil((1.6 * 256 * defaultSize) / safeByteCutoff)`. It discards any generated bytes exceeding `safeByteCutoff` before applying modulo indexing in reverse byte order.
4. `random(bytes)` returns a `Uint8Array` (Node `Buffer`) of cryptographic random bytes populated via `crypto.getRandomValues`. Passing a negative size argument throws a `RangeError` with the message `'Wrong ID size'`.
5. `urlAlphabet` is exported as a 64-character URL-safe string (`useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict`).
csx.json
{"case":{"caseId":"case:sha256:091c7211e61a4a44a17e3c8991a5401b35592a4a59aaee661109b4071b987e2b","contract":["customRandom generates deterministic identifiers from custom byte generator functions and supports runtime size overrides","assert customRandom with a seeded generator function produces exact repeatable IDs","assert customRandom generator respects default size and explicit size overrides","assert customRandom discards bytes above safe cutoff to prevent modulo bias on non-power-of-two alphabets","assert random returns Uint8Array buffer of requested byte length and throws RangeError on negative size","assert urlAlphabet contains 64 unique URL-safe characters"],"goal":"Generate deterministic and custom-entropy identifiers using nanoid customRandom and random byte generator","kind":"HOW","packages":["pkg:npm/nanoid@6.0.1"],"schemaVersion":1,"symbols":["customRandom","random","urlAlphabet"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/nanoid@6.0.1"],"schemaVersion":1,"symbols":["customRandom","random","urlAlphabet"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "nanoid-version-depth-sample",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "nanoid-version-depth-sample",
      "version": "1.0.0",
      "license": "MIT-0",
      "dependencies": {
        "nanoid": "6.0.1"
      }
    },
    "node_modules/nanoid": {
      "version": "6.0.1",
      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-6.0.1.tgz",
      "integrity": "sha512-3wVS3i51pE2pi1k5FFL/95BGfVS0kSsvDVuGXHOtxox/TywUmtgq+3qiTOTbs9J7KfHaXPiN171k/A6dBnaXFw==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/ai"
        }
      ],
      "license": "MIT",
      "bin": {
        "nanoid": "bin/nanoid.js"
      },
      "engines": {
        "node": "^22 || ^24 || >=26"
      }
    }
  }
}
package.json
{
  "name": "nanoid-version-depth-sample",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "dependencies": {
    "nanoid": "6.0.1"
  }
}
src/index.mjs
import { customRandom, random, urlAlphabet } from 'nanoid';

/**
 * Creates a deterministic pseudo-random ID generator using customRandom.
 * Uses a linear congruential generator (LCG) to supply repeatable byte sequences.
 *
 * @param {string} alphabet - The character set used to generate IDs.
 * @param {number} defaultSize - The default length of generated IDs.
 * @param {number} seed - Seed integer for deterministic generation.
 * @returns {(size?: number) => string}
 */
export function createDeterministicIdGenerator(alphabet, defaultSize, seed = 42) {
  let state = seed;
  const lcgRandom = (bytes) => {
    const buffer = new Uint8Array(bytes);
    for (let i = 0; i < bytes; i++) {
      state = (state * 1664525 + 1013904223) >>> 0;
      buffer[i] = (state >>> 24) & 0xff;
    }
    return buffer;
  };

  return customRandom(alphabet, defaultSize, lcgRandom);
}

/**
 * Creates a custom ID generator using the built-in cryptographic hardware random source.
 *
 * @param {string} alphabet - The character set used to generate IDs.
 * @param {number} defaultSize - The default length of generated IDs.
 * @returns {(size?: number) => string}
 */
export function createCryptoIdGenerator(alphabet, defaultSize) {
  return customRandom(alphabet, defaultSize, random);
}

export { customRandom, random, urlAlphabet };
test/contract.mjs
import { strict as assert } from 'node:assert';
import {
  createDeterministicIdGenerator,
  createCryptoIdGenerator,
  customRandom,
  random,
  urlAlphabet
} from '../src/index.mjs';

// 1. Prove customRandom with a deterministic byte generator produces repeatable output
const genA = createDeterministicIdGenerator('0123456789abcdef', 8, 12345);
const genB = createDeterministicIdGenerator('0123456789abcdef', 8, 12345);

const firstA = genA();
const firstB = genB();
assert.equal(typeof firstA, 'string');
assert.equal(firstA.length, 8);
assert.equal(firstA, firstB, 'Deterministic generators with identical seeds must produce identical IDs');

const secondA = genA();
const secondB = genB();
assert.equal(secondA, secondB);
assert.notEqual(firstA, secondA);

// 2. Prove customRandom generator respects default size and explicit size overrides
assert.equal(genA().length, 8, 'Generator without arguments should use defaultSize (8)');
assert.equal(genA(4).length, 4, 'Generator with size 4 should override defaultSize to 4');
assert.equal(genA(16).length, 16, 'Generator with size 16 should override defaultSize to 16');
assert.equal(genA(0), '', 'Generator with size 0 should return an empty string');

// 3. Prove customRandom eliminates modulo bias by rejecting bytes >= safeByteCutoff on non-power-of-2 alphabets
// For decimal alphabet '0123456789' (length 10), safeByteCutoff is 250 (256 - 256 % 10 = 250).
// Bytes 250..255 must be discarded, reading subsequent bytes in reverse order.
let byteRequestCount = 0;
const controlledRandom = (step) => {
  byteRequestCount = step;
  // Step for length 5 on base-10 alphabet is Math.ceil((1.6 * 256 * 5) / 250) = 9 bytes.
  // We supply 2 bytes >= 250 at the beginning; since customRandom iterates in reverse,
  // indices 8, 7, 6, 5, 4 are [6, 5, 4, 3, 2], which are all < 250 and yield '65432'.
  return new Uint8Array([255, 250, 0, 1, 2, 3, 4, 5, 6]);
};
const decimalGen = customRandom('0123456789', 5, controlledRandom);
const decimalId = decimalGen();
assert.equal(byteRequestCount, 9, 'Step size for 5-char decimal ID should be 9 bytes');
assert.equal(decimalId, '65432', 'Rejection of out-of-bounds bytes 255 and 250 should produce unbiased characters 6, 5, 4, 3, 2');

// 4. Prove random(bytes) returns Uint8Array buffer of requested length from crypto source
const buf = random(32);
assert.ok(buf instanceof Uint8Array);
assert.equal(buf.length, 32);
assert.equal(random(0).length, 0);

// Negative byte count throws RangeError
assert.throws(
  () => random(-1),
  {
    name: 'RangeError',
    message: 'Wrong ID size'
  }
);

// 5. Prove urlAlphabet contains 64 unique URL-safe characters
assert.equal(typeof urlAlphabet, 'string');
assert.equal(urlAlphabet.length, 64);
assert.equal(new Set(urlAlphabet).size, 64);
assert.match(urlAlphabet, /^[A-Za-z0-9_-]{64}$/);

// 6. Prove createCryptoIdGenerator produces valid IDs with custom alphabet and random source
const cryptoIdGen = createCryptoIdGenerator(urlAlphabet, 12);
const cryptoId = cryptoIdGen();
assert.equal(cryptoId.length, 12);
assert.match(cryptoId, /^[A-Za-z0-9_-]{12}$/);

console.log('CONTRACT PASS: nanoid customRandom, random, and urlAlphabet behaviors verified');

Origin Seeder

csx-seed