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

warpclock

v0.2.1

Published

Deterministic time engine for JavaScript async code

Readme

warpclock 🕐

Deterministic time engine for JavaScript async

Execute async code under a controlled virtual clock with deterministic execution order and record/replay capability.

Problem it solves

JavaScript async depends on:

  • System clock (not controllable)
  • Non-deterministic event loop
  • Non-reproducible timers
  • Global RNG without seed

This prevents:

  • Reproducing bugs
  • Flaky tests (random values)
  • Simulating long time intervals without waiting

warpclock defines a deterministic micro-runtime where time is a data value, not an external variable.


Implemented features

Core components (deterministic runtime)

1. VirtualClock

Virtual monotonic clock that replaces Date.now() and performance.now().

const clock = new VirtualClock(0);
console.log(clock.now());        // 0
clock.advanceBy(1000);
console.log(clock.now());        // 1000
clock.advanceTo(5000);
console.log(clock.now());        // 5000

API:

  • now(): number - Get current time
  • advanceBy(ms: number): void - Advance time
  • advanceTo(ts: number): void - Advance to specific timestamp
  • reset(time?: number): void - Reset the clock

2. DeterministicScheduler

Executes tasks in total deterministic order.

Model:

interface Task {
  id: number        // incremental
  time: number      // virtual timestamp
  type: "micro" | "macro"
  callback: () => any
}

Execution order:

  1. Lower timestamp
  2. Microtasks before macrotasks
  3. Lower ID

API:

  • scheduleTask(time, callback, type): number - Schedule task
  • executeAll(): Promise<void> - Execute all tasks
  • executeUntilTime(time): Promise<void> - Execute until specific time

3. TimerManager

Implements setTimeout, setInterval, clearTimeout, clearInterval without using system clock.

const timers = new TimerManager(scheduler, clock);

const id1 = timers.setTimeout(() => {
  console.log("A");
}, 1000);

const id2 = timers.setInterval(() => {
  console.log("B");
}, 500);

timers.clearTimeout(id1);
timers.clearInterval(id2);

4. ExecutionContext

Container with clock, scheduler, timers, rng and trace. Provides isolated API to the user.

const ctx = new ExecutionContext({
  initialTime: 0,
  seed: 42,
  recordTrace: false
});

ctx.clock.now()              // 0
ctx.random()                 // [0-1) deterministic
await ctx.sleep(500)         // Advances clock virtually
await ctx.advanceBy(1000)    // Advances clock + executes tasks

5. Sleep primitive

Promise that resolves after ms of virtual time.

await ctx.sleep(1000);  // Advances 1000ms virtually
console.log(ctx.clock.now());  // 1000

Public API

warp() - Main API

Execute async code inside the deterministic engine.

import { warp } from "warpclock";

await warp(async (ctx) => {
  // Everything here uses the virtual clock
  
  // Virtual timers
  ctx.timers.setTimeout(() => {
    console.log("1000ms virtual time passed");
  }, 1000);
  
  // Virtual sleep
  await ctx.sleep(500);
  console.log("500ms virtual time passed");
  
  // Deterministic RNG
  const random = ctx.random();  // 0-1
  
  // Advance time manually
  await ctx.advanceBy(2000);
  
  // Execute all pending tasks
  await ctx.executeAll();
}, {
  initialTime: 0,
  seed: 42
});

Configuration:

interface ExecutionContextConfig {
  initialTime?: number;  // Initial clock time
  seed?: number;         // Seed for RNG
  recordTrace?: boolean; // Record events
}

6. SeededRNG

Deterministic PRNG (xorshift32) that replaces Math.random().

const rng = new SeededRNG(42);
rng.random();      // Same value with seed=42
rng.setSeed(42);
rng.random();      // Same value again

7. TraceRecorder (v1 simple)

Records execution events to validate determinism.

ctx.trace.exportTrace();  // Array of TraceEvent[]

Format:

interface TraceEvent {
  type: "schedule" | "execute"
  taskId: number
  time: number
  taskType?: "micro" | "macro"
  meta?: Record<string, any>
}

Usage examples

Determinism: same seed = same result

const result1: string[] = [];
await warp(async (ctx) => {
  for (let i = 0; i < 5; i++) {
    result1.push(ctx.random().toFixed(2));
  }
}, { seed: 42 });

const result2: string[] = [];
await warp(async (ctx) => {
  for (let i = 0; i < 5; i++) {
    result2.push(ctx.random().toFixed(2));
  }
}, { seed: 42 });

console.log(result1 === result2);  // true

Debugging & validation (implemented)

