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

cf-api-sim

v0.1.0

Published

Local Cloudflare REST API simulator — mock the /client/v4 surface (D1, R2, KV, Workers Scripts) on your laptop, backed by SQLite + the filesystem. Point any Cloudflare SDK, wrangler, or REST client at it via CLOUDFLARE_API_BASE_URL.

Readme

cf-api-sim

A local simulator of the Cloudflare REST API (/client/v4). Run D1, R2, KV, Workers Scripts and the GraphQL analytics endpoint on your own machine — point any Cloudflare SDK, wrangler, or raw REST client at it for fast, offline local development and integration tests. No Cloudflare account, no network, no quotas.

If you've ever wanted a Cloudflare API mock for testing — a local D1/R2/KV emulator that speaks the real REST shapes, lets you run wrangler offline against fake resources, or exercise your client's retry and error-handling paths deterministically — that's what this is.


What it covers

cf-api-sim implements the commonly-used subset of the Cloudflare REST API surface:

  • D1 — create / list / get / delete databases; POST /query (single statement, results-as-objects), batch queries (array body, run atomically in one transaction), and POST /raw (results-as-2D-array). Backed by a real per-database SQLite file, so your SQL actually runs.
  • R2 — create / list / get / delete buckets; object PUT / GET / DELETE / list; bucket lifecycle get/set; plus an S3-compatible endpoint (/<bucket>/<key>, ?list-type=2) so S3 clients can read and write objects.
  • KV — create / list / rename / delete namespaces; get / put / delete values (raw bytes, with metadata and expiration); list keys with prefix + cursor pagination; and bulk/get, bulk PUT, bulk DELETE.
  • Workers Scripts — upload (PUT /scripts/:name, multipart), get (JSON or multipart round-trip), service existence check, and delete.
  • GraphQL analyticsPOST /client/v4/graphql returns shape-valid empty aggregates, so "no data yet" rendering paths in your app still exercise cleanly.
  • Fault injection — arm canned error responses and artificial delays on specific routes so you can test client retry and error handling deterministically (see Fault injection).

State is persisted on disk: a control-plane SQLite database for metadata, one SQLite file per simulated D1 database (via better-sqlite3), and R2 objects on the filesystem. No real Cloudflare account or network is involved.


Quick start

npx cf-api-sim

That's it. The simulator binds to http://127.0.0.1:8745 (loopback only) and prints its health URL on startup:

[cf-api-sim] listening on http://127.0.0.1:8745
[cf-api-sim] data dir: ./data
[cf-api-sim] health:   http://127.0.0.1:8745/sim/health

Check it's up:

curl http://127.0.0.1:8745/sim/health
# { "ok": true, "name": "cf-api-sim", "version": "...", ... }

Install as a dev dependency in your project:

npm i -D cf-api-sim

Configuration

| Env var | Default | Description | | -------------- | -------- | -------------------------------------------- | | SIM_PORT | 8745 | Port to listen on. | | SIM_DATA_DIR | ./data | Directory for persisted control DB, D1 files, and R2 objects. |

SIM_PORT=9000 SIM_DATA_DIR=/tmp/cf-sim npx cf-api-sim

Pointing a client at the simulator

Auth is shape-only — the simulator accepts any non-empty bearer token. Use any account ID you like; one default account (dev-acct) is always present.

Cloudflare SDK (cloudflare)

The official cloudflare SDK accepts a baseURL option:

import Cloudflare from "cloudflare";

const client = new Cloudflare({
  apiToken: "any-non-empty-string",
  baseURL: "http://127.0.0.1:8745/client/v4",
});

const dbs = await client.d1.database.list({ account_id: "dev-acct" });

Environment variable

Many tools (and the SDK) read CLOUDFLARE_API_BASE_URL:

export CLOUDFLARE_API_BASE_URL=http://127.0.0.1:8745/client/v4
export CLOUDFLARE_API_TOKEN=any-non-empty-string

Raw REST

curl -X POST http://127.0.0.1:8745/client/v4/accounts/dev-acct/d1/database \
  -H "Authorization: Bearer dev-token" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-db"}'

S3-compatible R2 endpoint

S3 clients can talk to R2 objects directly at http://127.0.0.1:8745/<bucket>/<key>. The account ID is taken from the Host header (canonical <account>.r2.cloudflarestorage.com shape) or from an x-sim-account-id header for clients that can't set a custom host (e.g. curl). A SigV4-shaped Authorization header is required, but the signature is not verified (see Limitations & security).


Fault injection (for tests)

The /sim/* control endpoints let you make the simulator misbehave on demand — perfect for testing how your client handles errors, timeouts, and retries. They require no auth and are never themselves affected by injected faults.

| Endpoint | Method | Purpose | | --------------------- | ------ | ------------------------------------------------------------- | | /sim/health | GET | Liveness check. | | /sim/fail-next | POST | Arm a canned status response for the next matching request. | | /sim/delay-next | POST | Arm an artificial delay (no status override) for the next match.| | /sim/reset | POST | Clear all armed faults and the call log. | | /sim/calls | GET | Inspect the recent request log. | | /sim/faults | GET | Inspect the armed-fault queue. |

Make the next D1 create return a 500:

curl -X POST http://127.0.0.1:8745/sim/fail-next \
  -H "Content-Type: application/json" \
  -d '{"method":"POST","path":"/client/v4/accounts/dev-acct/d1/database","status":500}'

fail-next accepts method, path, status (required), plus optional body, contentType, count (how many requests to affect, default 1), and delayMs. delay-next accepts method, path, delayMs (required), plus optional count.

Reset between test cases:

curl -X POST http://127.0.0.1:8745/sim/reset

Limitations & security

cf-api-sim is a development and testing tool. It is intentionally not a faithful or secure reproduction of Cloudflare.

  • Loopback only. The server binds to 127.0.0.1. Do not expose it to a network or run it on a shared/public host.
  • No real authentication. The data plane accepts any non-empty bearer token — there are no real accounts, tokens, or permissions behind it. The S3 endpoint trusts the x-sim-account-id header and the shape of a SigV4 Authorization header without verifying the signature. This is not an auth or permissions simulator — anyone who can reach the port has full access, which is exactly why it must stay on loopback.
  • No request-body size limits. Don't point untrusted input at it.
  • Partial API surface. It implements the commonly-used subset of each API, not the full Cloudflare surface. Unimplemented endpoints return a 501 with a clear "not implemented" message so you can tell sim gaps from real failures.
  • Persistent state. Resources, values, and objects persist under the data directory between runs. Delete it (or point SIM_DATA_DIR at a temp dir) for a clean slate.

See SECURITY.md for the security posture and reporting details.


Related projects

  • cf-wfp-simulator — a sibling project: a local simulator for Cloudflare Workers for Platforms (dispatch namespaces / tenant workers).
  • teenybase — the project these simulators came from: backend-as-config on Cloudflare Workers + D1.

Contributing

Contributions are welcome — see CONTRIBUTING.md for local setup, testing, and PR conventions.

License

Apache-2.0 © Palash Bansal <[email protected]>


Suggested GitHub topics: cloudflare · d1 · r2 · kv · workers · simulator · mock · testing · local-development

Keywords: Cloudflare API mock, Cloudflare REST API simulator, local D1 emulator, R2 emulator, KV emulator, wrangler offline, Cloudflare integration testing.