Skip to content
7 changes: 7 additions & 0 deletions .changeset/deprecate-supportedCompatibilityDate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"miniflare": minor
---

Deprecate `supportedCompatibilityDate` export

The `supportedCompatibilityDate` export is now deprecated. Instead of relying on the workerd-derived compatibility date, callers should just use today's date directly, e.g. `new Date().toISOString().slice(0, 10)`.
7 changes: 7 additions & 0 deletions .changeset/remove-formatCompatibilityDate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/workers-utils": minor
---

Remove `formatCompatibilityDate` from the package's public exports

This utility has been removed from the public API. Callers should use `getTodaysCompatDate()` from `@cloudflare/workers-utils` instead.
7 changes: 7 additions & 0 deletions .changeset/remove-getLocalWorkerdCompatibilityDate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/workers-utils": minor
---

Remove `getLocalWorkerdCompatibilityDate` from the package

This utility has been removed because its implementation besides being unreliable is no longer needed. Callers should now use today's date as the compatibility date directly, e.g. via `getTodaysCompatDate()` from `@cloudflare/workers-utils`.
8 changes: 8 additions & 0 deletions .changeset/use-today-date-for-compat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"create-cloudflare": patch
"wrangler": patch
---

Use today's date as the default compatibility date

Previously, when generating a compatibility date for new projects or when no compatibility date was configured, the date was resolved by loading the locally installed `workerd` package via `miniflare`. This approach was unreliable in some package manager environments (notably `pnpm`). The logic now simply uses today's date instead, which is always correct and works reliably across all environments.
7 changes: 7 additions & 0 deletions .changeset/vite-plugin-compat-date-today.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/vite-plugin": minor
---

Update `getLocalWorkerdCompatibilityDate` to return today's date

The re-exported `getLocalWorkerdCompatibilityDate` function from `@cloudflare/vite-plugin` previously resolved the workerd compatibility date by traversing the local `miniflare` installation, which was unreliable in some package manager setups. It now simply returns today's date. The function is also marked as deprecated — callers should just use today's date instead, for example like so: `new Date().toISOString().slice(0, 10)`
7 changes: 7 additions & 0 deletions .changeset/workers-utils-get-todays-date.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/workers-utils": minor
---

Add `getTodaysCompatDate()` utility function

Returns today's date as a `YYYY-MM-DD` string.
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { getLocalWorkerdCompatibilityDate } from "@cloudflare/workers-utils";
import {
getLatestTypesEntrypoint,
getWorkerdCompatibilityDate,
} from "helpers/compatDate";
import { afterEach, beforeEach, describe, test, vi } from "vitest";
import { beforeEach, describe, test, vi } from "vitest";
import { createTestContext } from "../../__tests__/helpers";
import { mockSpinner, mockWorkersTypesDirectory } from "./mocks";

vi.mock("helpers/files");
vi.mock("fs");
vi.mock("@cloudflare/cli/interactive");
vi.mock("@cloudflare/workers-utils");

