πŸ”₯ Miniflare is a simulator for developing and testing Cloudflare Workers.

Overview

πŸ”₯ Miniflare

Miniflare is a simulator for developing and testing Cloudflare Workers.

  • πŸŽ‰ Fun: develop workers easily with detailed logging, file watching and pretty error pages supporting source maps.
  • πŸ”‹ Full-featured: supports most Workers features, including KV, Durable Objects, WebSockets, modules and more.
  • ⚑ Fully-local: test and develop Workers without an internet connection. Reload code on change quickly.

It's an alternative to wrangler dev, written in TypeScript, that runs your workers in a sandbox implementing Workers' runtime APIs.

See https://miniflare.dev for more detailed documentation.

Features

  • πŸ“¨ Fetch Events (with HTTP(S) server and manual dispatch)
  • ⏰ Scheduled Events (with cron triggering and manual dispatch)
  • πŸ”‘ Variables and Secrets with .env Files
  • πŸ“š Modules Support
  • πŸ“¦ KV (with optional persistence)
  • ✨ Cache (with optional persistence)
  • πŸ“Œ Durable Objects (with optional persistence)
  • 🌐 Workers Sites
  • βœ‰οΈ WebSockets
  • πŸ›  Custom & Wrangler Builds Support
  • βš™οΈ WebAssembly Support
  • πŸ—Ί Source Map Support
  • πŸ•Έ Web Standards: Base64, Timers, Fetch, Encoding, URL, Streams, Crypto
  • πŸ“„ HTMLRewriter
  • πŸ‘€ Automatic Reload on File Changes
  • πŸ’ͺ Written in TypeScript

Install

Miniflare is installed using npm:

$ npm install -g miniflare # either globally..
$ npm install -D miniflare # ...or as a dev dependency

Using the CLI

$ miniflare worker.js --watch --debug
[mf:dbg] Options:
[mf:dbg] - Scripts: worker.js
[mf:dbg] Reloading worker.js...
[mf:inf] Worker reloaded! (97B)
[mf:dbg] Watching .env, package.json, worker.js, wrangler.toml...
[mf:inf] Listening on :8787
[mf:inf] - http://127.0.0.1:8787

Using the API

