chore: import upstream snapshot with attribution
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:30:11 +08:00
commit 70bf21e064
5213 changed files with 731895 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
# @cloudflare/runtime-types
## 0.0.1
### Patch Changes
- Updated dependencies [[`1b965c5`](https://github.com/cloudflare/workers-sdk/commit/1b965c51babff16ae7657335d93badebd50c310f)]:
- miniflare@4.20260709.0
+45
View File
@@ -0,0 +1,45 @@
{
"name": "@cloudflare/runtime-types",
"version": "0.0.1",
"private": true,
"homepage": "https://github.com/cloudflare/workers-sdk/tree/main/packages/runtime-types#readme",
"bugs": {
"url": "https://github.com/cloudflare/workers-sdk/issues"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cloudflare/workers-sdk.git",
"directory": "packages/runtime-types"
},
"files": [
"dist"
],
"type": "module",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs"
}
},
"scripts": {
"build": "tsdown",
"check:type": "tsc",
"dev": "tsdown --watch",
"test:ci": "vitest run",
"test:watch": "vitest"
},
"dependencies": {
"miniflare": "workspace:*",
"workerd": "catalog:default"
},
"devDependencies": {
"@cloudflare/workers-tsconfig": "workspace:*",
"@cloudflare/workers-utils": "workspace:*",
"@types/node": "catalog:default",
"tsdown": "0.16.3",
"typescript": "catalog:default",
"vitest": "catalog:default"
}
}
@@ -0,0 +1,22 @@
import { describe, it } from "vitest";
import { getRuntimeHeader, RUNTIME_HEADER_COMMENT_PREFIX } from "../header";
describe("getRuntimeHeader", () => {
it("includes the workerd version and compatibility date", ({ expect }) => {
expect(getRuntimeHeader("1.0.0-test", "2024-11-06")).toBe(
`${RUNTIME_HEADER_COMMENT_PREFIX}1.0.0-test 2024-11-06 `
);
});
it("sorts compatibility flags alphabetically", ({ expect }) => {
expect(getRuntimeHeader("1.0.0-test", "2024-11-06", ["b", "a", "c"])).toBe(
`${RUNTIME_HEADER_COMMENT_PREFIX}1.0.0-test 2024-11-06 a,b,c`
);
});
it("defaults to no flags when none are provided", ({ expect }) => {
expect(getRuntimeHeader("1.0.0-test", "2024-11-06", [])).toBe(
`${RUNTIME_HEADER_COMMENT_PREFIX}1.0.0-test 2024-11-06 `
);
});
});
@@ -0,0 +1,162 @@
import { runInTempDir, seed } from "@cloudflare/workers-utils/test-helpers";
import { beforeEach, describe, it, vi } from "vitest";
import { getRuntimeHeader, RUNTIME_TYPES_MARKER } from "../header";
import { generateRuntimeTypes } from "../runtime";
const OUT_FILE = "worker-configuration.d.ts";
const WORKERD_VERSION = "1.0.0-test";
const { MiniflareMock, dispatchFetchMock, disposeMock } = vi.hoisted(() => {
const dispatch = vi.fn();
const dispose = vi.fn();
const constructor = vi.fn(function () {
return {
dispatchFetch: dispatch,
dispose: dispose,
};
});
return {
MiniflareMock: constructor,
dispatchFetchMock: dispatch,
disposeMock: dispose,
};
});
vi.mock("workerd", () => ({
// Must be a literal: vi.mock factories are hoisted above top-level variables.
version: "1.0.0-test",
default: "/fake/workerd",
}));
vi.mock("miniflare", () => ({ Miniflare: MiniflareMock }));
describe("generateRuntimeTypes", () => {
runInTempDir();
beforeEach(() => {
vi.clearAllMocks();
dispatchFetchMock.mockResolvedValue({
ok: true,
text: async () => "GENERATED",
});
});
it("generates types when the out file does not exist (cache miss)", async ({
expect,
}) => {
const result = await generateRuntimeTypes({
compatibilityDate: "2024-11-06",
outFile: OUT_FILE,
});
expect(result).toEqual({
runtimeHeader: getRuntimeHeader(WORKERD_VERSION, "2024-11-06", []),
runtimeTypes: "GENERATED",
isCached: false,
});
expect(MiniflareMock).toHaveBeenCalledTimes(1);
});
it("strips nodejs_compat flags from the dispatch URL but keeps them in the header", async ({
expect,
}) => {
const result = await generateRuntimeTypes({
compatibilityDate: "2024-11-06",
compatibilityFlags: ["nodejs_compat", "flag_b", "flag_a"],
outFile: OUT_FILE,
});
// nodejs_compat flags are stripped from the dispatch URL; the remaining
// flags keep their original caller-provided order.
expect(dispatchFetchMock).toHaveBeenCalledWith(
"http://dummy.com/2024-11-06+flag_b+flag_a"
);
expect(result.runtimeHeader).toBe(
getRuntimeHeader(WORKERD_VERSION, "2024-11-06", [
"nodejs_compat",
"flag_b",
"flag_a",
])
);
});
it("returns cached types when the header and marker match", async ({
expect,
}) => {
const header = getRuntimeHeader(WORKERD_VERSION, "2024-11-06", ["flag_a"]);
await seed({
[OUT_FILE]: `${header}\nsome preamble\n${RUNTIME_TYPES_MARKER}\nCACHED TYPES\nmore`,
});
const result = await generateRuntimeTypes({
compatibilityDate: "2024-11-06",
compatibilityFlags: ["flag_a"],
outFile: OUT_FILE,
});
expect(result).toEqual({
runtimeHeader: header,
runtimeTypes: "CACHED TYPES\nmore",
isCached: true,
});
expect(MiniflareMock).not.toHaveBeenCalled();
});
it("regenerates when the cached header is stale", async ({ expect }) => {
const staleHeader = getRuntimeHeader(WORKERD_VERSION, "2020-01-01", []);
await seed({
[OUT_FILE]: `${staleHeader}\n${RUNTIME_TYPES_MARKER}\nOLD`,
});
const result = await generateRuntimeTypes({
compatibilityDate: "2024-11-06",
outFile: OUT_FILE,
});
expect(result.isCached).toBe(false);
expect(result.runtimeTypes).toBe("GENERATED");
expect(MiniflareMock).toHaveBeenCalledTimes(1);
});
it("regenerates when the marker is missing even if the header matches", async ({
expect,
}) => {
const header = getRuntimeHeader(WORKERD_VERSION, "2024-11-06", []);
await seed({ [OUT_FILE]: `${header}\nNO MARKER HERE` });
const result = await generateRuntimeTypes({
compatibilityDate: "2024-11-06",
outFile: OUT_FILE,
});
expect(result.isCached).toBe(false);
expect(MiniflareMock).toHaveBeenCalledTimes(1);
});
it("rejects and still disposes Miniflare when the response is not ok", async ({
expect,
}) => {
dispatchFetchMock.mockResolvedValue({
ok: false,
text: async () => "boom",
});
await expect(
generateRuntimeTypes({
compatibilityDate: "2024-11-06",
outFile: OUT_FILE,
})
).rejects.toThrow("boom");
expect(disposeMock).toHaveBeenCalledTimes(1);
});
it("rethrows non-ENOENT read errors without generating", async ({
expect,
}) => {
// Passing a directory as the out file triggers EISDIR on read.
await expect(
generateRuntimeTypes({ compatibilityDate: "2024-11-06", outFile: "." })
).rejects.toThrow();
expect(MiniflareMock).not.toHaveBeenCalled();
});
});
+25
View File
@@ -0,0 +1,25 @@
/**
* Prefix of the comment written above the generated runtime types. Used to
* detect when runtime types need to be regenerated (the full header encodes the
* workerd version, compatibility date and flags).
*/
export const RUNTIME_HEADER_COMMENT_PREFIX =
"// Runtime types generated with workerd@";
/**
* Marker line written immediately before the generated runtime types. Used to
* locate the start of the runtime section within a combined `.d.ts` file.
*/
export const RUNTIME_TYPES_MARKER = "// Begin runtime types";
/**
* Generates the runtime header string used in the generated types file.
* This header is used to detect when runtime types need to be regenerated.
*/
export function getRuntimeHeader(
workerdVersion: string,
compatibilityDate: string,
compatibilityFlags: string[] = []
): string {
return `${RUNTIME_HEADER_COMMENT_PREFIX}${workerdVersion} ${compatibilityDate} ${[...compatibilityFlags].sort().join(",")}`;
}
+6
View File
@@ -0,0 +1,6 @@
export {
getRuntimeHeader,
RUNTIME_HEADER_COMMENT_PREFIX,
RUNTIME_TYPES_MARKER,
} from "./header";
export { generateRuntimeTypes } from "./runtime";
+132
View File
@@ -0,0 +1,132 @@
import * as fsp from "node:fs/promises";
import { createRequire } from "node:module";
import { Miniflare } from "miniflare";
import { version } from "workerd";
import {
getRuntimeHeader,
RUNTIME_HEADER_COMMENT_PREFIX,
RUNTIME_TYPES_MARKER,
} from "./header";
// `require.resolve` is not available in native ESM, so reconstruct it from the
// current module URL. This resolves correctly both when this package is run
// directly (ESM) and when it is bundled into a consumer.
const require = createRequire(import.meta.url);
/**
* Generates runtime types for a Workers project based on the provided compatibility settings.
*
* This function is designed to be isolated and portable, making it easy to integrate into various
* build processes or development workflows. It handles the whole process of generating runtime
* types, from spawning the workerd process (via Miniflare) to returning the generated types.
*
* If an `outFile` already contains runtime types generated for the same workerd version,
* compatibility date and flags, the cached types are returned instead of regenerating them.
*
* @example
* import { generateRuntimeTypes } from "@cloudflare/runtime-types";
*
* const { runtimeHeader, runtimeTypes, isCached } = await generateRuntimeTypes({
* compatibilityDate: "2024-11-06",
* compatibilityFlags: ["nodejs_compat"],
* outFile: "worker-configuration.d.ts",
* });
*
* @remarks
* `nodejs_compat` flags are ignored as there is currently no mechanism to generate these
* dynamically; consumers should instead prompt users to install `@types/node`.
*/
export async function generateRuntimeTypes({
compatibilityDate,
compatibilityFlags = [],
outFile,
}: {
compatibilityDate: string;
compatibilityFlags?: string[];
outFile: string;
}): Promise<{
runtimeHeader: string;
runtimeTypes: string;
isCached: boolean;
}> {
const header = getRuntimeHeader(
version,
compatibilityDate,
compatibilityFlags
);
try {
const lines = (await fsp.readFile(outFile, "utf8")).split("\n");
const existingHeader = lines.find((line) =>
line.startsWith(RUNTIME_HEADER_COMMENT_PREFIX)
);
const existingTypesStart = lines.findIndex(
(line) => line === RUNTIME_TYPES_MARKER
);
if (existingHeader === header && existingTypesStart !== -1) {
return {
runtimeHeader: header,
runtimeTypes: lines.slice(existingTypesStart + 1).join("\n"),
isCached: true,
};
}
} catch (e) {
if ((e as { code: string }).code !== "ENOENT") {
throw e;
}
}
const types = await generate({
compatibilityDate,
// Ignore nodejs compat flags as there is currently no mechanism to generate these dynamically.
compatibilityFlags: compatibilityFlags.filter(
(flag) => !flag.includes("nodejs_compat")
),
});
return { runtimeHeader: header, runtimeTypes: types, isCached: false };
}
/**
* Generates runtime types for Cloudflare Workers by spawning a workerd process with the type-generation
* worker, and then making a request to that worker to fetch types.
*/
async function generate({
compatibilityDate,
compatibilityFlags = [],
}: {
compatibilityDate: string;
compatibilityFlags?: string[];
}) {
const worker = (
await fsp.readFile(require.resolve("workerd/worker.mjs"))
).toString();
const mf = new Miniflare({
// Must stay before the 2024-09-23 nodejs_compat v1->v2 switchover: the
// workerd RTTI worker only runs under nodejs_compat v1. This date is
// internal to type generation and never appears in the output/header.
compatibilityDate: "2024-01-01",
compatibilityFlags: ["nodejs_compat", "rtti_api"],
modules: true,
script: worker,
});
const flagsString = compatibilityFlags.length
? `+${compatibilityFlags.join("+")}`
: "";
const path = `http://dummy.com/${compatibilityDate}${flagsString}`;
try {
const res = await mf.dispatchFetch(path);
const text = await res.text();
if (!res.ok) {
throw new Error(text);
}
return text;
} finally {
await mf.dispose();
}
}
+6
View File
@@ -0,0 +1,6 @@
declare module "workerd" {
const path: string;
export default path;
export const compatibilityDate: string;
export const version: string;
}
+7
View File
@@ -0,0 +1,7 @@
{
"extends": "@cloudflare/workers-tsconfig/base.json",
"compilerOptions": {
"types": ["@types/node"]
},
"include": ["src"]
}
+11
View File
@@ -0,0 +1,11 @@
import { defineConfig } from "tsdown";
export default defineConfig({
entry: {
index: "src/index.ts",
},
platform: "node",
outDir: "dist",
dts: true,
tsconfig: "tsconfig.json",
});
+9
View File
@@ -0,0 +1,9 @@
{
"$schema": "http://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"outputs": ["dist/**"]
}
}
}
+8
View File
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["**/__tests__/**/*.test.ts"],
reporters: ["default"],
},
});