describe("Compatibility Date Helpers", () => {
let spinner: ReturnType<typeof mockSpinner>;
Expand All @@ -19,41 +17,13 @@ describe("Compatibility Date Helpers", () => {
spinner = mockSpinner();
});

afterEach(() => {
vi.useRealTimers();
});

describe("getWorkerdCompatibilityDate()", () => {
test("normal flow", async ({ expect }) => {
vi.mocked(getLocalWorkerdCompatibilityDate).mockReturnValue({
date: "2025-01-10",
source: "workerd",
});

const date = getWorkerdCompatibilityDate("./my-app");

const expectedDate = "2025-01-10";
expect(date).toBe(expectedDate);
expect(spinner.start).toHaveBeenCalled();
expect(spinner.stop).toHaveBeenCalledWith(
expect.stringContaining(expectedDate)
);
});

test("fallback result", async ({ expect }) => {
vi.mocked(getLocalWorkerdCompatibilityDate).mockReturnValue({
date: "2025-09-27",
source: "fallback",
});

test("returns today's date", async ({ expect }) => {
const date = getWorkerdCompatibilityDate("./my-app");

const fallbackDate = "2025-09-27";
expect(date).toBe(fallbackDate);
expect(date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
expect(spinner.start).toHaveBeenCalled();
expect(spinner.stop).toHaveBeenCalledWith(
expect.stringContaining(fallbackDate)
);
expect(spinner.stop).toHaveBeenCalledWith(expect.stringContaining(date));
});
});

Expand Down
20 changes: 6 additions & 14 deletions packages/create-cloudflare/src/helpers/compatDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,21 @@ import { readdirSync } from "node:fs";
import { resolve } from "node:path";
import { brandColor, dim } from "@cloudflare/cli/colors";
import { spinner } from "@cloudflare/cli/interactive";
import { getLocalWorkerdCompatibilityDate } from "@cloudflare/workers-utils";
import { getTodaysCompatDate } from "@cloudflare/workers-utils";
import type { C3Context } from "types";

/**
* Retrieves the latest workerd compatibility date
* Retrieves the current date as a workerd compatibility date
*
* @returns The latest compatibility date for workerd in the form "YYYY-MM-DD"
* @returns Today's date in the form "YYYY-MM-DD"
*/
export function getWorkerdCompatibilityDate(projectPath: string) {
export function getWorkerdCompatibilityDate(_projectPath: string) {
const s = spinner();
s.start("Retrieving current workerd compatibility date");

const { date, source } = getLocalWorkerdCompatibilityDate({ projectPath });
const date = getTodaysCompatDate();

if (source === "fallback") {
s.stop(
`${brandColor("compatibility date")} ${dim(
` Could not find workerd date, falling back to ${date}`
)}`
);
} else {
s.stop(`${brandColor("compatibility date")} ${dim(date)}`);
}
s.stop(`${brandColor("compatibility date")} ${dim(date)}`);
return date;
}

Expand Down
33 changes: 3 additions & 30 deletions packages/miniflare/src/plugins/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Readable } from "node:stream";
import tls from "node:tls";
import { TextEncoder } from "node:util";
import { DEFAULT_CONTAINER_EGRESS_INTERCEPTOR_IMAGE } from "@cloudflare/containers-shared";
import { bold } from "kleur/colors";
import { getTodaysCompatDate } from "@cloudflare/workers-utils";
import { MockAgent } from "undici";
import SCRIPT_ENTRY from "worker:core/entry";
import STRIP_CF_CONNECTING_IP from "worker:core/strip-cf-connecting-ip";
Expand All @@ -17,7 +17,6 @@ import {
kVoid,
Service,
ServiceDesignator,
supportedCompatibilityDate,
Worker_Binding,
Worker_ContainerEngine,
Worker_DurableObjectNamespace,
Expand Down Expand Up @@ -110,7 +109,6 @@ if (process.env.NODE_EXTRA_CA_CERTS !== undefined) {
}

const encoder = new TextEncoder();
const numericCompare = new Intl.Collator(undefined, { numeric: true }).compare;

export function createFetchMock() {
return new MockAgent();
Expand Down Expand Up @@ -473,37 +471,13 @@ function maybeGetCustomServiceService(

const FALLBACK_COMPATIBILITY_DATE = "2000-01-01";

function getCurrentCompatibilityDate() {
// Get current compatibility date in UTC timezone
const now = new Date().toISOString();
return now.substring(0, now.indexOf("T"));
}

function validateCompatibilityDate(log: Log, compatibilityDate: string) {
if (numericCompare(compatibilityDate, getCurrentCompatibilityDate()) > 0) {
function validateCompatibilityDate(compatibilityDate: string) {
if (compatibilityDate > getTodaysCompatDate()) {
// If this compatibility date is in the future, throw
throw new MiniflareCoreError(
"ERR_FUTURE_COMPATIBILITY_DATE",
`Compatibility date "${compatibilityDate}" is in the future and unsupported`
);
} else if (
numericCompare(compatibilityDate, supportedCompatibilityDate) > 0
) {
// If this compatibility date is greater than the maximum supported
// compatibility date of the runtime, but not in the future, warn,
// and use the maximum supported date instead
log.warn(
[
"The latest compatibility date supported by the installed Cloudflare Workers Runtime is ",
bold(`"${supportedCompatibilityDate}"`),
",\nbut you've requested ",
bold(`"${compatibilityDate}"`),
". Falling back to ",
bold(`"${supportedCompatibilityDate}"`),
"...",
].join("")
);
return supportedCompatibilityDate;
}
return compatibilityDate;
}
Expand Down Expand Up @@ -773,7 +747,6 @@ export const CORE_PLUGIN: Plugin<
}

const compatibilityDate = validateCompatibilityDate(
log,
options.compatibilityDate ?? FALLBACK_COMPATIBILITY_DATE
);

Expand Down
7 changes: 6 additions & 1 deletion packages/miniflare/src/runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ export class Runtime {
ipcAddress: info.inspectorIpc || "",
pid: String(this.#process.pid),
scriptName: name,
inspectorURL: `ws://127.0.0.1:${ports?.get(kInspectorSocket)}/core:user:${name}`,
inspectorURL: `ws://127.0.0.1:${ports?.get(
kInspectorSocket
)}/core:user:${name}`,
waitForDebugger: true,
ownId: randomBytes(12).toString("hex"),
openerId: info.openerId,
Expand Down Expand Up @@ -363,4 +365,7 @@ function getSafeCompatibilityDate(): string {
return workerdCompatibilityDate;
}

/**
* @deprecated Use today's date as the compatibility date instead: `new Date().toISOString().slice(0, 10)`
Comment thread
petebacondarwin marked this conversation as resolved.
*/
export const supportedCompatibilityDate = getSafeCompatibilityDate();
20 changes: 19 additions & 1 deletion packages/vite-plugin-cloudflare/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getTodaysCompatDate } from "@cloudflare/workers-utils";
import { assertWranglerVersion } from "./assert-wrangler-version";
import { PluginContext } from "./context";
import { resolvePluginConfig } from "./plugin-config";
Expand All @@ -23,9 +24,26 @@ import { wasmHelperPlugin } from "./plugins/wasm";
import { debuglog } from "./utils";
import type { SharedContext } from "./context";
import type { PluginConfig } from "./plugin-config";
import type { CompatDate } from "@cloudflare/workers-utils";
import type * as vite from "vite";

export { getLocalWorkerdCompatibilityDate } from "@cloudflare/workers-utils";
// TODO: simplify this function in the next major release (DEVX-2533)
/**
* @deprecated Use today's date instead (as `YYYY-MM-DD`)
Comment thread
petebacondarwin marked this conversation as resolved.
*
* Gets the compatibility date to use with the local workerd version.
*
* Note: the function's signature is as is because it needs to be backward compatibly with
* a previous iteration of this, it will be simplified in the next major version of this package.
*
* @param _options Unused argument (present only for backward compatibility)
* @returns Object containing the compatibility date (this is not the date directly for backward compatibility)
*/
export function getLocalWorkerdCompatibilityDate(_options?: {
projectPath?: string;
}): { date: CompatDate; source: "workerd" | "fallback" } {
return { date: getTodaysCompatDate(), source: "workerd" };
}

export type { PluginConfig } from "./plugin-config";
export type { WorkerConfig } from "./workers-configs";
Expand Down
8 changes: 2 additions & 6 deletions packages/vite-plugin-cloudflare/src/plugin-config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as path from "node:path";
import { parseStaticRouting } from "@cloudflare/workers-shared/utils/configuration/parseStaticRouting";
import { getLocalWorkerdCompatibilityDate } from "@cloudflare/workers-utils";
import { getTodaysCompatDate } from "@cloudflare/workers-utils";
import { defu } from "defu";
import * as vite from "vite";
import * as wrangler from "wrangler";
Expand Down Expand Up @@ -244,11 +244,7 @@ function resolveWorkerConfig(
configCustomizer: options.configCustomizer,
});

const { date } = getLocalWorkerdCompatibilityDate({
projectPath: options.root,
});

workerConfig.compatibility_date ??= date;
workerConfig.compatibility_date ??= getTodaysCompatDate();

if (isEntryWorker) {
workerConfig.name ??= wrangler.unstable_getWorkerNameFromProject(
Expand Down
10 changes: 4 additions & 6 deletions packages/vitest-pool-workers/src/pool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { getTodaysCompatDate } from "@cloudflare/workers-utils";
import * as devalue from "devalue";
import getPort, { portNumbers } from "get-port";
import {
Expand All @@ -15,7 +16,6 @@ import {
Miniflare,
structuredSerializableReducers,
structuredSerializableRevivers,
supportedCompatibilityDate,
} from "miniflare";
import semverSatisfies from "semver/functions/satisfies.js";
import { experimental_readRawConfig } from "wrangler";
Expand Down Expand Up @@ -310,14 +310,12 @@ async function buildProjectWorkerOptions(
);

if (runnerWorker.compatibilityDate === undefined) {
// No compatibility date was provided, so infer the latest supported date
runnerWorker.compatibilityDate ??= supportedCompatibilityDate;
// No compatibility date was provided, so use today's date
runnerWorker.compatibilityDate = getTodaysCompatDate();
log.info(
`No compatibility date was provided for project ${getRelativeProjectPath(
project
)}, defaulting to latest supported date ${
runnerWorker.compatibilityDate
}.`
)}, defaulting to today's date ${runnerWorker.compatibilityDate}.`
);
}

Expand Down
Loading
Loading