From f3d671138f17b6c8e56a7244f12c1cb896ed6904 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Tue, 23 Jul 2024 16:33:21 +0100 Subject: [PATCH] Add header + caching to runtime type generation --- packages/wrangler/e2e/types.test.ts | 38 ++++++++++++++++++- .../wrangler/src/type-generation/index.ts | 3 +- .../src/type-generation/runtime/index.ts | 20 +++++++++- packages/wrangler/src/workerd.d.ts | 6 +++ 4 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 packages/wrangler/src/workerd.d.ts diff --git a/packages/wrangler/e2e/types.test.ts b/packages/wrangler/e2e/types.test.ts index 9437312f229b..2fb3a8a678fc 100644 --- a/packages/wrangler/e2e/types.test.ts +++ b/packages/wrangler/e2e/types.test.ts @@ -1,5 +1,5 @@ import { existsSync } from "node:fs"; -import { readFile } from "node:fs/promises"; +import { readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import { describe, expect, it } from "vitest"; import { dedent } from "../src/utils/dedent"; @@ -10,7 +10,7 @@ const seed = { name = "test-worker" main = "src/index.ts" compatibility_date = "2023-01-01" - compatibility_flags = ["nodejs_compat"] + compatibility_flags = ["nodejs_compat", "no_global_navigator"] `, "src/index.ts": dedent` export default { @@ -130,4 +130,38 @@ describe("types", () => { `📣 It looks like you have some Node.js compatibility turned on in your project. You might want to consider adding Node.js typings with "npm i --save-dev @types/node@20.8.3". Please see the docs for more details: https://developers.cloudflare.com/workers/languages/typescript/#transitive-loading-of-typesnode-overrides-cloudflareworkers-types` ); }); + it("should include header with version information in the generated types", async () => { + const helper = new WranglerE2ETestHelper(); + await helper.seed(seed); + await helper.run(`wrangler types --x-include-runtime="./types.d.ts"`); + + const file = ( + await readFile(path.join(helper.tmpPath, "./types.d.ts")) + ).toString(); + + expect(file.split("\n")[0]).match( + /\/\/ Runtime types generated with workerd@1\.\d+\.\d \d\d\d\d-\d\d-\d\d ([a-z_]+,?)*/ + ); + }); + it("should not regenerate types if the header matches", async () => { + const helper = new WranglerE2ETestHelper(); + await helper.seed(seed); + await helper.run(`wrangler types --x-include-runtime`); + + const runtimeTypesFile = path.join( + helper.tmpPath, + "./.wrangler/types/runtime.d.ts" + ); + const file = (await readFile(runtimeTypesFile)).toString(); + + const header = file.split("\n")[0]; + + await writeFile(runtimeTypesFile, header + "\n" + "SOME_RANDOM_DATA"); + + await helper.run(`wrangler types --x-include-runtime`); + + const file2 = (await readFile(runtimeTypesFile)).toString(); + + expect(file2.split("\n")[1]).toBe("SOME_RANDOM_DATA"); + }); }); diff --git a/packages/wrangler/src/type-generation/index.ts b/packages/wrangler/src/type-generation/index.ts index 4368459530ba..e598af83428f 100644 --- a/packages/wrangler/src/type-generation/index.ts +++ b/packages/wrangler/src/type-generation/index.ts @@ -489,8 +489,7 @@ function writeDTSFile({ fs.writeFileSync( path, [ - `// Generated by Wrangler on ${new Date()}`, - `// by running \`${wranglerCommandUsed}\``, + `// Generated by Wrangler by running \`${wranglerCommandUsed}\``, "", combinedTypeStrings, ].join("\n") diff --git a/packages/wrangler/src/type-generation/runtime/index.ts b/packages/wrangler/src/type-generation/runtime/index.ts index 8e4ecffa35fa..4d38ba55a35d 100644 --- a/packages/wrangler/src/type-generation/runtime/index.ts +++ b/packages/wrangler/src/type-generation/runtime/index.ts @@ -1,6 +1,8 @@ import { readFileSync } from "fs"; -import { writeFile } from "fs/promises"; +import { readFile, writeFile } from "fs/promises"; import { Miniflare } from "miniflare"; +import { version } from "workerd"; +import { logger } from "../../logger"; import { ensureDirectoryExists } from "../../utils/filesystem"; import type { Config } from "../../config/config"; @@ -47,12 +49,26 @@ export async function generateRuntimeTypes({ await ensureDirectoryExists(outFile); + const header = `// Runtime types generated with workerd@${version} ${compatibility_date} ${compatibility_flags.join(",")}`; + + try { + const existingTypes = await readFile(outFile, "utf8"); + if (existingTypes.split("\n")[0] === header) { + logger.debug("Using cached runtime types: ", header); + return { outFile }; + } + } catch (e) { + if ((e as { code: string }).code !== "ENOENT") { + throw e; + } + } + const types = await generate({ compatibilityDate: compatibility_date, compatibilityFlags: compatibility_flags, }); - await writeFile(outFile, types, "utf8"); + await writeFile(outFile, header + "\n" + types, "utf8"); return { outFile, diff --git a/packages/wrangler/src/workerd.d.ts b/packages/wrangler/src/workerd.d.ts new file mode 100644 index 000000000000..1b6e6e04e334 --- /dev/null +++ b/packages/wrangler/src/workerd.d.ts @@ -0,0 +1,6 @@ +declare module "workerd" { + const path: string; + export default path; + export const compatibilityDate: string; + export const version: string; +}