Skip to content

Latest commit

Β 

History

History
1545 lines (1342 loc) Β· 70.2 KB

CHANGELOG.md

File metadata and controls

1545 lines (1342 loc) Β· 70.2 KB

🚧 Changelog

2.11.0

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

2.10.0

Features

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

Fixes

2.9.0

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.

2.8.2

Fixes

2.8.1

Fixes

  • Add missing @miniflare/queues dependencies. Closes issue #360, thanks @AlCalzone for the PR.
  • Fix support for queues in Jest/Vitest testing environments

2.8.0

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.

2.7.1

Fixes

  • Ensure initialisation is complete before tear down in Miniflare#dispose(). Closes issue #341, thanks @vlovich.
  • Ensure DurableObjectTransaction operations are executed in program order. Closes issue #344, thanks @vlovich.

2.7.0

⚠️ 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

2.6.0

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.

2.5.1

⚠️ Security Update

2.5.0

Features

Fixes

2.4.0

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.

2.3.0

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()

2.2.0

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

2.1.0

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

2.0.0

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.

    ---
    filename: wrangler.toml
    ---
    [miniflare]
    wasm_bindings = [
      { name = "MODULE1", path="module1.wasm" },
      { name = "MODULE2", path="module2.wasm" }
    ]

    ...should now be...

    ---
    filename: wrangler.toml
    ---
    [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

1.4.1

Fixes

  • Fixed linking of modules with cyclic imports, allowing new Rust workers to be run with Miniflare. Closes issue #41, thanks @nuvanti.
  • Fixed handling of ArrayBufferViews as Response bodies

1.4.0

Features

  • Added Event and EventTarget to the sandbox. The global scope and WebSocket now inherit from EventTarget so removeEventListener is now supported. Closes issue #18, thanks @jayphelps.
  • Added workers' uncompressed size to logs, closes issue #23, thanks @ItsWendell
  • Switch to lighter dependencies, thanks @lukeed. There's still lots of work to do here for the next major release.

Fixes

1.3.3

Features

  • Added an option to disable default and named caches. When disabled, the caches will still be available in the sandbox, they just won't cache anything. Thanks @frandiox for the suggestion. See ✨ Cache for more details.
  • Added the corresponding wrangler.toml key for the --disable-updater flag: miniflare.disable_updater

Fixes

  • Fixed the package.json file path the update checker checked against

1.3.2

Features

  • Responses are now streamed when using the built-in HTTP(S) server
  • Return values of Durable Object transaction closures are now propagated as the return value of the transaction call

Fixes

1.3.1

Fixes

  • Upgraded html-rewriter-wasm to version 0.3.1, fixing the return type of Element.attributes

1.3.0

Features

Fixes

1.2.0

Features

Fixes

  • Fixed Windows support, closes issue #10
  • Fixed issue where scripts were not reloaded correctly when editing script path in wrangler.toml. Scripts are now always reloaded on options change. Miniflare.reloadScript() is now deprecated. You should use Miniflare.reloadOptions() instead.

1.1.0

Features

  • Added support for namespaced caches with caches.open. See ✨ Cache for more details.

1.0.1

Fixes

  • Fixed /usr/bin/env: 'node --experimental-vm-modules': No such file or directory error when running the CLI in Linux. See πŸ’» Using the CLI for more details.

1.0.0

Breaking Changes

  • The first and only argument to the Miniflare constructor is now an object. Scripts should be specified via the script option for strings and the scriptPath option for files:

    // Previous version
    import vm from "vm";
    import { Miniflare } from "miniflare";
    
    const mf1 = new Miniflare(
      new vm.Script(`addEventListener("fetch", (event) => { ... })`),
      { kvPersist: true }
    );
    const mf2 = new Miniflare("script.js", { kvPersist: true });
    // New version
    import { Miniflare } from "miniflare";
    
    const mf1 = new Miniflare({
      script: `addEventListener("fetch", (event) => { ... })`,
      kvPersist: true,
    });
    const mf2 = new Miniflare({
      scriptPath: "script.js",
      kvPersist: true,
    });
  • The Miniflare.getNamespace method has been renamed to Miniflare.getKVNamespace

  • Logged errors will now throw a MiniflareError if no log is provided

  • When using file system KV persistence, key names are now sanitised to replace special characters such as :, /, and \. Reading keys containing these characters may now return null if a value was stored in the previous version.

Features

Fixes

  • Fixed error if options object (containing type and cacheTtl properties) passed as second parameter to KV get method, closes issue #3
  • Fixed error if ArrayBuffer passed as data to crypto.subtle.digest("md5", data)
  • Fixed handling of ignoreMethod option for Cache match and delete
  • Disabled edge caching when using Workers Sites, files are now always loaded from disk
  • Provided Set and WeakSet from Miniflare's realm to sandbox, removing Promise, so (async () => {})() instanceof Promise evaluates to true

0.1.1

Fixes

  • Depend on @mrbbot/node-fetch from npm instead of GitHub, closes issue #2

0.1.0

Initial Release

Features