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

fetchflow-vm

v1.4.0

Published

A JavaScript execution environment that automatically pauses on fetch() calls, allows external HTTP processing, and resumes with injected responses

Readme

FetchFlow

npm version License: MIT

A JavaScript execution environment that automatically pauses on fetch() calls, allows external HTTP processing, and resumes with injected responses.

Features

  • Automatic Fetch Interception - Any fetch() call automatically pauses execution
  • State Persistence - Complete VM state serialization and restoration
  • External Processing - HTTP requests handled by separate processes
  • Seamless Resumption - Continue execution with injected fetch responses
  • Recursive Resumability - Resumed VMs can pause again on new fetch calls

Installation

npm install fetchflow

For Deno users:

import { executeCode, resumeExecution } from "npm:fetchflow";

API Reference

Types

interface ExecutionResult {
  type: 'completed' | 'paused';
  result?: any;              // Final result if completed
  state?: VMState;           // VM state if paused
  fetchRequest?: FetchRequest; // Fetch details if paused
}

interface VMState {
  id: string;
  code: string;
  variables: Record<string, any>;
  timestamp: number;
}

interface FetchRequest {
  id: string;
  url: string;
  options: {
    method?: string;
    headers?: Record<string, string>;
    body?: string;
  };
  timestamp: number;
}

interface FetchResponse {
  id: string;
  success: boolean;
  status: number;
  statusText: string;
  data?: any;
  error?: string;
  timestamp: number;
}

Functions

executeCode(code: string): Promise<ExecutionResult>

Execute JavaScript code. If a fetch() call is encountered:

  • Execution pauses immediately
  • Returns { type: 'paused', state, fetchRequest }

If no fetch calls or execution completes:

  • Returns { type: 'completed', result }

resumeExecution(state: VMState, fetchResponse: FetchResponse): Promise<ExecutionResult>

Resume execution with a fetch response:

  • Restores VM state
  • Injects fetch response as if the original fetch completed
  • Continues execution from where it paused
  • Can pause again if more fetch calls are encountered

Class Usage

import { FetchVM } from 'fetchflow';

const vm = new FetchVM();
await vm.initialize();

const result1 = await vm.execute(code);
if (result1.type === 'paused') {
  // Process fetch request externally
  const response = await processHttpRequest(result1.fetchRequest);

  const result2 = await vm.resume(result1.state!, response);
  // Continue as needed...
}

vm.dispose();

Example Usage

Basic Fetch Pause/Resume

import { executeCode, resumeExecution } from 'fetchflow';

// Execute code that makes a fetch call
const result = await executeCode(`
  let data = null;

  console.log("About to fetch...");
  const response = await fetch("https://api.example.com/data");
  data = await response.json();

  console.log("Fetch completed:", data);
  data;
`);

if (result.type === 'paused') {
  console.log("VM paused for fetch:", result.fetchRequest?.url);

  // Process the HTTP request externally
  const httpResponse = await fetch(result.fetchRequest!.url);
  const responseData = await httpResponse.json();

  const fetchResponse = {
    id: result.fetchRequest!.id,
    success: httpResponse.ok,
    status: httpResponse.status,
    statusText: httpResponse.statusText,
    data: responseData,
    timestamp: Date.now()
  };

  // Resume execution with the response
  const finalResult = await resumeExecution(result.state!, fetchResponse);
  console.log("Final result:", finalResult.result);
}

Multiple Fetch Calls

const result1 = await executeCode(`
  let posts = [];

  for (let i = 1; i <= 3; i++) {
    console.log("Fetching post", i);
    const response = await fetch(\`https://jsonplaceholder.typicode.com/posts/\${i}\`);
    const post = await response.json();
    posts.push(post);
  }

  posts;
`);

// This will pause at the first fetch
// Process it, resume, it will pause at second fetch
// Continue until all fetches are completed

With State Management

const vm = new FetchVM();
await vm.initialize();

let currentState = null;
let fetchQueue = [];

async function processStep(code: string) {
  const result = await vm.execute(code);

  if (result.type === 'paused') {
    currentState = result.state;
    fetchQueue.push(result.fetchRequest);
    return 'paused';
  }

  return result.result;
}

// Execute multiple steps
await processStep('let counter = 0;');
await processStep('counter++;');
const result = await processStep('fetch("https://api.example.com/data")');

if (result === 'paused') {
  // Process queued fetches...
}

Use Cases

  • Serverless Functions - Pause expensive operations across invocations
  • Web Scraping - Handle rate limiting by pausing between requests
  • Distributed Computing - Split long-running tasks across multiple workers
  • Debugging - Inspect state at any fetch call
  • Testing - Mock HTTP responses without changing application code
  • Workflow Orchestration - Coordinate complex multi-step processes

How It Works

  1. Fetch Interception: The library replaces the global fetch function with a custom implementation that throws a special error when called
  2. State Serialization: When a fetch is encountered, the entire VM state (variables, functions, execution context) is serialized
  3. External Processing: The HTTP request details are returned to the caller for external processing
  4. Response Injection: When resumed, the fetch response is injected as if the original fetch call completed normally
  5. Recursive Capability: Resumed VMs maintain fetch interception, enabling infinite pause/resume cycles

Requirements

  • Deno with --allow-read, --allow-write, --allow-net permissions
  • QuickJS Emscripten package

License

MIT