Tools for tracing, determinism checks, debugging, and profiling:

  • TraceReplayer: validate/format/compare traces.
  • DeterminismValidator: assert deterministic or non-deterministic behavior across seeds/configs.
  • Debugger: snapshots, timeline visualization, pending tasks, summaries, pattern analysis.
  • Profiler: performance stats, reports, bottleneck hints.

Example (timeline + replay + determinism):

import { warp, TraceReplayer, DeterminismValidator, Debugger } from "warpclock";

const ctx = await warp(async (c) => {
  c.timers.setTimeout(() => {}, 10);
  c.timers.setTimeout(() => {}, 50);
  await c.executeAll();
  return c;
}, { seed: 123, recordTrace: true });

const dbg = new Debugger(ctx);
console.log(dbg.visualizeTimeline());

const replay = await TraceReplayer.validateReplay(async (c) => {
  c.timers.setTimeout(() => {}, 10);
  c.timers.setTimeout(() => {}, 50);
  await c.executeAll();
}, 123);
console.log(replay.valid); // true

const det = await DeterminismValidator.assertDeterministic(async (c) => {
  const out: number[] = [];
  out.push(c.random());
  out.push(c.random());
  return out;
}, 5, 123);
console.log(det.isDeterministic); // true

Flake-free timers

await warp(async (ctx) => {
  const order: string[] = [];
  
  ctx.timers.setTimeout(() => order.push("A"), 100);
  ctx.timers.setTimeout(() => order.push("B"), 50);
  ctx.timers.setTimeout(() => order.push("C"), 150);
  
  await ctx.executeAll();
  
  console.log(order);  // ["B", "A", "C"] - ALWAYS
});

Long time simulation

await warp(async (ctx) => {
  // Simulate 1 year (365 days) in real milliseconds
  const oneYear = 365 * 24 * 60 * 60 * 1000;
  
  const startTime = ctx.clock.now();
  await ctx.advanceTo(startTime + oneYear);
  
  // All time operations completed in ms real time
  console.log("1 year simulated in milliseconds");
});

Testing async without flakes

test("should process events in order", async () => {
  const processed: number[] = [];
  
  await warp(async (ctx) => {
    ctx.timers.setTimeout(() => processed.push(1), 100);
    ctx.timers.setTimeout(() => processed.push(2), 50);
    
    await ctx.executeAll();
  }, { seed: 123 });
  
  expect(processed).toEqual([2, 1]);  // Never fails
});

Architecture

warpclock/
├── src/
│   ├── VirtualClock.ts          # Virtual monotonic clock
│   ├── DeterministicScheduler.ts # Ordered task scheduler
│   ├── TimerManager.ts           # setTimeout/setInterval
│   ├── SeededRNG.ts              # Deterministic PRNG
│   ├── TraceRecorder.ts          # Event recording
│   ├── ExecutionContext.ts       # Main container
│   ├── index.ts                  # Public API
│   └── __tests__/
│       ├── VirtualClock.test.ts
│       ├── DeterministicScheduler.test.ts
│       ├── warp.test.ts
│       └── milestone3.test.ts
├── package.json
├── tsconfig.json
├── jest.config.js
└── README.md

Design principles

Total determinism: same seed + same code → same order and result
No global monkey-patching: everything is isolated by default
Explicit scope: user runs code inside warp()
Small core: timers, scheduler, sleep, RNG
Clear boundaries: real IO (fetch, fs) stays out


What it does NOT do

  • ❌ Simulate Node.js or browser
  • ❌ Automatic global monkey-patching
  • ❌ fetch, fs, network IO
  • ❌ Cryptographic determinism
  • ❌ UI/DOM
  • ❌ Plugins

Testing

npm test              # Run tests
npm test -- --watch  # Watch mode
npm run build         # Compile TypeScript
npm run dev          # Watch compilation

Current coverage:

Future work

  • Advanced trace replay with time warping
  • Capture/replay of promises
  • Statistical determinism testing
  • Integration with testing frameworks

Support

If warpclock helps you, you can support its development:

  • GitHub Sponsors: https://github.com/sponsors/ne07hekin6
  • Ko-fi: https://ko-fi.com/ne07hekin6

License

MIT

Author: Leandro Gaurisse


Philosophy

"This project does not simulate Node or browser. It defines a deterministic micro-runtime where time is a data value, not an external variable."

The goal is to provide a simple and powerful way to:

  1. Reproduce bugs exactly
  2. Test async without flakiness
  3. Simulate time intervals without waiting
  4. Guarantee deterministic execution order

All within an explicit and controlled scope.