{ event.respondWith(new Response("Hello Miniflare!")); }); `, }); const res = await mf.dispatchFetch("http://localhost:8787/"); console.log(await res.text()); // Hello Miniflare! ">
import { Miniflare } from "miniflare";

const mf = new Miniflare({
  script: `
  addEventListener("fetch", (event) => {
    event.respondWith(new Response("Hello Miniflare!"));
  });
  `,
});
const res = await mf.dispatchFetch("http://localhost:8787/");
console.log(await res.text()); // Hello Miniflare!

CLI Reference

Usage: miniflare [script] [options]

Options:
  -h, --help              Show help                                    [boolean]
  -v, --version           Show version number                          [boolean]
  -H, --host              HTTP server host to listen on (all by default)[string]
  -p, --port              HTTP server port (8787 by default)            [number]
  -d, --debug             Log debug messages                           [boolean]
  -c, --wrangler-config   Path to wrangler.toml                         [string]
      --wrangler-env      Environment in wrangler.toml to use           [string]
      --package           Path to package.json                          [string]
  -m, --modules           Enable modules                               [boolean]
      --modules-rule      Modules import rule (TYPE=GLOB)                [array]
      --build-command     Command to build project                      [string]
      --build-base-path   Working directory for build command           [string]
      --build-watch-path  Directory to watch for rebuilding on changes  [string]
  -w, --watch             Watch files for changes                      [boolean]
  -u, --upstream          URL of upstream origin                        [string]
  -t, --cron              Cron pattern to trigger scheduled events with  [array]
  -k, --kv                KV namespace to bind                           [array]
      --kv-persist        Path to persist KV data to (omit path for default)
      --cache-persist     Path to persist cached data to (omit path for default)
      --disable-cache     Disable caching with default/named caches    [boolean]
  -s, --site              Path to serve Workers Site files from         [string]
      --site-include      Glob pattern of site files to serve            [array]
      --site-exclude      Glob pattern of site files not to serve        [array]
  -o, --do                Durable Object to bind (NAME=CLASS)            [array]
      --do-persist        Path to persist Durable Object data to (omit path for
                          default)
  -e, --env               Path to .env file                             [string]
  -b, --binding           Bind variable/secret (KEY=VALUE)               [array]
      --wasm              WASM module to bind (NAME=PATH)                [array]
      --https             Enable self-signed HTTPS
      --https-key         Path to PEM SSL key                           [string]
      --https-cert        Path to PEM SSL cert chain                    [string]
      --https-ca          Path to SSL trusted CA certs                  [string]
      --https-pfx         Path to PFX/PKCS12 SSL key/cert chain         [string]
      --https-passphrase  Passphrase to decrypt SSL files               [string]
      --disable-updater   Disable update checker                       [boolean]

Acknowledgements

Many thanks to dollarshaveclub/cloudworker and gja/cloudflare-worker-local for inspiration.

Durable Object's transactions are implemented using Optimistic Concurrency Control (OCC) as described in "On optimistic methods for concurrency control." ACM Transactions on Database Systems. Thanks to Alistair O'Brien for helping me understand this.

Comments
  • GET request body failing to parse

    GET request body failing to parse

    With an API we are building on Cloudflare Workers we support setting a body on a GET request. It works when it's deployed on a Cloudflare Worker, however we don't get any response from await event.request.json() with miniflare.

    Thanks for building this awesome tool!

    fixed-in-next 
    opened by jonathannorris 32
  • API mocking with MSW fails after upgrade to miniflare 2.2.0

    API mocking with MSW fails after upgrade to miniflare 2.2.0

    Hey @mrbbot, thanks for all the work on miniflare, it's been a game-changer! With miniflare 1, I've been using mock service worker to mock API responses. When attempting to upgrade to miniflare 2.2.0, my tests failed. I've no idea where to start looking for a solution, so I've put up a fairly minimal demo, hoping that'll make it easier to pinpoint the cause. HEAD is using miniflare 2.2.0, while the miniflare-1.4.1 branch shows what it looks like when it's working. Running npm test should show failing tests for HEAD and passing for the latter.

    dependency 
    opened by fbarthez 19
  • Failed to parse URL from [object Object]

    Failed to parse URL from [object Object]

    I just tried to upgrade to v2 and hit /, which I have mapped to a 404 (but any of my previously working endpoints fail as well). I have no idea why this is failing now.

    My code is dead simple:

    2022-01-07 12-06-07

    The error is:

    2022-01-07 12-02-55

    Seems like there are two bits here... a problem with miniflare and giving feedback to your upstream dependency undici to display a more helpful error than trying to blindly concat a string and an object.

    bug 
    opened by lookfirst 16
  • Error: The first argument must be of type string or an instance of Buffer. Received an instance of Uint8Array

    Error: The first argument must be of type string or an instance of Buffer. Received an instance of Uint8Array

    Getting the error "The first argument must be of type string or an instance of Buffer. Received an instance of Uint8Array"

    worker.js: addEventListener("fetch", (event) => { event.respondWith(new Response("Hello Miniflare!")); });

    running: npx miniflare worker.js

    opened by elmarw 13
  • Unexpected token 'export' when using `@aws-sdk` with Jest

    Unexpected token 'export' when using `@aws-sdk` with Jest

    I have created a new worker using npx wrangler init with typescript. I am using the @aws-sdk/client-eventbridge package in my worker. However, when I try and mock it in tests using aws-sdk-client-mock I get the following error.

    .../node_modules/uuid/dist/esm-browser/index.js:1
        ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
    

    This appears to be an ES module issue and only occurs when I have new EventBridgeClient({}) in my test code.

    My jest config looks like this.

    module.exports = {
      preset: 'ts-jest',
      testEnvironment: 'miniflare',
    };
    

    If I change testEnvironment to node, the error no longer occurs and the test will pass. However, I loose the miniflare benefits in jest.

    Is there something I'm missing here to get this working with the miniflare test environment?

    question 
    opened by swelham 11
  • Wrangler 2 routes property ([mf:err] TypeError: Invalid URL)

    Wrangler 2 routes property ([mf:err] TypeError: Invalid URL)

    With wrangler 2 the route property is like;

    route = { pattern = "https://example.com/*", zone_id = "<ignored>"}

    thus this following line fails with like http://[object Object];

    [mf:err] TypeError: Invalid URL

    https://github.com/cloudflare/miniflare/blob/98b9d697775ac843ce77eef088dfe655188bc77c/packages/core/src/router.ts#L31-L33

    bug quick win 
    opened by maraisr 11
  • Request Object doesn't contains all properties

    Request Object doesn't contains all properties

    When I am using MiniflareI see the Request Object doesn't contain the same properties that are described in theCloudflare documentation That is annoying because that means code that works in live and with wrangler is not working with Miniflare

    With Miniflare

    Request Object direct endpoint:  {
     	"size": 0,
     	"timeout": 0,
     	"follow": 20,
     	"compress": true,
     	"counter": 0,
     	"query": {}
     }
    Request Object inside Durable Object : {
     	"size": 0,
     	"timeout": 0,
     	"follow": 20,
     	"compress": true,
     	"counter": 0
     }
    

    With wrangler dev

    Request Object direct endpoint: {
    	"cf": {
    		"clientTcpRtt": 25,
    		"longitude": "******",
    		"latitude": "******",
    		"tlsCipher": "ECDHE-ECDSA-AES128-GCM-SHA256",
    		"continent": "**",
    		"asn": ** ,
    		"clientAcceptEncoding": "gzip",
    		"country": "***",
    		"isEUCountry": "*",
    		"tlsClientAuth": {
    			"certIssuerDNLegacy": "",
    			"certIssuerSKI": "",
    			"certSubjectDNRFC2253": "",
    			"certSubjectDNLegacy": "",
    			"certFingerprintSHA256": "",
    			"certNotBefore": "",
    			"certSKI": "",
    			"certSerial": "",
    			"certIssuerDN": "",
    			"certVerified": "NONE",
    			"certNotAfter": "",
    			"certSubjectDN": "",
    			"certPresented": "0",
    			"certRevoked": "0",
    			"certIssuerSerial": "",
    			"certIssuerDNRFC2253": "",
    			"certFingerprintSHA1": ""
    		},
    		"tlsExportedAuthenticator": {
    			"clientFinished": "****",
    			"clientHandshake": "****",
    			"serverHandshake": "*****",
    			"serverFinished": "******"
    		},
    		"tlsVersion": "TLSv1.2",
    		"colo": "BCN",
    		"timezone": "****/***",
    		"city": "***",
    		"edgeRequestKeepAliveStatus": 1,
    		"requestPriority": "",
    		"httpProtocol": "HTTP/1.1",
    		"region": "***",
    		"regionCode": "**",
    		"asOrganization": "*** ***",
    		"postalCode": "***-**"
    	},
    	"signal": {
    		"aborted": false
    	},
    	"fetcher": {},
    	"redirect": "manual",
    	"headers": {},
    	"url": "https://********/api/rooms",
    	"method": "GET",
    	"bodyUsed": false,
    	"body": null,
    	"query": {}
    }
    Script modified; context reset.
    Request Object: {
     	"signal": {
     		"aborted": false
     	},
     	"fetcher": {},
     	"redirect": "manual",
     	"headers": {},
     	"url": "https://fake-host/",
     	"method": "GET",
     	"bodyUsed": false,
     	"body": null
     }
    
    opened by Moser-ss 11
  • wranglerConfigEnv not picking up env specific bindings on Jest@28

    wranglerConfigEnv not picking up env specific bindings on Jest@28

    Hey @mrbbot,

    It looks like in the latest version of miniflare wranglerConfigEnv is not adding bindings to the global getMiniflareBindings.

    wrangler.toml

    [[env.dev.kv_namespaces]]
    binding = "KEY_VALUE_STORE"
    preview_id = "unused"
    id = "unused"
    

    jest.config.json

    {
      "testEnvironment": "miniflare",
      "testEnvironmentOptions": {
        "wranglerConfigEnv": "dev"
      }
    }
    

    test

    console.log(getMiniflareBindings()) // {}
    

    However if I add a binding to the global env of the wrangler.toml it picks it up.

    wrangler.toml

    [[kv_namespaces]]
    binding = "KEY_VALUE_STORE"
    preview_id = "unused"
    id = "unused"
    

    test

    console.log(getMiniflareBindings()) // { KEY_VALUE_NAMESPACE: ... }
    

    I just popped it into the global scope as a workaround for now, but this would be a problem when I actually need to publish this worker. Thanks for looking into it!

    question 
    opened by SupremeTechnopriest 10
  • Missing EventTarget and Event

    Missing EventTarget and Event

    For compliance with Cloudflare the global object (aka globalThis et al) and WebSocket need to inherit from EventTarget and both EventTarget and Event need to be exposed globally. I did some preliminary investigation and it’s not trivial to do; WebSocket implementation etc. but it seems doable.

    I don’t need this right this second, so no immediate rush, but it was discovered while trying to test our complex worker so if/when we eventually need this we’ll spend more time and potentially contribute the fixes, assuming you haven’t prioritized it yourself. Our usage is pretty advanced, so I imagine most won’t run into this.

    opened by jayphelps 10
  • Feature: Local IP information in local cf object

    Feature: Local IP information in local cf object

    Background

    Deployed Cloudflare workers offer the useful cf object, which provides Cloudflare-specific data from their edge network. Among these is the ASN, ASO, country, of the remote client IP. This data is especially useful as it cuts out an extra step in look up this data with an external service.

    Since miniflare is not deployed on the Cloudflare edge, it does not provide this data. In fact, this data is explicitly overridden in the file miniflare/src/index.ts (lines 375-395).

    This feature seeks to explore ways to replace some of the data in the cf object.

    Targeted sources files and dependencies

    • miniflare/src/index.ts
      • contains the cf object and the overridden fields
      • this feature would alter the overridden fields to values from the locally ingested ip info
    • local ip info ingestion
      • somewhere we would be allowing the ingestion of a local ip info db, such as a .mmdb
      • this could potentially be done from the command line interface like many of the other miniflare configurations as an optional CLI flag/arg

    Benefits of this feature

    • build consistent systems that rely on the Workers cf object for IP geo/whois data, even when running locally with miniflare

    Risks of this feature

    • the cf object is data from the Cloudflare edge network. Supplementing the data in the cf object with data sourced from elsewhere is potentially confusing at best, misrepresentation at worst.

    Fields in cf object marked for IP info

    Below are a list of fields within the cf object that could make use of data from a local IP geo/whois database. I have also subjectively marked them as either geo or whois as that may determine the database to be used.

    • cf.asn: whois
    • cf.asOrganization: whois
    • cf.country: geo
    • cf.city: geo
    • cf.continent: geo
    • cf.latitude: geo
    • cf.longitude: geo
    • cf.postalCode: geo
    • cf.metroCode: geo
    • cf.region: geo
    • cf.regionCode: geo
    • cf.timezone: geo

    Reference materials

    enhancement fixed-in-next 
    opened by aaronsdevera 9
  •  Initial Queues Support

    Initial Queues Support

    Pulling over the commits from my private fork.

    Also added two new commits to clean up some temporary docs, and adjust to the latest desired wrangler config for queues.

    I'm hoping to get this cleaned up and merged so that I can begin integrating it into the wrangler queues branch.

    opened by jbw1991 8
  • Implement `WebSocket` constructor

    Implement `WebSocket` constructor

    The Workers runtime has supported the new WebSocket constructor, as an alternative to the fetch API for WebSocket clients, since February 2022. This PR adds support for it to Miniflare.

    opened by mrbbot 1
  • [BUG] ws/lib/sender.js:162: 'First argument must be a valid error code number'

    [BUG] ws/lib/sender.js:162: 'First argument must be a valid error code number'

    miniflare occasionally throws like this, see https://github.com/cloudflare/wrangler2/issues/2476 or https://github.com/cloudflare/wrangler2/issues/1749, or here #284 .

    The problem comes here https://github.com/cloudflare/miniflare/blob/80046ce36c1637668d99d0679ca3f0a2a4beb0c7/packages/web-sockets/src/couple.ts#L57-L63 .

    and for ws, it receives:

        if (code === undefined) {
          buf = EMPTY_BUFFER;
        } else if (typeof code !== 'number' || !isValidStatusCode(code)) {
          throw new TypeError('First argument must be a valid error code number');
    
    function isValidStatusCode(code) {
      return (
        (code >= 1000 &&
          code <= 1014 &&
          code !== 1004 &&
          code !== 1005 &&
          code !== 1006) ||
        (code >= 3000 && code <= 4999)
      );
    }
    

    Maybe it just needs some tweaks to fit in.

    opened by yw662 0
  • Cache persistence doesn't work

    Cache persistence doesn't work

    Initially I thought this is my configuration issue, but then I found this topic: https://community.cloudflare.com/t/testing-workers-with-the-cache-api/181346

    However solution from that discussion wont help me. My caching results already had caching reply status. I've noticed that sometimes the caching behavior is unexpected to me, and decided to write tests to address that issue. However, it seems that even with correct wrangler.toml, cache wont be persistent if miniflare was created as part of a jest test.

    It seems that between tests the cache being reset, and I don't see any files created in my selected cache folder. I have 500 lines worker with complicated caching logic, and I would like to have tests cover all the corner cases.

    https://github.com/cloudflare/miniflare/blob/master/packages/shared-test-environment/src/storage.ts#L43

    module.exports = {
        presets: [
            ['@babel/preset-env', {targets: {node: 'current'}}],
            '@babel/preset-typescript',
        ],
    };
    
    export default {
      testEnvironment: "miniflare",
      // Configuration is automatically loaded from `.env`, `package.json` and
      // `wrangler.toml` files by default, but you can pass any additional Miniflare
      // API options here:
      testEnvironmentOptions: {
        bindings: { KEY: "value" },
        kvNamespaces: ["TEST_NAMESPACE"],
      },
    };
    
    name = "cloudflare-proxy"
    main = "src/index.ts"
    compatibility_date = "2022-12-30"
    send_metrics = false
    
    [miniflare]
    cache_persist = "./cache/"
    
    opened by Enelar 2
  • Miniflare sets `CF-Cache-Status` to null on misses

    Miniflare sets `CF-Cache-Status` to null on misses

    Contrary to cloudflare's behavior, miniflare does not set CF-Cache-Status when the cache was a miss.

    Cloudflare however returns the header with MISS:

    CF-Cache-Status: miss
    
    opened by aeneasr 0
  • Workers do not access the same instance of Durable Object

    Workers do not access the same instance of Durable Object

    Hi!

    Currently, Miniflare does not reuse the same DurableObjectsPlugin across workers. However, that's not how the production Durable Objects behave. There is only one instance of a Durable Object, as the documentation explains in the sections "Durable Object lifespan" and "In-memory state" from https://developers.cloudflare.com/workers/runtime-apis/durable-objects/#durable-object-lifespan.

    I wrote a (very) simple patch to make it work and fixed one unit test. But I couldn't figure out how to fix packages/core/test/index.mounts.spec.ts. I didn't understand enough the initialization of Miniflare in those tests. Here's the relevant commit:

    https://github.com/grafbase/miniflare/commit/35cabdae243381c83882f613cdce210a3bdbf6ba

    opened by Finistere 0
  • Fixed Improperly Controlled Modification of Object Prototype Prototype Pollution

    Fixed Improperly Controlled Modification of Object Prototype Prototype Pollution

    πŸ‘Ύ Describe The Sumarry:

    Prototype pollution vulnerability in function parseQuery in parseQuery.js in webpack loader-utils prior to 2.0.3 via the name variable in parseQuery.js. Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as __proto__, constructor and prototype. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.

    merge (target, source)
    foreach property of source
    
    if property exists and is an object on both the target and the source merge(target[property], source[property]) else target[property] = source[property]
    

    When the source object contains a property named proto defined with Object.defineProperty() , the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object and the source of Object as defined by the attacker. Properties are then copied on the Object prototype.operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source). lodash and Hoek are of libraries susceptible to recursive merge attacks.

    πŸ₯· According CVeScores:

    CVE-2022-37601 CWE-1321 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

    opened by iot-defcon 1
Releases(v3.0.0-next.10)
  • v3.0.0-next.10(Dec 14, 2022)

  • v3.0.0-next.9(Dec 13, 2022)

    Features

    • Log uncaught errors to the console with source-maps (#446)
    • Respect cf.cacheKey when using the Cache API (#447)
    • Add WebSocket support to fetch and Miniflare#dispatchFetch, as supported in Workers and Miniflare 2 (#453)
    • Allow custom function service bindings to return WebSocket Responses, as they could in Miniflare 2 (#453)
    • Allow the cf object to be customised with Miniflare#dispatchFetch (#453)
    • Allow specifying port: 0 option to bind to any accessible port (#453)

    Fixes

    • Fix caching of ReadableStream-bodied Responses (#447)
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-next.8(Dec 12, 2022)

    Features

    • Export Fetch API classes, types and functions from @miniflare/tre (#440, thanks @GregBrimble)

    Fixes

    • Fix Linux and WSL support (#443, #445)
    • Use correct binding name for kvNamespaces/r2Buckets specified as string[]s (#439, thanks @sgentle)
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-next.7(Nov 18, 2022)

    Features

    • Allow kvNamespaces/r2Buckets to be specified as string[]s like in Miniflare 2 (#432)
    • Add configurable logger (#434)
    • Add support for workerd's network, external and disk services (#435)
    • Add support for pretty-error pages (#436)

    Fixes

    • Enable cache persistence (#433)
    • Disable caching of Workers Sites assets (#433)
    • Respect cache: false option to disable caching (#433)
    • Respect cacheWarnUsage: true option for workers.dev subdomains (#433)
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-next.6(Nov 15, 2022)

  • v3.0.0-next.4(Nov 14, 2022)

  • v3.0.0-next.3(Nov 14, 2022)

    Features

    • Add support for __STATIC_CONTENT_MANIFEST module allowing module mode sites (#398)
    • Add support for the DevTools inspector protocol via the inspectorPort: <number> option (#426)
    • Allow workerd verbose mode to be enabled via the verbose: true option (#426)
    • Add support for the Cache API (#428)
    • Add support for live reload via the liveReload: true option (#429)
    • Add support for SQLite as a KV/R2/cache storage backend via the sqlite: persist schema (#419)
    • Add experimental support for remote KV storage via the remote: persist schema (#430)

    Fixes

    • Pass --experimental flag to workerd allowing compatibility flags without a default-on compatibility date to be used (#397)
    • Fix KV cacheTtl validation (#416)
    • Respect port and host options (#424)
    • Apply setOptions() in execution order (#425)
    Source code(tar.gz)
    Source code(zip)
  • v2.11.0(Oct 27, 2022)

    Features

    • Add support for dead-letter queues. Thanks @jbw1991 for the PR.
    • Add getMiniflareDurableObjectIds() global function to Miniflare's Jest/Vitest environments for listing active Durable Objects. Calling getMiniflareDurableObjectIds("TEST_OBJECT") will return a Promise that resolves to an array of active DurableObjectIds for the TEST_OBJECT namespace. Closes issue #384, thanks @DaniFoldi for the PR.

    Fixes

    Source code(tar.gz)
    Source code(zip)
  • v2.10.0(Oct 11, 2022)

    Features

    • Add support for TextEncoderStream/TextDecoderStream. Closes issue #389, thanks @vlovich.

    Fixes

    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-next.2(Sep 28, 2022)

    Fixes

    • If the specified compatibility date is after the latest supported workerd compatibility date, but not in the future, log a warning, and fallback to the latest supported date instead.
    • Resolve Miniflare#ready's Promise with the URL of workerd's HTTP server.
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-next.1(Sep 28, 2022)

    Miniflare now uses Cloudflare's open-source Workers runtime, workerd, to run your code! πŸŽ‰ This is a massive change, and should mean your code runs locally almost-exactly as in production. Most Workers features are supported, including Web Standards, KV, R2, but there are a few things that aren't just yet:

    • Durable Objects are in-memory only and cannot be persisted between reloads
    • The Cache API is not yet implemented
    • Scheduled Events are not yet implemented
    • console.logging an object will not show all its properties

    Breaking Changes

    • Miniflare's CLI has been removed. We're still discussing whether it makes sense to keep this, given wrangler dev has additional features such as automatic bundling and TypeScript support. For now, use wrangler dev --experimental-local.

    Miniflare API Changes

    • kvNamespaces now accepts an object mapping binding names to namespace IDs, instead of an array of binding names. This means multiple workers can bind the same namespace under different names.

       const mf = new Miniflare({
      -  kvNamespaces: ["NAMESPACE_1", "NAMESPACE_2"],
      +  kvNamespaces: {
      +    NAMESPACE_1: "NAMESPACE_1", // Miniflare <= 2 behaviour
      +    NAMESPACE_2: "ns2",         // Custom namespace ID
      +  },
       });
      
    • Similarly, r2Buckets now accepts an object mapping binding names to bucket IDs, instead of an array of binding names.

       const mf = new Miniflare({
      -  r2Buckets: ["BUCKET_1", "BUCKET_2"],
      +  r2Buckets: {
      +    BUCKET_1: "BUCKET_1", // Miniflare <= 2 behaviour
      +    BUCKET_2: "bucket2",  // Custom namespace ID
      +  },
       });
      
    • workerd requires all modules to be known ahead of time, so Miniflare will parse your JavaScript to search for module dependencies when setting modules to true. This has some limitations:

      1. Dynamic import() with non-literal arguments is unsupported.
      2. Any call to a function named require in a CommonJS module will be searched, even if it's not actually the global require function, and just a user-defined function with the same name.

      Because of these limitations, Miniflare allows you to define all your modules manually.

      import { Miniflare } from "@miniflare/tre";
      
      const mf = new Miniflare({
        modules: [
          // The first module must be your entrypoint. `type` must be one of
          // "ESModule", "CommonJS", "Text", "Data" or "CompiledWasm". If `path`
          // isn't relative, it will be converted to a relative path before being
          // passed to `workerd`.
          { type: "ESModule", path: "src/index.mjs" },
          // Optionally, a `contents` `string` or `Uint8Array` can be defined.
          // If omitted, `contents` is loaded from `path`.
          { type: "Text", path: "src/message.txt", contents: "Hello!" },
        ],
      });
      
    • mounts has been removed and replaced with the workers option.

      import { Miniflare } from "@miniflare/tre";
      
      const message = "The count is ";
      const mf = new Miniflare({
        // Options shared between workers such as HTTP and persistence configuration
        // should always be defined at the top level.
        host: "0.0.0.0",
        port: 8787,
        kvPersist: true,
      
        workers: [
          {
            name: "worker",
            kvNamespaces: { COUNTS: "counts" },
            serviceBindings: {
              INCREMENTER: "incrementer",
              // Service bindings can also be defined as custom functions, with access
              // to anything defined outside Miniflare.
              async CUSTOM(request) {
                // `request` is the incoming `Request` object.
                return new Response(message);
              },
            },
            modules: true,
            script: `export default {
              async fetch(request, env, ctx) {
                // Get the message defined outside
                const response = await env.CUSTOM.fetch("http://host/");
                const message = await response.text();
      
                // Increment the count 3 times
                await env.INCREMENTER.fetch("http://host/");
                await env.INCREMENTER.fetch("http://host/");
                await env.INCREMENTER.fetch("http://host/");
                const count = await env.COUNTS.get("count");
      
                return new Response(message + count);
              }
            }`,
          },
          {
            name: "incrementer",
            // Note we're using the same `COUNTS` namespace as before, but binding it
            // to `NUMBERS` instead.
            kvNamespaces: { NUMBERS: "counts" },
            // Worker formats can be mixed-and-matched
            script: `addEventListener("fetch", (event) => {
              event.respondWith(handleRequest());
            })
            async function handleRequest() {
              const count = parseInt((await NUMBERS.get("count")) ?? "0") + 1;
              await NUMBERS.put("count", count.toString());
              return new Response(count.toString());
            }`,
          },
        ],
      });
      const res = await mf.dispatchFetch("http://localhost");
      console.log(await res.text()); // "The count is 3"
      
    Source code(tar.gz)
    Source code(zip)
  • v2.9.0(Sep 16, 2022)

    Features

    • πŸ’Ύ Add support for D1. Closes issue #277, thanks @geelen for the PR. Docs coming soonβ„’... πŸ‘€

    • πŸšͺ Add getMiniflareDurableObjectState() and runWithMiniflareDurableObjectGates() functions to the Jest/Vitest environments. This allows you to construct and call instance methods of Durable Objects directly, without having to fetch through a stub. Closes issue #157, thanks @jorroll.

      // Durable Object class, would probably come from an import
      class Counter {
        constructor(state) {
          this.storage = state.storage;
        }
        async fetch() {
          const count = ((await this.storage.get("count")) ?? 0) + 1;
          void this.storage.put("count", count);
          return new Response(String(count));
        }
      }
      
      const env = getMiniflareBindings();
      // Use standard Durable Object bindings to generate IDs
      const id = env.COUNTER.newUniqueId();
      // Get DurableObjectState, and seed data
      const state = await getMiniflareDurableObjectState(id);
      await state.storage.put("count", 3);
      // Construct object directly
      const object = new Counter(state, env);
      // Call instance method directly, closing input gate,
      // and waiting for output gate to open
      const res = await runWithMiniflareDurableObjectGates(state, () =>
        object.fetch(new Request("http://localhost/"))
      );
      expect(await res.text()).toBe("4");
      
    • πŸ₯· Don't construct corresponding Durable Object instance when calling Miniflare#getDurableObjectStorage(). This allows you to seed data before your Durable Object's constructor is invoked. Closes issue #300, thanks @spigaz.

    • β˜‘οΈ Add support for WebSocket#readyState and WebSocket.READY_STATE_{CONNECTING,OPEN,CLOSING,CLOSED} constants. Note these constant names intentionally deviate from the spec to match the Workers runtime.

    • πŸ“œ Add persistent history to the REPL. This respects the MINIFLARE_REPL_HISTORY, MINIFLARE_REPL_HISTORY_SIZE, and MINIFLARE_REPL_MODE environment variables based on Node's.

    • πŸ’΅ Add support for Range, If-Modified-Since and If-None-Match headers on Requests to Cache#match. Closes issue #246.

    Fixes

    • Don't wait for waitUntil Promises to resolve before opening WebSocket connections
    • Allow WebSockets to be close()d on receiving a close event. Closes issue #331, thanks @awthwathje.
    • Ensure calling WebSocket#close() before returning a WebSocket response sends the correct close code and reason.
    • Fix delivery of incoming WebSocket error events
    • Ensure only scheduled Durable Object alarms are flushed. Previously, flushing all alarms would attempt to execute the alarm handler of every constructed Durable Object instance, even if that instance hadn't scheduled an alarm, or didn't have an alarm handler.
    • Delay scheduled missed alarms. Previously, if Durable Object persistence was enabled, and an alarm should've executed when Miniflare wasn't running, Miniflare may have crashed on startup. Closes issue #359, thanks @AlCalzone.
    • Allow empty-chunk writes to IdentityTransformStream. Closes issue #374, thanks @cdloh.
    • Don't hang when fetching from Durable Objects with fake-timers installed. Closes issue #190, thanks @vlovich.
    • Match unimplemented Request/Response properties with the Workers runtime. Specifically, throw unimplemented errors when attempting to access Request#{context,mode,credentials,integrity,cache} and Response#{type,useFinalUrl}.
    • Discard Content-Length: NaN headers as a temporary workaround until cloudflare/kv-asset-handler#295 is released. Closes honojs/hono#520, thanks @Cherry.
    • Return byte streams when tee()ing byte streams to match the behaviour of the Workers runtime. Closes issues #317 and #375.
    • Throw TypeError when calling Fetcher#fetch with an illegal this to match the behaviour of the Workers runtime.
    Source code(tar.gz)
    Source code(zip)
  • v2.8.2(Sep 10, 2022)

  • v2.8.1(Sep 8, 2022)

  • v2.8.0(Sep 7, 2022)

    Features

    • ⚑️ Add custom Vitest testing environment. This behaves almost identically to the Jest environment. However, isolated storage must be installed manually in each test file. Call the setupMiniflareIsolatedStorage() global function and use the returned describe function instead of the regular describe/suite functions imported from vitest. See ⚑️ Vitest Environment for more details.
    • 🌐 Populate Workers Sites __STATIC_CONTENT_MANIFEST with site files instead of an empty object. Miniflare will still disable caching of Workers Sites files to ensure the most up-to-date files are always returned. Closes issues #233, #326 and cloudflare/wrangler2#1632. Thanks @ItalyPaleAle, @Skye-31, @CraigglesO, @Hexstream and @PolariTOON.
    • ⏱ Add global getMiniflareWaitUntil() method and ExecutionContext class to the Jest and Vitest testing environments. This can be used to await the results of waitUntiled Promises in tests. See 🀹️ Jest Environment and ⚑️ Vitest Environment for more details. Closes issue #202, thanks @jamesarosen and @CraigglesO for the PR.
    • ⏳ Match Web Streams implementations with Workers runtime, closes issue #168, thanks @leviwolfe:
      • Add support for the non-standard IdentityTransformStream class.
      • Add support for the streams_enable_constructors compatibility flag. ReadableStream and WritableStream constructors will throw unless this flag is enabled. ReadableByteStreamController, ReadableStreamBYOBRequest, ReadableStreamDefaultController and WritableStreamDefaultController will only be included in the sandbox if this flag is enabled.
      • Add support for the transformstream_enable_standard_constructor compatibility flag. TransformStream will behave like IdentityTransformStream if this isn't enabled, ignoring custom transformers. If transformstream_enable_standard_constructor is set, but streams_enable_constructors isn't, the TransformStream constructor will throw. TransformStreamDefaultController will only be included in the sandbox if both flags are enabled.
      • Add support for BYOB reads to the non-standard FixedLengthStream class.
    • πŸ‡¬πŸ‡§ Add support for Queues. Docs coming soonβ„’... πŸ‘€
    • πŸ™‰ Allow calls to addEventListener, removeEventListener and dispatchEvent in modules mode. Please note, calling addEventListener with a special event type (e.g. fetch, scheduled) will log a warning prompting you to use the export default syntax. Closes issue #207, thanks @Electroid.
    • 🍟 Add experimental and highly-inaccurate request CPU time measurements. These are not representative of deployed worker performance, should only be used for relative comparisons, and may be removed in the future. Enable measurements with the --inaccurate-cpu/[miniflare] inaccurate_cpu/inaccurateCpu option. Closes issue #161. Thanks @alexandernst and @y21.
    • πŸ¦„ Automatically enable watch mode when live_reload = true is set in wrangler.toml.

    Fixes

    • Return Responses with immutable headers from fetches to Durable Objects and service bindings. Closes issue #346, thanks @Cherry.
    • Fix CryptoKey#algorithm.name property of NODE-ED25519 keys. Closes issue panva/jose#446, thanks @ItalyPaleAle.
    • Disable automatic insertion of Sec-WebSocket-Protocol header. Closes issue #179, thanks @aboodman and @grgbkr.
    • Return Content-Length header is custom Content-Encoding is specified. Closes issue #313, thanks @vlovich.
    • Require "automatic" instead of "auto" for the encodeBody option when constructing Requests. Closes issue #357, thanks @GregBrimble for the PR.
    • Remove request.cf.cacheTtl/request.cf.cacheTtlByStatus support from the Cache API to match the behaviour of the Workers runtime, which only supports request.cf.cacheKey.
    Source code(tar.gz)
    Source code(zip)
  • v2.7.1(Aug 22, 2022)

  • v2.7.0(Aug 19, 2022)

    ⚠️ Miniflare's minimum supported Node.js version is now 16.13.0. This was the first LTS release of Node.js 16.

    We recommend you use the latest Node.js version if possible, as Cloudflare Workers use a very up-to-date version of V8. Consider using a Node.js version manager such as https://volta.sh/ or https://github.com/nvm-sh/nvm.

    Features

    • πŸŽ‰ Add support for easily mocking outbound fetch requests. See πŸ•Έ Web Standards for more details. Closes issue #162, thanks @william1616 for the PR.

      test("mocks fetch", async () => {
        // Get correctly set up `MockAgent`
        const fetchMock = getMiniflareFetchMock();
        // Throw when no matching mocked request is found
        fetchMock.disableNetConnect();
        // Mock request to https://example.com/thing
        const origin = fetchMock.get("https://example.com");
        origin.intercept({ method: "GET", path: "/thing" }).reply(200, "Mocked response!");
      
        const res = await fetch("https://example.com/thing");
        const text = await res.text();
        expect(text).toBe("Mocked response!");
      });
      
    • 🚽 Add support to immediately invoke ("flush") scheduled Durable Object alarms in the 🀹 Jest Environment. Closes issue #322, thanks @robertcepa and @CraigglesO for the PR.

      test("flushes alarms", async () => {
        // Get Durable Object stub
        const env = getMiniflareBindings();
        const id = env.TEST_OBJECT.newUniqueId();
        const stub = env.TEST_OBJECT.get(id);
      
        // Schedule Durable Object alarm
        await stub.fetch("http://localhost/");
      
        // Flush all alarms...
        await flushMiniflareDurableObjectAlarms();
        // ...or specify an array of `DurableObjectId`s to flush
        await flushMiniflareDurableObjectAlarms([id]);
      });
      
    • πŸͺ£ Add support for R2 bucket bindings to the 🀹 Jest Environment. Closes issue #305, thanks @Cerberus for the PR.

    • 2️⃣ Add support for Wrangler 2's routes property. Closes issue #254, thanks @jrencz for the PR.

    • ⚠️ Upgrade undici to 5.9.1. Thanks @yusukebe and @cameron-robey for the PRs.

    Fixes

    Source code(tar.gz)
    Source code(zip)
  • v2.6.0(Jul 9, 2022)

    Features

    Fixes

    • Load service bindings from services instead of experimental_services, and use binding instead of name for the binding name. Thanks @jrencz for the PR. issue #280.
    • Log warning instead of error when fetching Request#cf object fails. Closes issue #224, thanks @threepointone.
    • Increase the subrequest limit for unbound workers from 50 to 1000, and limit the number of calls to internal APIs such as KV/Durable Object to 1000. Closes issue #274, thanks @isaac-mcfadyen.
    • Fix logging of accessible hosts in Node.js 18
    • Remove name from DurableObjectIds in DurableObjectState to match the behaviour of the Workers runtime. Closes issue #219.
    • Allow failure WebSocket upgrade responses. Closes issue #174, thanks @jinjor.
    • Correctly handle internationalised domain names in routes. Closes issue #186, thanks @dsod.
    • Improve the error message when Durable Object bindings are missing a script to mention mounting. Closes issue #221, thanks @konsumer.
    • Allow WebSockets to be closed without a status code. Closes issue #284, thanks @hansottowirtz.
    • Allow Durable Object alarms to be scheduled less than 30 seconds in the future. Closes issue #290, thanks @wighawag and @CraigglesO for the PR.
    • Fix DurableObjectStorage#list() when alarms are scheduled. Closes issue #297, thanks @evanderkoogh and @CraigglesO for the PR.
    Source code(tar.gz)
    Source code(zip)
  • v2.5.1(Jun 19, 2022)

  • v2.5.0(May 27, 2022)

    Features

    Fixes

    Source code(tar.gz)
    Source code(zip)
  • v2.4.0(Apr 2, 2022)

    Features

    Fixes

    • Pass correctly-typed value to webcrypto.getRandomValues(). Closes issue #188, thanks @vlovich.
    • Fix fetch with Content-Length: 0 header. Closes issue #193, thanks @orls for the PR.
    • Bind this to webcrypto methods, fixing crypto.getRandomValues() and crypto.subtle.generateKey(). Thanks @szkl for the PR.
    Source code(tar.gz)
    Source code(zip)
  • v2.3.0(Feb 7, 2022)

    Features

    • Route /cdn-cgi/mf/scheduled requests based on mount routes. Closes issue #163, thanks @jed.
    • Add clear error if a Durable Object class is missing a fetch handler. Closes issue #164, thanks @aboodman.
    • Upgrade undici to 4.13.0

    Fixes

    • Fix instanceof when subclassing Error. Subclasses of Error were previously treated as Errors themselves in instanceof checks. Closes issue #159, thanks @valeriangalliat.
    • Return null bodies when fetching Responses with a null status. Closes issue #165, thanks @lukaszczerpak for reporting this and @GregBrimble for the PR.
    • Clone ArrayBuffer bodies when constructing Request/Responses. Closes issue #171, thanks @segator and @leader22.
    • Watch index.js by default in type = "webpack" projects
    • Throw TypeErrors instead of strings on HTMLRewriter parser errors
    • Disable nested mounts via Miniflare#getMount().setOptions()
    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Jan 18, 2022)

    Features

    Fixes

    • Fix instanceof checks with null values. Closes issues #152 and #154. Thanks @Cerberus for the PR, and @bduff9, @huw & @g45t345rt for reporting this.
    • Fix subdirectory watching on Linux. Closes issue #153, thanks @huw for reporting this.
    • Throw a TypeError instead of a string when the parameter passed to a HTMLRewriter handler is used outside the handler
    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Jan 14, 2022)

    Features

    • Allow multiple build watch paths to be set in wrangler.toml files. Use the [miniflare] build_watch_dirs option. Note this gets merged with the regular [build] watch_dir option:

      [build]
      watch_dir = "src1"
      
      [miniflare]
      build_watch_dirs = ["src2", "src3"]
      
    • WebSocket handshake headers are now included in responses from the HTTP server and WebSocket upgrade fetches. Closes issue #151, thanks @jed.

    Fixes

    • Allow Miniflare to be installed with Yarn PnP. Closes issue #144, thanks @lookfirst, @merceyz, and @DJtheRedstoner.
    • Use the actual body length for the Content-Length header in HTTP server responses, instead of the value provided in the Response constructor. Closes issue #148, thanks @lukaszczerpak.
    • Don't rewrite the Host header to match the upstream URL. Closes issue #149, thanks @hansede.
    • Bump dependencies, fixing npm audit warnings. Thanks @leader22 for the PR.
    • Make instanceof spec-compliant, ensuring checks like Object instanceof Object succeed. This particular check was used by Lodash's _.isPlainObject() method, which is internally called by _.merge(), causing unexpected results.
    • Make the unimplemented Response#type property non-enumerable
    • Copy header guard when clone()ing Requests, ensuring Requests with immutable headers still have immutable headers when clone()ed
    • Fix race conditions in file-system watcher
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jan 7, 2022)

    Miniflare 2 has been completely redesigned from version 1 with 3 primary design goals:

    1. πŸ“š Modular: Miniflare 2 splits Workers components (KV, Durable Objects, etc.) into separate packages (@miniflare/kv, @miniflare/durable-objects, etc.) that you can import separately for testing.
    2. ✨ Lightweight: Miniflare 1 included 122 third-party packages with a total install size of 88MB. Miniflare 2 reduces this to 24 packages and 6MB by leveraging features included with Node.js 16.
    3. βœ… Accurate: Miniflare 2 more accurately replicates the quirks and thrown errors of the real Workers runtime, so you'll know before you deploy if things are going to break.

    Check out the migration guide if you're upgrading from version 1.

    Notable Changes

    • ✳️ Node.js 16.7.0 is now the minimum required version
    • 🀹 Added a custom Jest test environment, allowing you to run unit tests in the Miniflare sandbox, with isolated storage for each test
    • πŸ”Œ Added support for running multiple workers in the same Miniflare instance
    • ⚑️ Added a live reload feature (--live-reload) that automatically refreshes your browser when your worker reloads
    • πŸšͺ Added Durable Object input and output gates, and write coalescing
    • πŸ›‘ Added the DurableObjectState#blockConcurrencyWhile(callback) method
    • πŸ“… Added support for compatibility dates and flags: durable_object_fetch_requires_full_url, fetch_refuses_unknown_protocols, formdata_parser_supports_files
    • πŸ“š Added a proper CommonJS module loader
    • πŸ—Ί Automatically fetch the incoming Request#cf object from a trusted Cloudflare endpoint
    • 🎲 Added support for crypto.randomUUID()
    • πŸ” Added support for the NODE-ED25519 algorithm
    • βœ‰οΈ Added support for sending/receiving binary WebSocket messages

    Breaking Changes

    • Node.js 16.7.0 is now the minimum required version. You should use the latest Node.js version if possible, as Cloudflare Workers use a very up-to-date version of V8. Consider using a Node.js version manager such as https://volta.sh/ or https://github.com/nvm-sh/nvm.

    • Changed the storage format for Durable Objects and cached responses. If you're using file-system or Redis storage, you'll need to delete these directories/namespaces.

    • Changed the Durable Object ID format to include a hash of the object name. Durable Object IDs generated in Miniflare 1 cannot be used with Miniflare 2.

    • Correctly implement the Durable Object script_name option. In Miniflare 1, this incorrectly expected a script path instead of a script name. This now relies on mounting the other worker. See πŸ“Œ Durable Objects for more details.

    • Removed the non-standard DurableObjectStub#storage() method. To access Durable Object storage outside a worker, use the new Miniflare#getDurableObjectStorage(id) method, passing a DurableObjectId obtained from a stub. See πŸ“Œ Durable Objects for more details.

    • Renamed the --disable-cache/disableCache: true option to --no-cache/cache: false

    • Renamed the --disable-updater option to --no-update-check

    • When using the API, wrangler.toml, package.json and .env are no longer automatically loaded from their default locations. To re-enable this behaviour, set these options to true:

      const mf = new Miniflare({
        wranglerConfigPath: true,
        packagePath: true,
        envPath: true,
      });
      
    • Replaced the ConsoleLog class with the Log class from @miniflare/shared. You can construct this with a LogLevel to control how much information is logged to the console:

      import { Miniflare, Log, LogLevel } from "miniflare";
      
      const mf = new Miniflare({
        log: new Log(LogLevel.DEBUG),
      });
      
    • Load WASM bindings from the standard wasm_modules wrangler.toml key instead of miniflare.wasm_bindings.

      [miniflare]
      wasm_bindings = [
        { name = "MODULE1", path="module1.wasm" },
        { name = "MODULE2", path="module2.wasm" }
      ]
      

      ...should now be...

      [wasm_modules]
      MODULE1 = "module1.wasm"
      MODULE2 = "module2.wasm"
      
    • Renamed the buildWatchPath option to buildWatchPaths. This is now an array of string paths to watch as opposed to a single string.

    • Replaced the Miniflare#reloadOptions() method with the Miniflare#reload() and Miniflare#setOptions({ ... }) methods. reload() will reload options from wrangler.toml (useful if not watching), and setOptions() accepts the same options object as the new Miniflare constructor, applies those options, then reloads the worker.

    • Replaced the Miniflare#getCache() method the Miniflare#getCaches() method. This returns the global caches object. See ✨ Cache.

    • Miniflare#createServer() now always returns a Promise which you must await to get a http.Server/https.Server instance. You may want to check out the new Miniflare#startServer() method which automatically starts a server using the configured host and port.

    • Redis support is no longer included by default. If you're persisting KV, Durable Objects or cached responses in Redis, you must install the @miniflare/storage-redis optional peer dependency.

    • Replaced how Miniflare sanitises file paths for file-system storage so namespace separators (/, \, : and |) now create new directories.

    • The result of Miniflare#dispatchScheduled will no longer include undefined if a module scheduled handler doesn't return a value

    Features and Fixes

    Cache:

    • Added support for cf.cacheKey, cf.cacheTtl and cf.cacheTtlByStatus on Request. Closes issue #37, thanks @cdloh.
    • Added the CF-Cache-Status: HIT header to matched Responses
    • Log warning when trying to use cache with workers_dev = true in wrangler.toml. Cache operations are a no-op on workers.dev subdomains.
    • Throw errors when trying to cache Web Socket, non-GET, 206 Partial Content, or Vary: * responses
    • Throw an error when trying to open a cache with a name longer than 1024 characters

    CLI:

    • Separated command line options into sections
    • Validate types of all command line options

    Core:

    • Added support for running multiple workers in the same Miniflare instance. See πŸ”Œ Multiple Workers for more details.

    • Added support for compatibility dates and flags, specifically the flags durable_object_fetch_requires_full_url, fetch_refuses_unknown_protocols, formdata_parser_supports_files are now supported. This feature is exposed under the --compat-date and --compat-flag CLI options, in addition to the standard keys in wrangler.toml. Closes issue #48, thanks @PaganMuffin. See πŸ“… Compatibility Dates for more details.

    • Added a proper CommonJS module loader. Workers built with Webpack will be more likely to work with Miniflare now. Closes issue #44, thanks @TimTinkers.

    • Don't crash on unhandled promise rejections when using the CLI. Instead, log them. Closes issue #115, thanks @togglydev.

    • Limit the number of subrequests to 50, as per the Workers runtime. Closes issue #117, thanks @leader22 for the suggestion.

    • To match the behaviour of the Workers runtime, some functionality, such as asynchronous I/O (fetch, Cache API, KV), timeouts (setTimeout, setInterval), and generating cryptographically-secure random values (crypto.getRandomValues, crypto.subtle.generateKey), can now only be performed while handling a request.

      This behaviour can be disabled by setting the --global-async-io/globalAsyncIO, --global-timers/globalTimers and --global-random/globalRandom options respectively, which may be useful for tests or libraries that need async I/O for setup during local development. Note the Miniflare Jest environment automatically enables these options.

      KV namespaces and caches returned from Miniflare#getKVNamespace() and getCaches() are unaffected by this change, so they can still be used in tests without setting any additional options.

    • To match the behaviour of the Workers runtime, Miniflare now enforces recursion depth limits. Durable Object fetches can recurse up to 16 times, and service bindings can recurse up to 32 times. This means if a Durable Object fetch triggers another Durable Object fetch, and so on 16 times, an error will be thrown.

    • Incoming request headers are now immutable. Closes issue #36, thanks @grahamlyons.

    • Disabled dynamic WebAssembly compilation in the Miniflare sandbox

    • Fixed instanceof on primitives such as Object, Array, Promise, etc. from outside the Miniflare sandbox. This makes it much easier to run Rust workers in Miniflare, as wasm-bindgen frequently generates this code.

    • Added a new --verbose/verbose: true option that enables verbose logging with more debugging information

    • Throw a more helpful error with suggested fixes when Miniflare can't find your worker's script

    • Only rebuild parts of the sandbox that need to change when options are updated

    • Added a new reload event to Miniflare instances that is dispatched whenever the worker reloads:

      const mf = new Miniflare({ ... });
      mf.addEventListener("reload", (event) => {
        console.log("Worker reloaded!");
      });
      
    • Added a new Miniflare#getGlobalScope() method for getting the global scope of the Miniflare sandbox. This allows you to access and manipulate the Miniflare environment whilst your worker is running without reloading it. Closes issue #38, thanks @cdloh.

    • Added a new Miniflare#startScheduler() method that starts a CRON scheduler that dispatches scheduled events according to CRON expressions in options

    • Miniflare-added CF-* headers are now included in the HTML error response

    • Updated build script to use ES module exports of dependencies where possible. Thanks @lukeed for the PR.

    Bindings:

    • Added --global KEY=VALUE/globals: { KEY: "value" } option for binding arbitrary values to the global scope. This behaves exactly like the --binding/bindings: { ... } option, but always binds to the global scope, even in modules mode.

    • Added a new global variable MINIFLARE to the Miniflare sandbox, which will always have the value true when your script is running within Miniflare

    • Miniflare now stringifies all environment variables from wrangler.toml. Closes issue #50, thanks @ozburo.

    • Adds highly experimental support for service bindings. This is primarily meant for internal testing, and users outside the beta can't deploy workers using this feature yet, but feel free to play around with them locally and let us know what you think in the Cloudflare Workers Discord server.

      To enable these, mount your service (so Miniflare knows where to find it) then add the binding. Note the bound service name must match the mounted name:

      $ miniflare --mount auth=./auth --service AUTH_SERVICE=auth # or -S
      
      # wrangler.toml
      experimental_services = [
        # Note environment is currently ignored
        { name = "AUTH_SERVICE", service = "auth", environment = "production" }
      ]
      
      [miniflare.mounts]
      auth = "./auth"
      
      const mf = new Miniflare({
        mounts: { auth: "./auth" },
        serviceBindings: { AUTH_SERVICE: "auth" },
      });
      

      ...then to use the service binding:

      export default {
        async fetch(request, env, ctx) {
          const res = await env.AUTH_SERVICE.fetch("...");
          // ...
        },
      };
      

      If ./auth/wrangler.toml contains its own service bindings, those services must also be mounted in the root worker (i.e. in wrangler.toml not ./auth/wrangler.toml). Nested mounts are not supported.

    Builds:

    • When running your worker's build script, Miniflare will set the environment variable MINIFLARE=1. Closes issue #65, thanks @maraisr.
    • Added an alias, -B, for the --build-command option
    • Multiple build watch paths can now be specified. If any of them change, your worker will rebuild and reload.
    • Pass the --env flag to wrangler build when --wrangler-env is set for type = "webpack"/"rust" builds
    • Fixed an issue where workers would not rebuild if the build watch path started with ./. Closes issue #53, thanks @janat08.

    Standards:

    • Added support for crypto.randomUUID()
    • Added support for structuredClone. Note the transfer option is only supported on Node.js >= 17.
    • Added support for queueMicrotask
    • Added support for the NODE-ED25519 algorithm to crypto.subtle.sign() and crypto.subtle.verify()
    • Added support for AbortSignal.timeout()
    • Added support for crypto.DigestStream
    • Added support for scheduler.wait()
    • Added support for FixedLengthStream. Closes issue #123, thanks @vlovich.
    • Throw an error when attempting to create a new TextDecoder with a non-UTF-8 encoding
    • Throw errors when attempting to use FetchEvent/ScheduledEvent methods with incorrectly bound this
    • Throw errors when attempting to call respondWith() twice, or after the fetch handler has finished executing synchronously. Closes issue #63, thanks @Kikobeats.
    • Added support for the unhandledrejection and rejectionhandled events
    • Throw an error (with a suggested fix) when trying to access an env binding globally in modules mode
    • Throw errors when trying to use addEventListener(), removeEventListener() and dispatchEvent() globals in modules mode
    • Split the FetchError: No fetch handler responded and unable to proxy request to upstream? error into more specific errors with suggested fixes
    • Added the non-standard Headers#getAll() method. This can only be used with the Set-Cookie header.
    • Switch to a more spec-compliant fetch implementation, and get crypto, EventTarget and Web Streams from Node.js. Closes issues #56 and #59, thanks @jasnell, @jonathannorris and @SupremeTechnopriest.
    • Added support for the Response#encodeBody property. If this is omitted or set to auto, Responses with a Content-Encoding header that includes gzip, deflate or br will be automatically encoded. Closes issue #72, thanks @SupremeTechnopriest.
    • Return a non-opaque Response containing headers when fetching with a redirect mode set to manual in response to a redirect, closes issue #133, thanks @hansede, @vzaramel and @hnrqer.
    • Set the redirect mode of incoming requests to manual, matching the behaviour of the Workers runtime
    • Remove extra headers not sent by Cloudflare Workers with fetch requests. Closes issue #139, thanks @dfcowell.
    • Request/Response bodys are now byte streams, allowing them to be read with bring-your-own-buffer readers
    • Throw an error when attempting to construct a WebSocket response with a status other than 101
    • Throw an error when attempting to clone a WebSocket response
    • Added support for the non-standard ReadableStreamBYOBReader#readAtLeast(size, buffer) method
    • Include File in the Miniflare sandbox. Closes issue #66, thanks @tranzium.

    Durable Objects:

    • Added input and output gates for ensuring consistency without explicit transactions
    • Added write coalescing for put/delete without interleaving awaits for automatic atomic writes
    • Added the DurableObjectState#blockConcurrencyWhile(callback) method. This prevents new fetch events being delivered to your object whilst the callback runs. Closes issue #45, thanks @gmencz.
    • Added the DurableObjectId#equals(id) method for comparing if 2 Durable Object IDs have the same hex-ID
    • Automatically resolve relative URLs passed to DurableObjectStub#fetch(input, init?) against https://fast-host. Closes issue #27, thanks @halzy.
    • Throw an error if the string passed to DurableObjectNamespace#idFromString(hexId) is not 64 hex digits
    • Throw an error if the hex-ID passed to DurableObjectNamespace#idFromString(hexId) is for a different Durable Object
    • Throw an error if the ID passed to DurableObjectNamespace#get(id) is for a different Durable Object
    • Throw an error when keys are greater than 2KiB or undefined
    • Throw an error when values are greater than 128KiB
    • Throw an error when attempting to get, put or delete more than 128 keys, or when attempting to modify more than 128 keys in a transaction
    • Throw an error when attempting to put an undefined value
    • Throw an error when attempting to list keys with a negative limit
    • Throw an error when attempting to perform an operation in a rolledback transaction or in a transaction that has already committed
    • Throw an error when attempting to call deleteAll() in a transaction
    • Throw an error when a Durable Object fetch handler doesn't return a Response
    • Use the same V8 serialization as Cloudflare Workers to store values
    • Fixed an issue where keys added in a transaction callback were not reported as deleted in the same transaction
    • Fixed an issue where keys added in a transaction callback were not included in the list of keys in the same transaction

    HTMLRewriter:

    • Remove Content-Length header from HTMLRewriter transformed Responses
    • Don't start transforming until transformed Response body is needed
    • Throw an error when attempting to transform body streams containing non-ArrayBuffer/ArrayBufferView chunks

    HTTP Server:

    • Added a live reload feature, that automatically refreshes your browser when your worker reloads. For this to work, pass the --live-reload option, and return an HTML response containing a <body> tag with the Content-Type set to text/html. See ⚑️ Live Reload for more details.

      addEventListener("fetch", (event) => {
        const body = `
          <!DOCTYPE html>
          <html>
          <body>
            <p>Try update me!</p>
          </body>
          </html>
        `;
      
        const res = new Response(body, {
          headers: { "Content-Type": "text/html; charset=utf-8" },
        });
      
        event.respondWith(res);
      });
      
    • Added --open/-O option that automatically opens your browser once your worker is running. You can optionally specify a different URL to open with --open https://example.com. Closes issue #121, thanks @third774 for the suggestion.

    • Automatically fetch the incoming Request#cf object from a trusted Cloudflare endpoint, so the values are the same as you'd get for real. Closes issue #61, thanks @aaronsdevera and @Electroid.

    • Added a metaProvider option that allows you fetch metadata for an incoming Request:

      const mf = new Miniflare({
        async metaProvider(req) {
          return {
            forwardedProto: req.headers["X-Forwarded-Proto"],
            realIp: req.headers["X-Forwarded-For"],
            cf: {
              // Could get these from a geo-IP database
              colo: "SFO",
              country: "US",
              // ...
            },
          };
        },
      });
      
    • Split out the Node request to Request object conversion logic into a convertNodeRequest(req, meta?) function. You can import this from @miniflare/http-server.

    • Only return a pretty-error page when the request Accept header includes text/html

    • Added a new Miniflare#startServer(options?) method that starts an HTTP server using the configured port and host. options can be a http.ServerOptions or https.ServerOptions object. Closes issue #39, thanks @amlwwalker

    • Include a default Content-Type header of text/plain in Responses. Closes issue #57, thanks @Rysertio.

    Jest Environment:

    • Added a custom Jest test environment, allowing you to run unit tests in the Miniflare sandbox, with isolated storage for each test. See 🀹 Jest Environment for more details.

    KV:

    • Throw an error when keys are empty, ., .., undefined, or greater than 512B when UTF-8 encoded
    • Throw an error when values are greater than 25MiB
    • Throw an error when metadata is greater than 1KiB
    • Throw an error when the cacheTtl option is less than 60s
    • Throw an error when expirationTtl is non-numeric, less than or equal 0, or less than 60s
    • Throw an error when expiration is non-numeric, less than or equal the current time, or less than 60s in the future
    • Throw an error when the limit passed to KVNamespace#list() is non-numeric, less than or equal 0, or greater than 1000

    Scheduler:

    • Moved the /.mf/scheduled endpoint for triggering scheduled events to /cdn-cgi/mf/scheduled. Closes issue #42, thanks @ObsidianMinor.
    • Switched the CRON validation and scheduling package from node-cron to cron-schedule. This improves error messages for invalid CRON expressions, and removes a transitive dependency on moment-timezone, reducing the installation size by 5MB.

    Workers Sites:

    • Added support for the new __STATIC_CONTENT_MANIFEST text module allowing you to use Workers Sites in modules mode

    Web Sockets:

    • Added support for sending/receiving binary messages. Closes issue #67, thanks @NostalgiaRunner.
    • Removed the WebSocket#readyState property. Closes issue #47, thanks @aboodman.
    • Wait for worker response before opening WebSocket in client, closes issue #88, thanks @TimTinkers.
    • http and https protocols are now required for WebSocket upgrades via fetch as per the workers runtime
    • Throw an error when attempting to use a WebSocket in a Response that has already been used
    • Throw an error when attempting to use a WebSocket in a Response after calling accept() on it
    • Throw an error when attempting to construct a WebSocket using the WebSocket constructor
    • Throw an error when attempting to call WebSocket#send() or WebSocket#close() without first calling accept(). Closes issue #43, thanks @aboodman.
    • Throw an error when attempting to call WebSocket#send() after calling close()
    • Throw an error when attempting to call WebSocket#close() on an already closed WebSocket
    • Throw an error when attempting to call WebSocket#close() with an invalid close code
    • Make WebSocket event constructors more spec-compliant

    Changes Since 2.0.0-rc.5

    • Return a Response containing headers when fetching with a redirect mode set to manual in response to a redirect, closes issue #133, thanks @hansede, @vzaramel and @hnrqer.
    • Set the redirect mode of incoming requests to manual, matching the behaviour of the Workers runtime
    • Removed default fetch headers automatically added by undici, closes issue #139, thanks @dfcowell
    • Removed the --proxy-primitive/proxy_primitive_instanceof option. This is now the default behaviour, whilst still allowing prototype/constructor checks to succeed. See πŸ•Έ Web Standards for more details.
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-rc.5(Jan 3, 2022)

    This update is mostly focused on improving mounts for service bindings. It also matches some other core behaviour of the Workers runtime, like blocking asynchronous I/O outside request handlers, and limiting request recursion depth.

    Breaking Changes

    • ~~instanceof checks on primitives such as Object, Array, Promise, etc. from outside the Miniflare sandbox no longer succeed by default. This was initially added to make it easier to run Rust workers in Miniflare, as wasm-bindgen frequently generates this code. However, the implementation caused Object prototype/constructor checks to fail in JavaScript. The previous behaviour can be restored with the --proxy-primitive/miniflare.proxy_primitive_instanceof/proxyPrimitiveInstanceOf CLI/wrangler.toml/API option. This should be enabled when developing Rust workers. See this comment for more details. Closes issues #109, #137, #141 and cloudflare/wrangler2#91. Thanks @EmilianoSanchez, @lukaszczerpak, @SirJosh3917 and @johnhenry.~~ NOTE: this change will be reverted in the next release. I've thought of an alternative solution that doesn't need this flag.
    • Mount paths defined in wrangler.toml are now resolved relative to the directory containing the wrangler.toml file
    • Mount names must match the name field in wrangler.toml if its defined

    Features

    • To match the behaviour of the Workers runtime, some functionality, such as asynchronous I/O (fetch, Cache API, KV), timeouts (setTimeout, setInterval), and generating cryptographically-secure random values (crypto.getRandomValues, crypto.subtle.generateKey), can now only be performed while handling a request.

      • This behaviour can be disabled by setting the --global-async-io/globalAsyncIO, --global-timers/globalTimers and --global-random/globalRandom options respectively, which may be useful for tests or libraries that need async I/O for setup during local development. Note the Miniflare Jest environment automatically enables these options.

      • KV namespaces and caches returned from Miniflare#getKVNamespace() and getCaches() are unaffected by this change, so they can still be used in tests without setting any additional options.

    • Adds highly experimental support for service bindings. This is primarily meant for internal testing, and users outside the beta can't deploy workers using this feature yet, but feel free to play around with them locally and let us know what you think in the Cloudflare Workers Discord server.

      To enable these, mount your service (so Miniflare knows where to find it) then add the binding. Note the bound service name must match the mounted name:

      $ miniflare --mount auth=./auth --service AUTH_SERVICE=auth # or -S
      
      # wrangler.toml
      experimental_services = [
        # Note environment is currently ignored
        { name = "AUTH_SERVICE", service = "auth", environment = "production" }
      ]
      
      [miniflare.mounts]
      auth = "./auth"
      
      const mf = new Miniflare({
        mounts: { auth: "./auth" },
        serviceBindings: { AUTH_SERVICE: "auth" },
      });
      

      ...then to use the service binding:

      export default {
        async fetch(request, env, ctx) {
          const res = await env.AUTH_SERVICE.fetch("...");
          // ...
        },
      };
      

      If ./auth/wrangler.toml contains its own service bindings, those services must also be mounted in the root worker (i.e. in wrangler.toml not ./auth/wrangler.toml). Nested mounts are not supported.

    • To match the behaviour of the Workers runtime, Miniflare now enforces recursion depth limits. Durable Object fetches can recurse up to 16 times, and service bindings can recurse up to 32 times. This means if a Durable Object fetch triggers another Durable Object fetch, and so on 16 times, an error will be thrown.

    • The root worker is now routable using route/routes as with mounts if it has a name set. This means if it has more specific routes than other mounts, they'll be used instead. The root worker is always used as a fallback if no mounts' routes match.

    • Mounted workers can now access Durable Objects defined in other mounts or the root worker (assuming a name is set) using the script_name option.

    • Allow the subrequest limit to be customised using the MINIFLARE_SUBREQUEST_LIMIT environment variable. Setting this to a negative number disables the limit. Setting this to 0 disables subrequests. The majority of users should never need to touch this, hence it's configured via an environment variable, not a CLI option. This also makes the implementation much simpler. :slight_smile: Closes issue #132, thanks @DanielAGW.

    Fixes

    • Allow env_path to be set in wrangler.toml
    • WebSocket client fetches now contribute to the subrequest limit
    • Errors raised when reloading (e.g. missing Durable Object classes) in response to mount file changes are now logged, and don't crash
    • Fixed issue where deleting [miniflare.mounts] in wrangler.toml wouldn't unmount everything
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-rc.4(Dec 18, 2021)

    This update incorporates the 2021-12-10 Workers runtime changes. The Miniflare docs now use the Cloudflare Docs Engine.

    Features

    • Switched back to CommonJS exports. A primary goal of Miniflare is to provide a fun developer experience. Currently, this is not the case when using Miniflare with a certain popular testing framework (cough, ~~Jest~~, cough), because it and its ecosystem's support for ESM isn't great yet. This also makes it easier to upgrade from Miniflare 1. Node lets you import CommonJS modules in ES modules so this won't break existing code. Thanks @Kikobeats.
    • Added --open/-O option that automatically opens your browser once your worker is running. You can optionally specify a different URL to open with --open https://example.com. Closes issue #121, thanks @third774 for the suggestion.
    • Don't crash on unhandled promise rejections when using the CLI. Instead, log them. Closes issue #115, thanks @togglydev.
    • Added support for AbortSignal.timeout()
    • Added support for crypto.DigestStream
    • Added support for scheduler.wait()
    • Added support for FixedLengthStream. Closes issue #123, thanks @vlovich.
    • Limit the number of subrequests to 50, as per the Workers runtime. Closes issue #117, thanks @leader22 for the suggestion.
    • Raised the Durable Object storage max value size from 32KiB to 128KiB
    • Re-export remaining fetch types from undici in @miniflare/core. Closes issue #124, thanks @GregBrimble.

    Fixes

    • Fixed issue where Math was missing in sandbox when running Worker for module exports in jest-environment-miniflare. Closes issue #128, thanks @worenga for the PR.
    • Fixed the script path for type = "webpack" Workers Sites projects
    • Allow */* route in mounted workers
    • kv_persist, cache_persist and durable_objects_persist options set in mounted workers' wrangler.toml files are now respected
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-rc.3(Dec 8, 2021)

    The Miniflare docs now include a migration guide for upgrading from version 1.

    Breaking Changes

    • Mounts are no longer accessible by default via /<mount_name>. You must specify routes in wrangler.toml using the route/routes/miniflare.route/miniflare.routes options for them to be accessible. See πŸ”Œ Multiple Workers for more details. This feature was inspired by multiflare, created by @dan-lee.
    • All file-path-valued options are now resolved relative to the --root option
    • Miniflare#dispatchFetch will now rewrite the request's URL/Host header to match the upstream URL if specified
    • convertNodeRequest no longer accepts an upstream parameter, it now always uses the request's Host header

    Features

    • Make Request/Response bodys byte streams, allowing them to be read with bring-your-own-buffer readers
    • Allow setting the wrangler.toml environment when mounting workers with the CLI. For example, --mount api=./api@dev mounts the worker in the ./api directory as api, using the dev environment in ./api/wrangler.toml.
    • Allow setting the Durable Object script_name option via the CLI. For example, --do COUNTER=Counter@api binds the COUNTER Durable Object namespace using the Counter class exported by the mounted api worker.
    • Update error message when attempting to access bindings via global in modules mode for Cloudflare Pages
    • When the fetch_refuses_unknown_protocols compatibility flag isn't set, log a warning when attempting to use a protocol other than http or https
    • The upstream URL is now validated on startup if specified

    Fixes

    • Copy webSocket when constructing a Response from an existing Response, closes issue #100, thanks @universse
    • Allow constructing null body with empty-string, closes issue #101, thanks @PH4NTOMiki
    • Remove ASCII whitespace from atob input, closes issue #104, thanks @dan-lee
    • Remove keys limit from Durable Objects list() method, closes issue #105, thanks @vzaramel
    • Allow Sec-WebSocket-Protocol header in WebSocket fetch, closes issue #106, thanks @f5io
    • Fix uncaught rejection when closing server-sent events connection, closes issue #107, thanks @dan-lee
    • Bump undici to 4.11.1, allowing Responses with null bodies to be cloned, closes issue #110, thanks @payellodevsupport
    • Allow forbidden header mutation on Request/Response instances, closes cloudflare/wrangler2 issue #59, thanks @oliverjam
    • Allow missing parent script with mounted workers
    • Correctly handle attempting to read a key in a namespace that is also a key when using FileStorage, and throw when trying to write in this case (this is a limitation of Miniflare's file-system storage).
    • When the fetch_refuses_unknown_protocols compatibility flag isn't set, correctly replace non-standard protocols (e.g. random://) with http:// in fetch.
    • Remove types dependency on lib.webworker
    • Incoming https requests will now have https URLs
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-rc.2(Nov 22, 2021)

    Features

    • Add structuredClone to the sandbox
    • Copy --kv-persist, --cache-persist and --do-persist options to --mounts, so data is shared correctly
    • Resolve mount-custom storage persistence options relative to mounted directory
    • Add a more helpful error message on DurableObjectStorage#get deserialization failure due to Miniflare 1 data
    • Add a more helpful error message on Cache#match deserialization failure due to Miniflare 1 data
    • Add a more helpful error message when unable to find a matching module rule that suggests bundling npm packages

    Fixes

    • Bump undici to 4.10.2, closes issues #84 and #91, thanks @gzuidhof and @tranzium
    • Remove Host and CF-Connecting-IP headers when fetching, closes issue #97, thanks @WalshyDev
    • Allow file-system persisted keys to start with /, thanks @eidam for reporting this
    • Setting an option to undefined now overrides that option in wrangler.toml like Miniflare 1
    • When building mounted workers, set the current working directory to the mounted directory
    • Respect the fetch_refuses_unknown_protocols compatibility flag in DurableObjectStub#fetch
    • Default Response.redirect status to 302 instead of throwing
    • Improve spec-compliance of WebSocket event constructors

    Jest Fixes πŸ™

    • Fix importing miniflare in Jest when using the node environment, specifically fix WebSocketServer import and atob/btoa/AbortSignal globals
    • Add Buffer to global in jest-environment-node, thanks @dan-lee for the PR
    • Allow dynamic code generation in jest-environment-node for coverage, thanks @dan-lee for reporting this
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-rc.1(Nov 13, 2021)

    Breaking Changes

    • Changed the priority of bindings, so it matches Miniflare 1. The new order (from lowest to highest priority) is:
      1. Variables from wrangler.toml [vars]
      2. Variables from .env files
      3. WASM module bindings (--wasm, [wasm_modules])
      4. Custom bindings
    • The result of dispatchScheduled will no longer include undefined if a module scheduled handler doesn't return a value

    Features

    • Added a custom Jest test environment for Miniflare. This allows you to run unit tests in the Miniflare sandbox, with isolated storage for each test. Install jest-environment-miniflare@next to get started and see 🀹 Jest Environment for more details.
    • Added support for running multiple workers in the same Miniflare instance. See πŸ”Œ Multiple Workers for more details.
    • Added support for the Durable Object script_name option. See πŸ“Œ Durable Objects for more details.
    • Added support for the new __STATIC_CONTENT_MANIFEST text module for using Workers Sites in modules mode
    • Throw an error when a Durable Object fetch handler doesn't return a Response
    • Added queueMicrotask to the sandbox
    • Added the Miniflare#getCaches method for accessing the global caches outside workers
    • Added back the sourceMap option to Miniflare
    • Changed the default location for the update-check and cf.json files to inside node_modules
    • Switched the CRON validation and scheduling package from node-cron to cron-schedule. This improves error messages for invalid CRON expressions, and removes a transitive dependency on moment-timezone, reducing the installation size by a further 5MB.

    Fixes

    • Allow any close code when a client closes a WebSocket connection. Closes issue #86, thanks @TimTinkers.
    • Wait for worker response before opening WebSocket in client, closes issue #88, thanks @TimTinkers.
    • Pass the --env flag to wrangler build when --wrangler-env is set for type = "webpack"/"rust" builds
    • Set correct Host header with --upstream flag set
    • Fixed memory leak in HTMLRewriter when passing non-ArrayBuffer(View) chunks
    • Marked @miniflare/core and @miniflare/storage-memory as dependencies of @miniflare/durable-objects
    • Removed ServiceWorkerGlobalScope#dispose() from global scope
    Source code(tar.gz)
    Source code(zip)
The perfect library for adding search, sort, filters and flexibility to tables, lists and various HTML elements. Built to be invisible and work on existing HTML.

List.js Perfect library for adding search, sort, filters and flexibility to tables, lists and various HTML elements. Built to be invisible and work on

Jonny StrΓΆmberg 10.9k Jan 1, 2023
Drag and drop library for two-dimensional, resizable and responsive lists

GridList Drag and drop library for a two-dimensional resizable and responsive list of items Demo: http://hootsuite.github.io/grid/ The GridList librar

Hootsuite 3.6k Dec 14, 2022
πŸ“ Algorithms and data structures implemented in JavaScript with explanations and links to further readings

JavaScript Algorithms and Data Structures This repository contains JavaScript based examples of many popular algorithms and data structures. Each algo

Oleksii Trekhleb 158k Dec 31, 2022
Gmail-like client-side drafts and bit more. Plugin developed to save html forms data to LocalStorage to restore them after browser crashes, tabs closings and other disasters.

Sisyphus Plugin developed to save html forms data to LocalStorage to restore them after browser crashes, tabs closings and other disasters. Descriptio

Alexander Kaupanin 2k Dec 8, 2022
A lightweight jQuery plugin for collapsing and expanding long blocks of text with "Read more" and "Close" links.

Readmore.js V3 alpha I am deprecating the 2.x version of Readmore.js. A new version is coming soon! Check it out and help me test it! Readmore.js A sm

Jed Foster 1.5k Nov 30, 2022
FriendAdvisor is a mobile app with a focus on allowing friends and family to coordinate and receive text notifications about upcoming group events.

FriendAdvisor is a mobile app with a focus on allowing friends and family to coordinate and receive text notifications about upcoming group events.

Brad Johnson 4 Sep 29, 2022
Defines the communication layer between mobile native(iOS/Android) and webview using JSON Schema and automatically generates SDK code

Defines the communication layer between mobile native(iOS/Android) and webview using JSON Schema and automatically generates SDK code.

λ‹Ήκ·Όλ§ˆμΌ“ 31 Dec 8, 2022
A responsive image polyfill for , srcset, sizes, and more

Picturefill A responsive image polyfill. Authors: See Authors.txt License: MIT Picturefill has three versions: Version 1 mimics the Picture element pa

Scott Jehl 10k Dec 31, 2022
A high-performance, dependency-free library for animated filtering, sorting, insertion, removal and more

MixItUp 3 MixItUp is a high-performance, dependency-free library for animated DOM manipulation, giving you the power to filter, sort, add and remove D

Patrick Kunka 4.5k Dec 24, 2022
JavaScript Survey and Form Library

SurveyJS is a JavaScript Survey and Form Library. SurveyJS is a modern way to add surveys and forms to your website. It has versions for Angular, jQue

SurveyJS 3.5k Jan 1, 2023
Extensive math expression evaluator library for JavaScript and Node.js

?? Homepage Fcaljs is an extensive math expression evaluator library for JavaScript and Node.js. Using fcal, you can perform basic arithmetic, percent

Santhosh Kumar 93 Dec 19, 2022
Components for interactive scientific writing, reactive documents and explorable explanations.

@curvenote/article The goal of @curvenote/article is to provide web-components for interactive scientific writing, reactive documents and explorable e

curvenote 142 Dec 24, 2022
Create explorable explanations and interactive essays.

Tutorials | Examples | Docs | Chatroom | Mailing list | Twitter What is Idyll? For an introduction to Idyll, API reference, examples, and tutorials, p

Idyll 1.9k Dec 27, 2022
Browser fingerprinting library with the highest accuracy and stability.

FingerprintJS is a browser fingerprinting library that queries browser attributes and computes a hashed visitor identifier from them. Unlike cookies a

FingerprintJS 18.1k Dec 31, 2022
autoNumeric is a standalone library that provides live as-you-type formatting for international numbers and currencies.

What is autoNumeric? autoNumeric is a standalone Javascript library that provides live as-you-type formatting for international numbers and currencies

AutoNumeric 1.7k Dec 16, 2022
Bookmarklet to remove sticky elements and restore scrolling to web pages!

Bookmarklet to remove sticky elements and restore scrolling to web pages!

Tim Martin 648 Dec 29, 2022
Free, open-source crypto trading bot, automated bitcoin / cryptocurrency trading software, algorithmic trading bots. Visually design your crypto trading bot, leveraging an integrated charting system, data-mining, backtesting, paper trading, and multi-server crypto bot deployments.

Free, open-source crypto trading bot, automated bitcoin / cryptocurrency trading software, algorithmic trading bots. Visually design your crypto trading bot, leveraging an integrated charting system, data-mining, backtesting, paper trading, and multi-server crypto bot deployments.

Superalgos 3.1k Jan 1, 2023
Scheme flooding vulnerability: how it works and why it is a threat to anonymous browsing

Scheme flooding vulnerability: how it works and why it is a threat to anonymous browsing

FingerprintJS 623 Dec 28, 2022
A user script for the web that allows you to view and edit files in the Godot Web Editor

Godot-Web-File-Manager This is a user script for the web that allows you to view and edit files in the Godot Web Editor. You can even use this to enab

Roujel Williams 4 Jan 31, 2022