From 9a037bae956ce5a3f4210b98bb37a45ceaf4ed72 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:46:38 +0100 Subject: [PATCH 01/17] add option to use generated types --- packages/create-cloudflare/src/cli.ts | 7 +- packages/create-cloudflare/src/templates.ts | 6 + packages/create-cloudflare/src/workers.ts | 137 +++++++++++++------- 3 files changed, 101 insertions(+), 49 deletions(-) diff --git a/packages/create-cloudflare/src/cli.ts b/packages/create-cloudflare/src/cli.ts index 8872387a49af..50ad53bde3c3 100644 --- a/packages/create-cloudflare/src/cli.ts +++ b/packages/create-cloudflare/src/cli.ts @@ -34,7 +34,7 @@ import { updatePackageScripts, } from "./templates"; import { validateProjectDirectory } from "./validators"; -import { installWorkersTypes } from "./workers"; +import { generateWorkersTypes, installWorkersTypes } from "./workers"; import { updateWranglerConfig } from "./wrangler/config"; import type { C3Args, C3Context } from "types"; @@ -154,7 +154,6 @@ const configure = async (ctx: C3Context) => { startSection("Configuring your application for Cloudflare", "Step 2 of 3"); await installWrangler(); - await installWorkersTypes(ctx); // Note: This _must_ be called before the configure phase since // pre-existing workers assume its presence in their configure phase @@ -168,6 +167,10 @@ const configure = async (ctx: C3Context) => { addWranglerToGitIgnore(ctx); await updatePackageScripts(ctx); + if (ctx.template.installWorkersTypes) { + await installWorkersTypes(ctx); + } + await generateWorkersTypes(ctx); await offerGit(ctx); await gitCommit(ctx); diff --git a/packages/create-cloudflare/src/templates.ts b/packages/create-cloudflare/src/templates.ts index fcb8f52be662..8606c80f5b6c 100644 --- a/packages/create-cloudflare/src/templates.ts +++ b/packages/create-cloudflare/src/templates.ts @@ -142,10 +142,16 @@ export type TemplateConfig = { /** The key of the package.json "scripts" entry for previewing the project. Defaults to undefined (there might not be such script) */ previewScript?: string; + /** The file path to the generated types file. Defaults to worker-configuration.d.ts*/ + typesPath?: string; + /** The file path of the template. This is used internally and isn't a user facing config value.*/ path?: string; bindings?: Record; + + /** Don't generate types, use @cloudflare/workers-types instead. Usually because the framework is pinned to Wrangler 3. Default false. */ + installWorkersTypes?: boolean; }; type CopyFiles = (StaticFileMap | VariantInfo) & { diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 30d73c24e2c4..ebc485f520d6 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -1,74 +1,103 @@ import { existsSync } from "fs"; -import { join } from "path"; +import { join, resolve } from "path"; import { warn } from "@cloudflare/cli"; import { brandColor, dim } from "@cloudflare/cli/colors"; -import { spinner } from "@cloudflare/cli/interactive"; +import { runCommand } from "helpers/command"; import { getLatestTypesEntrypoint } from "helpers/compatDate"; -import { readFile, usesTypescript, writeFile } from "helpers/files"; +import { readFile, readJSON, usesTypescript, writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; import * as jsonc from "jsonc-parser"; -import type { C3Context } from "types"; +import type { C3Context, PackageJson } from "types"; /** - * Installs the latest version of the `@cloudflare/workers-types` package - * and updates the .tsconfig file to use the latest entrypoint version. + * Generate types using `wrangler types` and update tsconfig */ -export async function installWorkersTypes(ctx: C3Context) { - const { npm } = detectPackageManager(); +export async function generateWorkersTypes(ctx: C3Context) { if (!usesTypescript(ctx)) { return; } + const packageJsonPath = resolve("package.json"); + const packageManifest = readJSON(packageJsonPath) as PackageJson; + if (!Object.keys(packageManifest.scripts ?? {}).includes("cf-typegen")) { + return; + } - await installPackages(["@cloudflare/workers-types"], { - dev: true, - startText: "Installing @cloudflare/workers-types", - doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, + const { npm } = detectPackageManager(); + + const typesCmd = [npm, "run", "cf-typegen"]; + + await runCommand(typesCmd, { + cwd: ctx.project.path, + silent: true, + env: { + CLOUDFLARE_ACCOUNT_ID: ctx.account?.id, + NODE_ENV: "production", + }, + startText: "Generating types for your application", + doneText: `${brandColor("generated")} ${dim(`to \`${ctx.template.typesPath ?? "worker-configuration.d.ts"}\` via \`${typesCmd.join(" ")}\``)}`, }); - await addWorkersTypesToTsConfig(ctx); + + if (ctx.template.compatibilityFlags?.includes("nodejs_compat")) { + await installPackages(["@types/node"], { + dev: true, + startText: "Installing @types/node", + doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, + }); + } + + delete packageManifest["devDependencies"]?.["@cloudflare/workers-types"]; + + writeFile(packageJsonPath, JSON.stringify(packageManifest, null, 2)); + await updateTsConfig(ctx); } -export async function addWorkersTypesToTsConfig(ctx: C3Context) { +export async function updateTsConfig(ctx: C3Context) { const tsconfigPath = join(ctx.project.path, "tsconfig.json"); if (!existsSync(tsconfigPath)) { return; } - const s = spinner(); - s.start("Adding latest types to `tsconfig.json`"); - const tsconfig = readFile(tsconfigPath); - const entrypointVersion = getLatestTypesEntrypoint(ctx); - if (entrypointVersion === null) { - s.stop( - `${brandColor( - "skipped", - )} couldn't find latest compatible version of @cloudflare/workers-types`, - ); - return; - } - - const typesEntrypoint = `@cloudflare/workers-types/${entrypointVersion}`; try { const config = jsonc.parse(tsconfig); const currentTypes = config.compilerOptions?.types ?? []; - - const explicitEntrypoint = (currentTypes as string[]).some((t) => - t.match(/@cloudflare\/workers-types\/\d{4}-\d{2}-\d{2}/), - ); - - // If a type declaration with an explicit entrypoint exists, leave the types as is - // Otherwise, add the latest entrypoint - const newTypes = explicitEntrypoint - ? [...currentTypes] - : [ - ...currentTypes.filter( - (t: string) => t !== "@cloudflare/workers-types", - ), - typesEntrypoint, - ]; + let newTypes: string[]; + if (ctx.template.installWorkersTypes) { + const entrypointVersion = getLatestTypesEntrypoint(ctx); + if (entrypointVersion === null) { + return; + } + const typesEntrypoint = `@cloudflare/workers-types/${entrypointVersion}`; + const explicitEntrypoint = (currentTypes as string[]).some((t) => + t.match(/@cloudflare\/workers-types\/\d{4}-\d{2}-\d{2}/), + ); + // If a type declaration with an explicit entrypoint exists, leave the types as is + // Otherwise, add the latest entrypoint + newTypes = explicitEntrypoint + ? [...currentTypes] + : [ + ...currentTypes.filter( + (t: string) => t !== "@cloudflare/workers-types", + ), + typesEntrypoint, + ]; + } else { + newTypes = [ + ...currentTypes.filter( + (t: string) => !t.startsWith("@cloudflare/workers-types"), + ), + ctx.template.typesPath ?? "./worker-configuration.d.ts", + ...(ctx.template.compatibilityFlags?.includes("nodejs_compat") + ? ["node"] + : []), + ]; + } + if (newTypes.sort() === currentTypes.sort()) { + return; + } // If we detect any tabs, use tabs, otherwise use spaces. // We need to pass an explicit value here in order to preserve formatting properly. @@ -86,10 +115,24 @@ export async function addWorkersTypesToTsConfig(ctx: C3Context) { const updated = jsonc.applyEdits(tsconfig, edits); writeFile(tsconfigPath, updated); } catch (error) { - warn( - "Failed to update `tsconfig.json` with latest `@cloudflare/workers-types` entrypoint.", - ); + warn("Failed to update `tsconfig.json`."); } +} - s.stop(`${brandColor("added")} ${dim(typesEntrypoint)}`); +/** + * Installs the latest version of the `@cloudflare/workers-types` package + * and updates the .tsconfig file to use the latest entrypoint version. + */ +export async function installWorkersTypes(ctx: C3Context) { + if (!usesTypescript(ctx)) { + return; + } + const { npm } = detectPackageManager(); + + await installPackages(["@cloudflare/workers-types"], { + dev: true, + startText: "Installing @cloudflare/workers-types", + doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, + }); + await updateTsConfig(ctx); } From 84d3e903fb252d31d39812a11a5b4c93853b36a0 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:47:42 +0100 Subject: [PATCH 02/17] update templates --- .../templates-experimental/solid/c3.ts | 1 + .../create-cloudflare/templates/analog/c3.ts | 24 ---------------- .../templates/analog/templates/env.d.ts | 2 +- .../templates/worker-configuration.d.ts | 4 --- .../templates/angular/pages/c3.ts | 6 ++-- .../angular/pages/templates/wrangler.jsonc | 5 ++++ .../templates/angular/workers/c3.ts | 1 + .../templates/ts/worker-configuration.d.ts | 4 --- .../templates/common/ts/tsconfig.json | 3 -- .../common/ts/worker-configuration.d.ts | 4 --- .../templates/docusaurus/pages/c3.ts | 1 + .../templates/docusaurus/workers/c3.ts | 1 + .../templates/gatsby/pages/c3.ts | 1 + .../templates/gatsby/workers/c3.ts | 1 + .../ts/tsconfig.json | 2 -- .../ts/worker-configuration.d.ts | 8 ------ .../ts/tsconfig.json | 2 -- .../ts/worker-configuration.d.ts | 7 ----- .../templates/hello-world-with-assets/c3.ts | 1 + .../ts/test/tsconfig.json | 2 +- .../hello-world-with-assets/ts/tsconfig.json | 2 -- .../ts/worker-configuration.d.ts | 7 ----- .../hello-world/ts/test/index.spec.ts | 1 - .../hello-world/ts/test/tsconfig.json | 2 +- .../templates/hello-world/ts/tsconfig.json | 2 -- .../hello-world/ts/worker-configuration.d.ts | 8 ------ .../pages/templates/worker-configuration.d.ts | 4 --- .../templates/worker-configuration.d.ts | 4 --- .../templates/next/pages/c3.ts | 2 +- .../templates/next/workers/c3.ts | 4 ++- .../workers/templates/cloudflare-env.d.ts | 5 ---- .../templates/nuxt/pages/c3.ts | 28 ++----------------- .../templates/nuxt/pages/templates/env.d.ts | 2 +- .../pages/templates/worker-configuration.d.ts | 4 --- .../templates/nuxt/workers/c3.ts | 28 ++----------------- .../templates/nuxt/workers/templates/env.d.ts | 2 +- .../templates/worker-configuration.d.ts | 4 --- .../templates/openapi/ts/tsconfig.json | 1 - .../openapi/ts/worker-configuration.d.ts | 4 --- .../templates/queues/ts/tsconfig.json | 2 -- .../queues/ts/worker-configuration.d.ts | 5 ---- .../templates/qwik/pages/c3.ts | 1 + .../pages/templates/worker-configuration.d.ts | 4 --- .../templates/qwik/workers/c3.ts | 1 + .../templates/worker-configuration.d.ts | 4 --- .../templates/react-router/c3.ts | 12 -------- .../templates/worker-configuration.d.ts | 8 ------ .../templates/react/pages/c3.ts | 6 ++-- .../react/pages/templates/wrangler.jsonc | 5 ++++ .../react/workers/ts/tsconfig.worker.json | 2 +- .../workers/ts/worker-configuration.d.ts | 5 ---- .../templates/remix/pages/c3.ts | 1 + .../pages/templates/worker-configuration.d.ts | 4 --- .../templates/remix/workers/c3.ts | 1 + .../templates/worker-configuration.d.ts | 4 --- .../templates/scheduled/ts/tsconfig.json | 2 -- .../scheduled/ts/worker-configuration.d.ts | 4 --- .../create-cloudflare/templates/solid/c3.ts | 1 + .../templates/svelte/pages/c3.ts | 5 ++-- .../templates/svelte/workers/c3.ts | 5 ++-- .../templates/vue/pages/c3.ts | 8 ++++-- .../vue/pages/templates/wrangler.jsonc | 5 ++++ .../vue/workers/ts/tsconfig.worker.json | 2 +- .../vue/workers/ts/worker-configuration.d.ts | 6 ---- 64 files changed, 58 insertions(+), 239 deletions(-) delete mode 100644 packages/create-cloudflare/templates/analog/templates/worker-configuration.d.ts create mode 100644 packages/create-cloudflare/templates/angular/pages/templates/wrangler.jsonc delete mode 100644 packages/create-cloudflare/templates/astro/workers/templates/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/common/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/hello-world-durable-object/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/hello-world-with-assets/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/hello-world/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/hono/pages/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/hono/workers/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/next/workers/templates/cloudflare-env.d.ts delete mode 100644 packages/create-cloudflare/templates/nuxt/pages/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/nuxt/workers/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/openapi/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/queues/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/react-router/templates/worker-configuration.d.ts create mode 100644 packages/create-cloudflare/templates/react/pages/templates/wrangler.jsonc delete mode 100644 packages/create-cloudflare/templates/react/workers/ts/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts delete mode 100644 packages/create-cloudflare/templates/scheduled/ts/worker-configuration.d.ts create mode 100644 packages/create-cloudflare/templates/vue/pages/templates/wrangler.jsonc delete mode 100644 packages/create-cloudflare/templates/vue/workers/ts/worker-configuration.d.ts diff --git a/packages/create-cloudflare/templates-experimental/solid/c3.ts b/packages/create-cloudflare/templates-experimental/solid/c3.ts index 088774a570f0..ca7f71603325 100644 --- a/packages/create-cloudflare/templates-experimental/solid/c3.ts +++ b/packages/create-cloudflare/templates-experimental/solid/c3.ts @@ -84,6 +84,7 @@ const config: TemplateConfig = { scripts: { preview: `${npm} run build && npx wrangler dev`, deploy: `${npm} run build && wrangler deploy`, + "cf-typegen": `wrangler types`, }, }), compatibilityFlags: ["nodejs_compat"], diff --git a/packages/create-cloudflare/templates/analog/c3.ts b/packages/create-cloudflare/templates/analog/c3.ts index 1df940eb00ae..1b6fdada7cf2 100644 --- a/packages/create-cloudflare/templates/analog/c3.ts +++ b/packages/create-cloudflare/templates/analog/c3.ts @@ -3,8 +3,6 @@ import { brandColor, dim } from "@cloudflare/cli/colors"; import { spinner } from "@cloudflare/cli/interactive"; import { runFrameworkGenerator } from "frameworks/index"; import { loadTemplateSnippets, transformFile } from "helpers/codemod"; -import { getLatestTypesEntrypoint } from "helpers/compatDate"; -import { readFile, writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; import * as recast from "recast"; @@ -40,28 +38,6 @@ const configure = async (ctx: C3Context) => { } updateViteConfig(ctx); - updateEnvTypes(ctx); -}; - -const updateEnvTypes = (ctx: C3Context) => { - const filepath = "env.d.ts"; - - const s = spinner(); - s.start(`Updating ${filepath}`); - - let file = readFile(filepath); - - let typesEntrypoint = `@cloudflare/workers-types`; - const latestEntrypoint = getLatestTypesEntrypoint(ctx); - if (latestEntrypoint) { - typesEntrypoint += `/${latestEntrypoint}`; - } - - // Replace placeholder with actual types entrypoint - file = file.replace("WORKERS_TYPES_ENTRYPOINT", typesEntrypoint); - writeFile("env.d.ts", file); - - s.stop(`${brandColor(`updated`)} ${dim(`\`${filepath}\``)}`); }; const updateViteConfig = (ctx: C3Context) => { diff --git a/packages/create-cloudflare/templates/analog/templates/env.d.ts b/packages/create-cloudflare/templates/analog/templates/env.d.ts index adbc5cbd9fa6..d56c6a19b136 100644 --- a/packages/create-cloudflare/templates/analog/templates/env.d.ts +++ b/packages/create-cloudflare/templates/analog/templates/env.d.ts @@ -1,4 +1,4 @@ -/// +/// declare module "h3" { interface H3EventContext { diff --git a/packages/create-cloudflare/templates/analog/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/analog/templates/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/analog/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/angular/pages/c3.ts b/packages/create-cloudflare/templates/angular/pages/c3.ts index 456e33590f51..ea13e5673e74 100644 --- a/packages/create-cloudflare/templates/angular/pages/c3.ts +++ b/packages/create-cloudflare/templates/angular/pages/c3.ts @@ -3,7 +3,6 @@ import { logRaw } from "@cloudflare/cli"; import { brandColor, dim } from "@cloudflare/cli/colors"; import { spinner } from "@cloudflare/cli/interactive"; import { runFrameworkGenerator } from "frameworks/index"; -import { compatDateFlag } from "helpers/compatDate"; import { readFile, readJSON, writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; @@ -107,10 +106,11 @@ const config: TemplateConfig = { configure, transformPackageJson: async () => ({ scripts: { - start: `${npm} run build && wrangler pages dev dist/cloudflare ${await compatDateFlag()}`, + start: `${npm} run build && wrangler pages dev`, build: `ng build && ${npm} run process`, process: "node ./tools/copy-files.mjs", - deploy: `${npm} run build && wrangler pages deploy dist/cloudflare`, + deploy: `${npm} run build && wrangler pages deploy`, + "cf-typegen": `wrangler types`, }, }), }; diff --git a/packages/create-cloudflare/templates/angular/pages/templates/wrangler.jsonc b/packages/create-cloudflare/templates/angular/pages/templates/wrangler.jsonc new file mode 100644 index 000000000000..61c73b85f831 --- /dev/null +++ b/packages/create-cloudflare/templates/angular/pages/templates/wrangler.jsonc @@ -0,0 +1,5 @@ +{ + "name": "", + "compatibility_date": "", + "pages_build_output_dir": "./dist/cloudflare" + } diff --git a/packages/create-cloudflare/templates/angular/workers/c3.ts b/packages/create-cloudflare/templates/angular/workers/c3.ts index 98f73e30de61..4e19a678caa5 100644 --- a/packages/create-cloudflare/templates/angular/workers/c3.ts +++ b/packages/create-cloudflare/templates/angular/workers/c3.ts @@ -106,6 +106,7 @@ const config: TemplateConfig = { start: `${npm} run build && wrangler dev`, build: `ng build`, deploy: `${npm} run build && wrangler deploy`, + "cf-typegen": `wrangler types`, }, }), }; diff --git a/packages/create-cloudflare/templates/astro/workers/templates/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/astro/workers/templates/ts/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/astro/workers/templates/ts/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/common/ts/tsconfig.json b/packages/create-cloudflare/templates/common/ts/tsconfig.json index b8633da91901..b5dd586e4ce2 100644 --- a/packages/create-cloudflare/templates/common/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/common/ts/tsconfig.json @@ -16,9 +16,6 @@ /* Enable importing .json files */ "resolveJsonModule": true, - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], - /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ "allowJs": true, /* Enable error reporting in type-checked JavaScript files. */ diff --git a/packages/create-cloudflare/templates/common/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/common/ts/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/common/ts/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/docusaurus/pages/c3.ts b/packages/create-cloudflare/templates/docusaurus/pages/c3.ts index cdd0e5358ee5..5661d3b53142 100644 --- a/packages/create-cloudflare/templates/docusaurus/pages/c3.ts +++ b/packages/create-cloudflare/templates/docusaurus/pages/c3.ts @@ -27,5 +27,6 @@ const config: TemplateConfig = { devScript: "preview", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/docusaurus/workers/c3.ts b/packages/create-cloudflare/templates/docusaurus/workers/c3.ts index 1bf70ac2cccf..6a94696ad61f 100644 --- a/packages/create-cloudflare/templates/docusaurus/workers/c3.ts +++ b/packages/create-cloudflare/templates/docusaurus/workers/c3.ts @@ -29,5 +29,6 @@ const config: TemplateConfig = { devScript: "start", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/gatsby/pages/c3.ts b/packages/create-cloudflare/templates/gatsby/pages/c3.ts index 9cf83507cc1d..28b10923ec62 100644 --- a/packages/create-cloudflare/templates/gatsby/pages/c3.ts +++ b/packages/create-cloudflare/templates/gatsby/pages/c3.ts @@ -47,5 +47,6 @@ const config: TemplateConfig = { devScript: "develop", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/gatsby/workers/c3.ts b/packages/create-cloudflare/templates/gatsby/workers/c3.ts index c079a1d7ed57..ce40d51a42ac 100644 --- a/packages/create-cloudflare/templates/gatsby/workers/c3.ts +++ b/packages/create-cloudflare/templates/gatsby/workers/c3.ts @@ -49,5 +49,6 @@ const config: TemplateConfig = { devScript: "develop", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/tsconfig.json b/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/tsconfig.json index 26376384f509..2e3a41447194 100644 --- a/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/tsconfig.json @@ -13,8 +13,6 @@ "module": "es2022", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "node", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], /* Enable importing .json files */ "resolveJsonModule": true, diff --git a/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/worker-configuration.d.ts deleted file mode 100644 index 7dd159f208a0..000000000000 --- a/packages/create-cloudflare/templates/hello-world-durable-object-with-assets/ts/worker-configuration.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated by Wrangler by running `wrangler types --include-runtime=false` (hash: 24be54e90498ce3774054fcb8bb2bc1a) -declare namespace Cloudflare { - interface Env { - MY_DURABLE_OBJECT: DurableObjectNamespace; - ASSETS: Fetcher; - } -} -interface Env extends Cloudflare.Env {} diff --git a/packages/create-cloudflare/templates/hello-world-durable-object/ts/tsconfig.json b/packages/create-cloudflare/templates/hello-world-durable-object/ts/tsconfig.json index cb0ed78a428c..3aedb947da23 100644 --- a/packages/create-cloudflare/templates/hello-world-durable-object/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/hello-world-durable-object/ts/tsconfig.json @@ -13,8 +13,6 @@ "module": "es2022", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "node", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], /* Enable importing .json files */ "resolveJsonModule": true, diff --git a/packages/create-cloudflare/templates/hello-world-durable-object/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/hello-world-durable-object/ts/worker-configuration.d.ts deleted file mode 100644 index b1b571eacb32..000000000000 --- a/packages/create-cloudflare/templates/hello-world-durable-object/ts/worker-configuration.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Generated by Wrangler by running `wrangler types --include-runtime=false` (hash: 4c81d17e8de07f650cddf73ce751ba8d) -declare namespace Cloudflare { - interface Env { - MY_DURABLE_OBJECT: DurableObjectNamespace; - } -} -interface Env extends Cloudflare.Env {} diff --git a/packages/create-cloudflare/templates/hello-world-with-assets/c3.ts b/packages/create-cloudflare/templates/hello-world-with-assets/c3.ts index ffe12542727d..64bc1e4edeb8 100644 --- a/packages/create-cloudflare/templates/hello-world-with-assets/c3.ts +++ b/packages/create-cloudflare/templates/hello-world-with-assets/c3.ts @@ -21,5 +21,6 @@ const config: TemplateConfig = { }, }, }, + compatibilityFlags: ["nodejs_compat"], }; export default config; diff --git a/packages/create-cloudflare/templates/hello-world-with-assets/ts/test/tsconfig.json b/packages/create-cloudflare/templates/hello-world-with-assets/ts/test/tsconfig.json index 7fc4362899ec..978ecd87b7ce 100644 --- a/packages/create-cloudflare/templates/hello-world-with-assets/ts/test/tsconfig.json +++ b/packages/create-cloudflare/templates/hello-world-with-assets/ts/test/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "types": ["@cloudflare/workers-types/experimental", "@cloudflare/vitest-pool-workers"] + "types": ["@cloudflare/vitest-pool-workers"] }, "include": ["./**/*.ts", "../worker-configuration.d.ts"], "exclude": [] diff --git a/packages/create-cloudflare/templates/hello-world-with-assets/ts/tsconfig.json b/packages/create-cloudflare/templates/hello-world-with-assets/ts/tsconfig.json index c9aae166737a..d2f8744883d7 100644 --- a/packages/create-cloudflare/templates/hello-world-with-assets/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/hello-world-with-assets/ts/tsconfig.json @@ -13,8 +13,6 @@ "module": "es2022", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "Bundler", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], /* Enable importing .json files */ "resolveJsonModule": true, diff --git a/packages/create-cloudflare/templates/hello-world-with-assets/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/hello-world-with-assets/ts/worker-configuration.d.ts deleted file mode 100644 index 46fbe93fc125..000000000000 --- a/packages/create-cloudflare/templates/hello-world-with-assets/ts/worker-configuration.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Generated by Wrangler by running `wrangler types --include-runtime=false` (hash: 187132f48ddf0f604882ba8213fe386f) -declare namespace Cloudflare { - interface Env { - ASSETS: Fetcher; - } -} -interface Env extends Cloudflare.Env {} diff --git a/packages/create-cloudflare/templates/hello-world/ts/test/index.spec.ts b/packages/create-cloudflare/templates/hello-world/ts/test/index.spec.ts index fbee335d71cd..519729651a56 100644 --- a/packages/create-cloudflare/templates/hello-world/ts/test/index.spec.ts +++ b/packages/create-cloudflare/templates/hello-world/ts/test/index.spec.ts @@ -1,4 +1,3 @@ -// test/index.spec.ts import { env, createExecutionContext, waitOnExecutionContext, SELF } from 'cloudflare:test'; import { describe, it, expect } from 'vitest'; import worker from '../src/index'; diff --git a/packages/create-cloudflare/templates/hello-world/ts/test/tsconfig.json b/packages/create-cloudflare/templates/hello-world/ts/test/tsconfig.json index 7fc4362899ec..978ecd87b7ce 100644 --- a/packages/create-cloudflare/templates/hello-world/ts/test/tsconfig.json +++ b/packages/create-cloudflare/templates/hello-world/ts/test/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "types": ["@cloudflare/workers-types/experimental", "@cloudflare/vitest-pool-workers"] + "types": ["@cloudflare/vitest-pool-workers"] }, "include": ["./**/*.ts", "../worker-configuration.d.ts"], "exclude": [] diff --git a/packages/create-cloudflare/templates/hello-world/ts/tsconfig.json b/packages/create-cloudflare/templates/hello-world/ts/tsconfig.json index ce321858be20..877b0cf7eb98 100644 --- a/packages/create-cloudflare/templates/hello-world/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/hello-world/ts/tsconfig.json @@ -13,8 +13,6 @@ "module": "es2022", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "Bundler", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], /* Enable importing .json files */ "resolveJsonModule": true, diff --git a/packages/create-cloudflare/templates/hello-world/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/hello-world/ts/worker-configuration.d.ts deleted file mode 100644 index 07966391f81b..000000000000 --- a/packages/create-cloudflare/templates/hello-world/ts/worker-configuration.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated by Wrangler by running `wrangler types --include-runtime=false` (hash: 2905fd8e181cd2f4083a615fa51f1913) -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -declare namespace Cloudflare { - // eslint-disable-next-line @typescript-eslint/no-empty-interface,@typescript-eslint/no-empty-object-type - interface Env { - } -} -interface Env extends Cloudflare.Env {} diff --git a/packages/create-cloudflare/templates/hono/pages/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/hono/pages/templates/worker-configuration.d.ts deleted file mode 100644 index c943da4ceacb..000000000000 --- a/packages/create-cloudflare/templates/hono/pages/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface CloudflareBindings { -} diff --git a/packages/create-cloudflare/templates/hono/workers/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/hono/workers/templates/worker-configuration.d.ts deleted file mode 100644 index c943da4ceacb..000000000000 --- a/packages/create-cloudflare/templates/hono/workers/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface CloudflareBindings { -} diff --git a/packages/create-cloudflare/templates/next/pages/c3.ts b/packages/create-cloudflare/templates/next/pages/c3.ts index ea3f5a381e13..237450061c3d 100644 --- a/packages/create-cloudflare/templates/next/pages/c3.ts +++ b/packages/create-cloudflare/templates/next/pages/c3.ts @@ -145,7 +145,6 @@ export const writeEslintrc = async (ctx: C3Context): Promise => { const addDevDependencies = async (installEslintPlugin: boolean) => { const packages = [ "@cloudflare/next-on-pages@1", - "@cloudflare/workers-types", "vercel", ...(installEslintPlugin ? ["eslint-plugin-next-on-pages"] : []), ]; @@ -222,4 +221,5 @@ export default { previewScript: "preview", deployScript: "deploy", compatibilityFlags: ["nodejs_compat"], + typesPath: "env.d.ts", } as TemplateConfig; diff --git a/packages/create-cloudflare/templates/next/workers/c3.ts b/packages/create-cloudflare/templates/next/workers/c3.ts index f334db22823d..78f1db22c2be 100644 --- a/packages/create-cloudflare/templates/next/workers/c3.ts +++ b/packages/create-cloudflare/templates/next/workers/c3.ts @@ -48,7 +48,7 @@ export default { frameworkCli: "create-next-app", frameworkCliPinnedVersion: "~15.3.0", platform: "workers", - displayName: "Next.js (using Node.js compat + Workers Assets)", + displayName: "Next.js", path: "templates/next/workers", copyFiles: { path: "./templates", @@ -65,5 +65,7 @@ export default { devScript: "dev", previewScript: "preview", deployScript: "deploy", + + typesPath: "cloudflare-env.d.ts", compatibilityFlags: ["nodejs_compat"], } as TemplateConfig; diff --git a/packages/create-cloudflare/templates/next/workers/templates/cloudflare-env.d.ts b/packages/create-cloudflare/templates/next/workers/templates/cloudflare-env.d.ts deleted file mode 100644 index cdfc25f8e42c..000000000000 --- a/packages/create-cloudflare/templates/next/workers/templates/cloudflare-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Generated by Wrangler -// by running `wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts` - -interface CloudflareEnv { -} diff --git a/packages/create-cloudflare/templates/nuxt/pages/c3.ts b/packages/create-cloudflare/templates/nuxt/pages/c3.ts index ea9945d95916..2221dcb09058 100644 --- a/packages/create-cloudflare/templates/nuxt/pages/c3.ts +++ b/packages/create-cloudflare/templates/nuxt/pages/c3.ts @@ -3,8 +3,7 @@ import { brandColor, dim } from "@cloudflare/cli/colors"; import { spinner } from "@cloudflare/cli/interactive"; import { runFrameworkGenerator } from "frameworks/index"; import { mergeObjectProperties, transformFile } from "helpers/codemod"; -import { getLatestTypesEntrypoint } from "helpers/compatDate"; -import { readFile, writeFile } from "helpers/files"; +import { writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; import * as recast from "recast"; @@ -30,7 +29,7 @@ const generate = async (ctx: C3Context) => { logRaw(""); // newline }; -const configure = async (ctx: C3Context) => { +const configure = async () => { const packages = ["nitro-cloudflare-dev"]; // When using pnpm, explicitly add h3 package so the H3Event type declaration can be updated. @@ -45,29 +44,6 @@ const configure = async (ctx: C3Context) => { doneText: `${brandColor("installed")} ${dim(`via \`${npm} install\``)}`, }); updateNuxtConfig(); - - updateEnvTypes(ctx); -}; - -const updateEnvTypes = (ctx: C3Context) => { - const filepath = "env.d.ts"; - - const s = spinner(); - s.start(`Updating ${filepath}`); - - let file = readFile(filepath); - - let typesEntrypoint = `@cloudflare/workers-types`; - const latestEntrypoint = getLatestTypesEntrypoint(ctx); - if (latestEntrypoint) { - typesEntrypoint += `/${latestEntrypoint}`; - } - - // Replace placeholder with actual types entrypoint - file = file.replace("WORKERS_TYPES_ENTRYPOINT", typesEntrypoint); - writeFile("env.d.ts", file); - - s.stop(`${brandColor(`updated`)} ${dim(`\`${filepath}\``)}`); }; const updateNuxtConfig = () => { diff --git a/packages/create-cloudflare/templates/nuxt/pages/templates/env.d.ts b/packages/create-cloudflare/templates/nuxt/pages/templates/env.d.ts index dda21a4ab105..43e222ef2138 100644 --- a/packages/create-cloudflare/templates/nuxt/pages/templates/env.d.ts +++ b/packages/create-cloudflare/templates/nuxt/pages/templates/env.d.ts @@ -1,4 +1,4 @@ -/// +/// declare module "h3" { interface H3EventContext { diff --git a/packages/create-cloudflare/templates/nuxt/pages/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/nuxt/pages/templates/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/nuxt/pages/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/nuxt/workers/c3.ts b/packages/create-cloudflare/templates/nuxt/workers/c3.ts index 022c4920da7c..a89af1fe71a8 100644 --- a/packages/create-cloudflare/templates/nuxt/workers/c3.ts +++ b/packages/create-cloudflare/templates/nuxt/workers/c3.ts @@ -3,8 +3,7 @@ import { brandColor, dim } from "@cloudflare/cli/colors"; import { spinner } from "@cloudflare/cli/interactive"; import { runFrameworkGenerator } from "frameworks/index"; import { mergeObjectProperties, transformFile } from "helpers/codemod"; -import { getLatestTypesEntrypoint } from "helpers/compatDate"; -import { readFile, writeFile } from "helpers/files"; +import { writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; import * as recast from "recast"; @@ -30,7 +29,7 @@ const generate = async (ctx: C3Context) => { logRaw(""); // newline }; -const configure = async (ctx: C3Context) => { +const configure = async () => { const packages = ["nitro-cloudflare-dev", "nitropack"]; // When using pnpm, explicitly add h3 package so the H3Event type declaration can be updated. @@ -45,29 +44,6 @@ const configure = async (ctx: C3Context) => { doneText: `${brandColor("installed")} ${dim(`via \`${npm} install\``)}`, }); updateNuxtConfig(); - - updateEnvTypes(ctx); -}; - -const updateEnvTypes = (ctx: C3Context) => { - const filepath = "env.d.ts"; - - const s = spinner(); - s.start(`Updating ${filepath}`); - - let file = readFile(filepath); - - let typesEntrypoint = `@cloudflare/workers-types`; - const latestEntrypoint = getLatestTypesEntrypoint(ctx); - if (latestEntrypoint) { - typesEntrypoint += `/${latestEntrypoint}`; - } - - // Replace placeholder with actual types entrypoint - file = file.replace("WORKERS_TYPES_ENTRYPOINT", typesEntrypoint); - writeFile("env.d.ts", file); - - s.stop(`${brandColor(`updated`)} ${dim(`\`${filepath}\``)}`); }; const updateNuxtConfig = () => { diff --git a/packages/create-cloudflare/templates/nuxt/workers/templates/env.d.ts b/packages/create-cloudflare/templates/nuxt/workers/templates/env.d.ts index dda21a4ab105..43e222ef2138 100644 --- a/packages/create-cloudflare/templates/nuxt/workers/templates/env.d.ts +++ b/packages/create-cloudflare/templates/nuxt/workers/templates/env.d.ts @@ -1,4 +1,4 @@ -/// +/// declare module "h3" { interface H3EventContext { diff --git a/packages/create-cloudflare/templates/nuxt/workers/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/nuxt/workers/templates/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/nuxt/workers/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/openapi/ts/tsconfig.json b/packages/create-cloudflare/templates/openapi/ts/tsconfig.json index 4784966fb66c..2995bd1b4296 100644 --- a/packages/create-cloudflare/templates/openapi/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/openapi/ts/tsconfig.json @@ -22,7 +22,6 @@ "types": [ "@types/node", "@types/service-worker-mock", - "@cloudflare/workers-types" ] }, "exclude": ["node_modules", "dist", "tests"], diff --git a/packages/create-cloudflare/templates/openapi/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/openapi/ts/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/openapi/ts/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/queues/ts/tsconfig.json b/packages/create-cloudflare/templates/queues/ts/tsconfig.json index 26376384f509..2e3a41447194 100644 --- a/packages/create-cloudflare/templates/queues/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/queues/ts/tsconfig.json @@ -13,8 +13,6 @@ "module": "es2022", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "node", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], /* Enable importing .json files */ "resolveJsonModule": true, diff --git a/packages/create-cloudflare/templates/queues/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/queues/ts/worker-configuration.d.ts deleted file mode 100644 index 83fed320a334..000000000000 --- a/packages/create-cloudflare/templates/queues/ts/worker-configuration.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { - MY_QUEUE: Queue; -} diff --git a/packages/create-cloudflare/templates/qwik/pages/c3.ts b/packages/create-cloudflare/templates/qwik/pages/c3.ts index a0f8c2720c93..6a1747cb47ea 100644 --- a/packages/create-cloudflare/templates/qwik/pages/c3.ts +++ b/packages/create-cloudflare/templates/qwik/pages/c3.ts @@ -146,5 +146,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/qwik/workers/c3.ts b/packages/create-cloudflare/templates/qwik/workers/c3.ts index c2be839c9dbd..da324850e6bc 100644 --- a/packages/create-cloudflare/templates/qwik/workers/c3.ts +++ b/packages/create-cloudflare/templates/qwik/workers/c3.ts @@ -148,5 +148,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/react-router/c3.ts b/packages/create-cloudflare/templates/react-router/c3.ts index 7d506fd247b8..def8b91062e7 100644 --- a/packages/create-cloudflare/templates/react-router/c3.ts +++ b/packages/create-cloudflare/templates/react-router/c3.ts @@ -19,24 +19,12 @@ const generate = async (ctx: C3Context) => { logRaw(""); // newline }; -// TODO: Uncomment this once @react-router/dev updates its peer dependency to Wrangler v4 -// const configure = async () => { -// await installPackages(["wrangler@latest"], { -// dev: true, -// startText: "Updating the Wrangler version", -// doneText: `${brandColor(`updated`)} ${dim("wrangler@latest")}`, -// }); -// }; - const config: TemplateConfig = { configVersion: 1, id: "react-router", platform: "workers", frameworkCli: "create-react-router", displayName: "React Router (formerly Remix)", - copyFiles: { - path: "./templates", - }, generate, // configure, transformPackageJson: async () => ({ diff --git a/packages/create-cloudflare/templates/react-router/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/react-router/templates/worker-configuration.d.ts deleted file mode 100644 index 3400629ce87e..000000000000 --- a/packages/create-cloudflare/templates/react-router/templates/worker-configuration.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -declare namespace Cloudflare { - interface Env { - VALUE_FROM_CLOUDFLARE: "Hello from Cloudflare"; - } -} -interface Env extends Cloudflare.Env {} \ No newline at end of file diff --git a/packages/create-cloudflare/templates/react/pages/c3.ts b/packages/create-cloudflare/templates/react/pages/c3.ts index 181b95fac6c4..e2b2a9ead021 100644 --- a/packages/create-cloudflare/templates/react/pages/c3.ts +++ b/packages/create-cloudflare/templates/react/pages/c3.ts @@ -49,11 +49,13 @@ const config: TemplateConfig = { platform: "pages", hidden: true, path: "templates/react/pages", + copyFiles: { path: "./templates" }, generate, transformPackageJson: async () => ({ scripts: { - deploy: `${npm} run build && wrangler pages deploy ./dist`, - preview: `${npm} run build && wrangler pages dev ./dist`, + deploy: `${npm} run build && wrangler pages deploy`, + preview: `${npm} run build && wrangler pages dev`, + "cf-typegen": `wrangler types`, }, }), devScript: "dev", diff --git a/packages/create-cloudflare/templates/react/pages/templates/wrangler.jsonc b/packages/create-cloudflare/templates/react/pages/templates/wrangler.jsonc new file mode 100644 index 000000000000..9fb9c7262e8b --- /dev/null +++ b/packages/create-cloudflare/templates/react/pages/templates/wrangler.jsonc @@ -0,0 +1,5 @@ +{ + "name": "", + "compatibility_date": "", + "pages_build_output_dir": "./dist" + } diff --git a/packages/create-cloudflare/templates/react/workers/ts/tsconfig.worker.json b/packages/create-cloudflare/templates/react/workers/ts/tsconfig.worker.json index 5a170fd149f1..2acc852185d1 100644 --- a/packages/create-cloudflare/templates/react/workers/ts/tsconfig.worker.json +++ b/packages/create-cloudflare/templates/react/workers/ts/tsconfig.worker.json @@ -2,7 +2,7 @@ "extends": "./tsconfig.node.json", "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo", - "types": ["@cloudflare/workers-types/2023-07-01", "vite/client"] + "types": ["./worker-configuration.d.ts", "vite/client"], }, "include": ["./worker-configuration.d.ts", "./worker"] } diff --git a/packages/create-cloudflare/templates/react/workers/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/react/workers/ts/worker-configuration.d.ts deleted file mode 100644 index 1f0a97cb3ae0..000000000000 --- a/packages/create-cloudflare/templates/react/workers/ts/worker-configuration.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { - ASSETS: Fetcher; -} diff --git a/packages/create-cloudflare/templates/remix/pages/c3.ts b/packages/create-cloudflare/templates/remix/pages/c3.ts index e803a54cafcf..ae8596597db3 100644 --- a/packages/create-cloudflare/templates/remix/pages/c3.ts +++ b/packages/create-cloudflare/templates/remix/pages/c3.ts @@ -65,5 +65,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/remix/workers/c3.ts b/packages/create-cloudflare/templates/remix/workers/c3.ts index e92dd2357228..af587725d709 100644 --- a/packages/create-cloudflare/templates/remix/workers/c3.ts +++ b/packages/create-cloudflare/templates/remix/workers/c3.ts @@ -48,5 +48,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", + installWorkersTypes: true, }; export default config; diff --git a/packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts deleted file mode 100644 index 5b2319b3f29f..000000000000 --- a/packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/scheduled/ts/tsconfig.json b/packages/create-cloudflare/templates/scheduled/ts/tsconfig.json index 26376384f509..2e3a41447194 100644 --- a/packages/create-cloudflare/templates/scheduled/ts/tsconfig.json +++ b/packages/create-cloudflare/templates/scheduled/ts/tsconfig.json @@ -13,8 +13,6 @@ "module": "es2022", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "node", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["@cloudflare/workers-types"], /* Enable importing .json files */ "resolveJsonModule": true, diff --git a/packages/create-cloudflare/templates/scheduled/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/scheduled/ts/worker-configuration.d.ts deleted file mode 100644 index a0b76efdd358..000000000000 --- a/packages/create-cloudflare/templates/scheduled/ts/worker-configuration.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Generated by Wrangler -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` -interface Env { -} diff --git a/packages/create-cloudflare/templates/solid/c3.ts b/packages/create-cloudflare/templates/solid/c3.ts index e406ad86e30d..8ee4fc2239b8 100644 --- a/packages/create-cloudflare/templates/solid/c3.ts +++ b/packages/create-cloudflare/templates/solid/c3.ts @@ -77,6 +77,7 @@ const config: TemplateConfig = { scripts: { preview: `${npm} run build && npx wrangler pages dev`, deploy: `${npm} run build && wrangler pages deploy`, + "cf-typegen": `wrangler types`, }, }), compatibilityFlags: ["nodejs_compat"], diff --git a/packages/create-cloudflare/templates/svelte/pages/c3.ts b/packages/create-cloudflare/templates/svelte/pages/c3.ts index 9aa0858f2d4d..d87f48e128ea 100644 --- a/packages/create-cloudflare/templates/svelte/pages/c3.ts +++ b/packages/create-cloudflare/templates/svelte/pages/c3.ts @@ -1,5 +1,4 @@ import { existsSync } from "node:fs"; -import { platform } from "node:os"; import { logRaw, updateStatus } from "@cloudflare/cli"; import { blue, brandColor, dim } from "@cloudflare/cli/colors"; import { runFrameworkGenerator } from "frameworks/index"; @@ -144,10 +143,9 @@ const config: TemplateConfig = { }; if (usesTypescript(ctx)) { - const mv = platform() === "win32" ? "move" : "mv"; scripts = { ...scripts, - "cf-typegen": `wrangler types && ${mv} worker-configuration.d.ts src/`, + "cf-typegen": `wrangler types ./src/worker-configuration.d.ts`, }; } @@ -156,5 +154,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", + typesPath: "./src/worker-configuration.d.ts", }; export default config; diff --git a/packages/create-cloudflare/templates/svelte/workers/c3.ts b/packages/create-cloudflare/templates/svelte/workers/c3.ts index a251fccbb856..47d43649c1c4 100644 --- a/packages/create-cloudflare/templates/svelte/workers/c3.ts +++ b/packages/create-cloudflare/templates/svelte/workers/c3.ts @@ -1,4 +1,3 @@ -import { platform } from "node:os"; import { logRaw, updateStatus } from "@cloudflare/cli"; import { blue, brandColor, dim } from "@cloudflare/cli/colors"; import { runFrameworkGenerator } from "frameworks/index"; @@ -113,10 +112,9 @@ const config: TemplateConfig = { }; if (usesTypescript(ctx)) { - const mv = platform() === "win32" ? "move" : "mv"; scripts = { ...scripts, - "cf-typegen": `wrangler types && ${mv} worker-configuration.d.ts src/`, + "cf-typegen": `wrangler types ./src/worker-configuration.d.ts`, }; } @@ -125,5 +123,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", + typesPath: "./src/worker-configuration.d.ts", }; export default config; diff --git a/packages/create-cloudflare/templates/vue/pages/c3.ts b/packages/create-cloudflare/templates/vue/pages/c3.ts index 24d1931567a1..60dad473557c 100644 --- a/packages/create-cloudflare/templates/vue/pages/c3.ts +++ b/packages/create-cloudflare/templates/vue/pages/c3.ts @@ -16,12 +16,14 @@ const config: TemplateConfig = { displayName: "Vue", platform: "pages", hidden: true, - path: "templates/pages/vue", + path: "templates/vue/pages", + copyFiles: { path: "./templates" }, generate, transformPackageJson: async () => ({ scripts: { - deploy: `${npm} run build && wrangler pages deploy ./dist`, - preview: `${npm} run build && wrangler pages dev ./dist`, + deploy: `${npm} run build && wrangler pages deploy`, + preview: `${npm} run build && wrangler pages dev`, + "cf-typegen": `wrangler types`, }, }), devScript: "dev", diff --git a/packages/create-cloudflare/templates/vue/pages/templates/wrangler.jsonc b/packages/create-cloudflare/templates/vue/pages/templates/wrangler.jsonc new file mode 100644 index 000000000000..9fb9c7262e8b --- /dev/null +++ b/packages/create-cloudflare/templates/vue/pages/templates/wrangler.jsonc @@ -0,0 +1,5 @@ +{ + "name": "", + "compatibility_date": "", + "pages_build_output_dir": "./dist" + } diff --git a/packages/create-cloudflare/templates/vue/workers/ts/tsconfig.worker.json b/packages/create-cloudflare/templates/vue/workers/ts/tsconfig.worker.json index 533fb11bead3..b48c4245e9f7 100644 --- a/packages/create-cloudflare/templates/vue/workers/ts/tsconfig.worker.json +++ b/packages/create-cloudflare/templates/vue/workers/ts/tsconfig.worker.json @@ -2,7 +2,7 @@ "extends": "./tsconfig.node.json", "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo", - "types": ["@cloudflare/workers-types/2023-07-01", "./worker-configuration.d.ts","vite/client"], + "types": [ "./worker-configuration.d.ts","vite/client"], }, "include": ["server"], } diff --git a/packages/create-cloudflare/templates/vue/workers/ts/worker-configuration.d.ts b/packages/create-cloudflare/templates/vue/workers/ts/worker-configuration.d.ts deleted file mode 100644 index c34b3b6621d0..000000000000 --- a/packages/create-cloudflare/templates/vue/workers/ts/worker-configuration.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Generated by Wrangler by running `wrangler types` -// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` - -interface Env { - ASSETS: Fetcher; -} From 6b1f7ea9e67822a6de8e3be734934d24a312216e Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:47:49 +0100 Subject: [PATCH 03/17] update tests --- .../e2e-tests/frameworks.test.ts | 36 +++-------- .../frameworks/framework-test-config.ts | 64 ++++++++++++++----- .../src/__tests__/workers.test.ts | 36 +++++++++-- 3 files changed, 87 insertions(+), 49 deletions(-) diff --git a/packages/create-cloudflare/e2e-tests/frameworks.test.ts b/packages/create-cloudflare/e2e-tests/frameworks.test.ts index 00f5aadaa7e6..9ec617326f4d 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks.test.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks.test.ts @@ -361,48 +361,32 @@ const verifyBuildCfTypesScript = async ( return; } - const { outputFile, envInterfaceName } = verifyBuildCfTypes; - - const outputFileContentPre = readFile(join(projectPath, outputFile)); - const outputFileContentPreLines = outputFileContentPre.split("\n"); - - // the file contains the "Generated by Wrangler" comment without a timestamp - expect(outputFileContentPreLines).toContain("// Generated by Wrangler"); - - // the file contains the env interface - // the file still contains the env interface - const hasEnvInterfacePre = outputFileContentPreLines.some( - (line) => - // old type gen - some framework templates pin older versions of wrangler - line === `interface ${envInterfaceName} {` || - // new after importable env change - line === `interface ${envInterfaceName} extends Cloudflare.Env {}`, - ); - expect(hasEnvInterfacePre).toBe(true); - // Run the `cf-typegen` script to generate types for bindings in fixture const buildTypesProc = spawnWithLogging( [pm, "run", "cf-typegen"], { cwd: projectPath }, logStream, ); + await waitForExit(buildTypesProc); - const outputFileContentPost = readFile(join(projectPath, outputFile)); - const outputFileContentPostLines = outputFileContentPost.split("\n"); + const { outputFile, envInterfaceName } = verifyBuildCfTypes; - // the file doesn't contain the "Generated by Wrangler" comment anymore - expect(outputFileContentPostLines).not.toContain("// Generated by Wrangler"); + const outputFileContent = readFile(join(projectPath, outputFile)).split("\n"); - // the file still contains the env interface - const hasEnvInterfacePost = outputFileContentPostLines.some( + // the file contains the env interface + const hasEnvInterfacePre = outputFileContent.some( (line) => // old type gen - some framework templates pin older versions of wrangler line === `interface ${envInterfaceName} {` || // new after importable env change line === `interface ${envInterfaceName} extends Cloudflare.Env {}`, ); - expect(hasEnvInterfacePost).toBe(true); + expect(hasEnvInterfacePre).toBe(true); + + expect(outputFileContent[1]).match( + /\/\/ Runtime types generated with workerd@1\.\d{8}\.\d \d{4}-\d{2}-\d{2} ([a-z_]+,?)*/, + ); }; const verifyBuildScript = async ( diff --git a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts index 505cfa343f71..dea941585179 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts @@ -40,6 +40,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, flags: [ "--skip-houston", "--no-install", @@ -68,6 +72,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, flags: [ "--skip-houston", "--no-install", @@ -184,6 +192,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Congratulations! Your app is running.", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, flags: ["--style", "sass"], }, "gatsby:pages": { @@ -238,6 +250,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Hello!", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "CloudflareBindings", + }, promptHandlers: [ { matcher: /Do you want to install project dependencies\?/, @@ -257,6 +273,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/message", expectedText: "Hello Hono!", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "CloudflareBindings", + }, promptHandlers: [ { matcher: /Do you want to install project dependencies\?/, @@ -283,10 +303,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Welcome to Qwik", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "qwik:workers": { argv: ["--platform", "workers"], @@ -308,10 +324,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Welcome to Qwik", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "remix:pages": { argv: ["--platform", "pages"], @@ -327,10 +339,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, verifyBuild: { outputDir: "./build/client", script: "build", @@ -353,10 +361,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, flags: ["--typescript", "--no-install", "--no-git-init"], }, "next:pages": { @@ -506,6 +510,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite + React", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, }, "react:workers": { argv: ["--platform", "workers"], @@ -534,6 +542,10 @@ export default function getFrameworkTestConfig(pm: string) { // not actually running the client side JS. expectedText: "Vite + React + TS", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, }, solid: { promptHandlers: [ @@ -558,6 +570,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Hello world", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, }, "svelte:pages": { argv: ["--platform", "pages"], @@ -586,6 +602,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + verifyBuildCfTypes: { + outputFile: "./src/worker-configuration.d.ts", + envInterfaceName: "Env", + }, }, "svelte:workers": { argv: ["--platform", "workers"], @@ -608,6 +628,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + verifyBuildCfTypes: { + outputFile: "./src/worker-configuration.d.ts", + envInterfaceName: "Env", + }, }, "vue:pages": { argv: ["--platform", "pages"], @@ -621,6 +645,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite App", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, flags: ["--ts"], }, "vue:workers": { @@ -636,6 +664,10 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite App", }, + verifyBuildCfTypes: { + outputFile: "worker-configuration.d.ts", + envInterfaceName: "Env", + }, }, }; } diff --git a/packages/create-cloudflare/src/__tests__/workers.test.ts b/packages/create-cloudflare/src/__tests__/workers.test.ts index b0b67a72f72f..1a18eb90bdb2 100644 --- a/packages/create-cloudflare/src/__tests__/workers.test.ts +++ b/packages/create-cloudflare/src/__tests__/workers.test.ts @@ -3,7 +3,7 @@ import { mockSpinner } from "helpers/__tests__/mocks"; import { getLatestTypesEntrypoint } from "helpers/compatDate"; import { readFile, writeFile } from "helpers/files"; import { beforeEach, describe, expect, test, vi } from "vitest"; -import { addWorkersTypesToTsConfig } from "../workers"; +import { updateTsConfig } from "../workers"; import { createTestContext } from "./helpers"; import type { C3Context } from "types"; @@ -18,12 +18,13 @@ beforeEach(() => { const mockCompatDate = "2024-01-17"; -describe("addWorkersTypesToTsConfig", () => { +describe("updateTsConfig", () => { let ctx: C3Context; beforeEach(() => { ctx = createTestContext(); ctx.args.ts = true; + ctx.template.installWorkersTypes = false; vi.mocked(existsSync).mockImplementation(() => true); vi.mocked(getLatestTypesEntrypoint).mockReturnValue(mockCompatDate); @@ -34,8 +35,9 @@ describe("addWorkersTypesToTsConfig", () => { ); }); - test("happy path", async () => { - await addWorkersTypesToTsConfig(ctx); + test("installing workers types", async () => { + ctx.template.installWorkersTypes = true; + await updateTsConfig(ctx); expect(writeFile).toHaveBeenCalled(); @@ -46,26 +48,46 @@ describe("addWorkersTypesToTsConfig", () => { test("tsconfig.json not found", async () => { vi.mocked(existsSync).mockImplementation(() => false); - await addWorkersTypesToTsConfig(ctx); + await updateTsConfig(ctx); expect(writeFile).not.toHaveBeenCalled(); }); test("latest entrypoint not found", async () => { + ctx.template.installWorkersTypes = true; vi.mocked(getLatestTypesEntrypoint).mockReturnValue(null); - await addWorkersTypesToTsConfig(ctx); + await updateTsConfig(ctx); expect(writeFile).not.toHaveBeenCalled(); }); test("don't clobber existing entrypoints", async () => { + ctx.template.installWorkersTypes = true; vi.mocked(readFile).mockImplementation( () => `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, ); - await addWorkersTypesToTsConfig(ctx); + await updateTsConfig(ctx); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `"@cloudflare/workers-types/2021-03-20"`, ); }); + + test("will remove workers-types when generating types", async () => { + vi.mocked(readFile).mockImplementation( + () => + `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, + ); + await updateTsConfig(ctx); + expect(vi.mocked(writeFile).mock.calls[0][1]).not.toContain( + `"@cloudflare/workers-types/2021-03-20"`, + ); + }); + + test("will add generated types file", async () => { + await updateTsConfig(ctx); + expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( + `./worker-configuration.d.ts`, + ); + }); }); From 129701d4abe86d6cf8b72ccec042ce3ecd642639 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:47:55 +0100 Subject: [PATCH 04/17] changeset --- .changeset/slimy-eels-wink.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slimy-eels-wink.md diff --git a/.changeset/slimy-eels-wink.md b/.changeset/slimy-eels-wink.md new file mode 100644 index 000000000000..b773093ce934 --- /dev/null +++ b/.changeset/slimy-eels-wink.md @@ -0,0 +1,5 @@ +--- +"create-cloudflare": minor +--- + +use `wrangler types` to generate types instead of using the `@cloudflare/workers-types` package From 884a598f87b8dafe1b9360c36bf3f11792cc3765 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Fri, 11 Apr 2025 15:09:14 +0100 Subject: [PATCH 05/17] fix next test --- packages/create-cloudflare/templates/next/workers/c3.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-cloudflare/templates/next/workers/c3.ts b/packages/create-cloudflare/templates/next/workers/c3.ts index 78f1db22c2be..5a8834950f86 100644 --- a/packages/create-cloudflare/templates/next/workers/c3.ts +++ b/packages/create-cloudflare/templates/next/workers/c3.ts @@ -59,13 +59,13 @@ export default { scripts: { deploy: `opennextjs-cloudflare build && opennextjs-cloudflare deploy`, preview: `opennextjs-cloudflare build && opennextjs-cloudflare preview`, - "cf-typegen": `wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts`, + "cf-typegen": `wrangler types --env-interface CloudflareEnv ./cloudflare-env.d.ts`, }, }), devScript: "dev", previewScript: "preview", deployScript: "deploy", - typesPath: "cloudflare-env.d.ts", + typesPath: "./cloudflare-env.d.ts", compatibilityFlags: ["nodejs_compat"], } as TemplateConfig; From 9970bb4fde50474e092bf3099c72a6a4d98fc4a4 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Mon, 14 Apr 2025 06:54:24 +0100 Subject: [PATCH 06/17] don't conflate installing workers-types and generating types --- packages/create-cloudflare/src/__tests__/workers.test.ts | 1 + packages/create-cloudflare/src/cli.ts | 4 +++- packages/create-cloudflare/src/templates.ts | 5 ++++- packages/create-cloudflare/src/workers.ts | 1 + packages/create-cloudflare/templates/docusaurus/pages/c3.ts | 2 +- .../create-cloudflare/templates/docusaurus/workers/c3.ts | 2 +- packages/create-cloudflare/templates/gatsby/pages/c3.ts | 2 +- packages/create-cloudflare/templates/gatsby/workers/c3.ts | 2 +- 8 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/create-cloudflare/src/__tests__/workers.test.ts b/packages/create-cloudflare/src/__tests__/workers.test.ts index 1a18eb90bdb2..716cb18287aa 100644 --- a/packages/create-cloudflare/src/__tests__/workers.test.ts +++ b/packages/create-cloudflare/src/__tests__/workers.test.ts @@ -25,6 +25,7 @@ describe("updateTsConfig", () => { ctx = createTestContext(); ctx.args.ts = true; ctx.template.installWorkersTypes = false; + ctx.template.skipWranglerTypegen = false; vi.mocked(existsSync).mockImplementation(() => true); vi.mocked(getLatestTypesEntrypoint).mockReturnValue(mockCompatDate); diff --git a/packages/create-cloudflare/src/cli.ts b/packages/create-cloudflare/src/cli.ts index 50ad53bde3c3..9c9bd7965fdb 100644 --- a/packages/create-cloudflare/src/cli.ts +++ b/packages/create-cloudflare/src/cli.ts @@ -170,7 +170,9 @@ const configure = async (ctx: C3Context) => { if (ctx.template.installWorkersTypes) { await installWorkersTypes(ctx); } - await generateWorkersTypes(ctx); + if (ctx.template.skipWranglerTypegen) { + await generateWorkersTypes(ctx); + } await offerGit(ctx); await gitCommit(ctx); diff --git a/packages/create-cloudflare/src/templates.ts b/packages/create-cloudflare/src/templates.ts index 8606c80f5b6c..d5bb2b481697 100644 --- a/packages/create-cloudflare/src/templates.ts +++ b/packages/create-cloudflare/src/templates.ts @@ -150,8 +150,11 @@ export type TemplateConfig = { bindings?: Record; - /** Don't generate types, use @cloudflare/workers-types instead. Usually because the framework is pinned to Wrangler 3. Default false. */ + /** Default false. For frameworks that are pinned to Wrangler 3. */ installWorkersTypes?: boolean; + + /** Default false. To accomodate SSG frameworks etc. */ + skipWranglerTypegen?: boolean; }; type CopyFiles = (StaticFileMap | VariantInfo) & { diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index ebc485f520d6..f6a1399a0d99 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -120,6 +120,7 @@ export async function updateTsConfig(ctx: C3Context) { } /** + * TODO: delete if/when qwik and remix move to wrangler v4 * Installs the latest version of the `@cloudflare/workers-types` package * and updates the .tsconfig file to use the latest entrypoint version. */ diff --git a/packages/create-cloudflare/templates/docusaurus/pages/c3.ts b/packages/create-cloudflare/templates/docusaurus/pages/c3.ts index 5661d3b53142..aced59dc2f7a 100644 --- a/packages/create-cloudflare/templates/docusaurus/pages/c3.ts +++ b/packages/create-cloudflare/templates/docusaurus/pages/c3.ts @@ -27,6 +27,6 @@ const config: TemplateConfig = { devScript: "preview", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + skipWranglerTypegen: false, }; export default config; diff --git a/packages/create-cloudflare/templates/docusaurus/workers/c3.ts b/packages/create-cloudflare/templates/docusaurus/workers/c3.ts index 6a94696ad61f..806c456d01f5 100644 --- a/packages/create-cloudflare/templates/docusaurus/workers/c3.ts +++ b/packages/create-cloudflare/templates/docusaurus/workers/c3.ts @@ -29,6 +29,6 @@ const config: TemplateConfig = { devScript: "start", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + skipWranglerTypegen: true, }; export default config; diff --git a/packages/create-cloudflare/templates/gatsby/pages/c3.ts b/packages/create-cloudflare/templates/gatsby/pages/c3.ts index 28b10923ec62..bbe079a91d8d 100644 --- a/packages/create-cloudflare/templates/gatsby/pages/c3.ts +++ b/packages/create-cloudflare/templates/gatsby/pages/c3.ts @@ -47,6 +47,6 @@ const config: TemplateConfig = { devScript: "develop", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + skipWranglerTypegen: true, }; export default config; diff --git a/packages/create-cloudflare/templates/gatsby/workers/c3.ts b/packages/create-cloudflare/templates/gatsby/workers/c3.ts index ce40d51a42ac..e86db793f86c 100644 --- a/packages/create-cloudflare/templates/gatsby/workers/c3.ts +++ b/packages/create-cloudflare/templates/gatsby/workers/c3.ts @@ -49,6 +49,6 @@ const config: TemplateConfig = { devScript: "develop", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + skipWranglerTypegen: true, }; export default config; From 98a9a76194acc3e85e3bb86e59649e515e708b3f Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Mon, 14 Apr 2025 07:56:52 +0100 Subject: [PATCH 07/17] next on pages --- packages/create-cloudflare/templates/next/pages/c3.ts | 2 +- packages/create-cloudflare/templates/next/pages/env.d.ts | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 packages/create-cloudflare/templates/next/pages/env.d.ts diff --git a/packages/create-cloudflare/templates/next/pages/c3.ts b/packages/create-cloudflare/templates/next/pages/c3.ts index 237450061c3d..25b7ce0a7f41 100644 --- a/packages/create-cloudflare/templates/next/pages/c3.ts +++ b/packages/create-cloudflare/templates/next/pages/c3.ts @@ -221,5 +221,5 @@ export default { previewScript: "preview", deployScript: "deploy", compatibilityFlags: ["nodejs_compat"], - typesPath: "env.d.ts", + typesPath: "./env.d.ts", } as TemplateConfig; diff --git a/packages/create-cloudflare/templates/next/pages/env.d.ts b/packages/create-cloudflare/templates/next/pages/env.d.ts deleted file mode 100644 index 68a2a989df06..000000000000 --- a/packages/create-cloudflare/templates/next/pages/env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Generated by Wrangler -// by running `wrangler types --env-interface CloudflareEnv env.d.ts` - -interface CloudflareEnv { -} From 1dafb47d7ae6e49e15e6cd9552eae6e9a0598711 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Tue, 15 Apr 2025 02:19:58 +0100 Subject: [PATCH 08/17] pr feedback --- packages/create-cloudflare/src/workers.ts | 57 +++++++++++++---------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index f6a1399a0d99..5c60b95f0f16 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -1,4 +1,4 @@ -import { existsSync } from "fs"; +import { existsSync, read } from "fs"; import { join, resolve } from "path"; import { warn } from "@cloudflare/cli"; import { brandColor, dim } from "@cloudflare/cli/colors"; @@ -11,7 +11,7 @@ import * as jsonc from "jsonc-parser"; import type { C3Context, PackageJson } from "types"; /** - * Generate types using `wrangler types` and update tsconfig + * Generate types using the `cf-typegen` script and update tsconfig */ export async function generateWorkersTypes(ctx: C3Context) { @@ -31,10 +31,6 @@ export async function generateWorkersTypes(ctx: C3Context) { await runCommand(typesCmd, { cwd: ctx.project.path, silent: true, - env: { - CLOUDFLARE_ACCOUNT_ID: ctx.account?.id, - NODE_ENV: "production", - }, startText: "Generating types for your application", doneText: `${brandColor("generated")} ${dim(`to \`${ctx.template.typesPath ?? "worker-configuration.d.ts"}\` via \`${typesCmd.join(" ")}\``)}`, }); @@ -53,6 +49,13 @@ export async function generateWorkersTypes(ctx: C3Context) { await updateTsConfig(ctx); } +/** + * update `types` in tsconfig: + * - set workers-types to latest entrypoint if installed + * - remove workers-types if runtime types have been generated + * - add generated types file if types were generated + * - add node if node compat + */ export async function updateTsConfig(ctx: C3Context) { const tsconfigPath = join(ctx.project.path, "tsconfig.json"); if (!existsSync(tsconfigPath)) { @@ -64,7 +67,7 @@ export async function updateTsConfig(ctx: C3Context) { try { const config = jsonc.parse(tsconfig); const currentTypes = config.compilerOptions?.types ?? []; - let newTypes: string[]; + const newTypes: string[] = currentTypes; if (ctx.template.installWorkersTypes) { const entrypointVersion = getLatestTypesEntrypoint(ctx); if (entrypointVersion === null) { @@ -76,24 +79,30 @@ export async function updateTsConfig(ctx: C3Context) { ); // If a type declaration with an explicit entrypoint exists, leave the types as is // Otherwise, add the latest entrypoint - newTypes = explicitEntrypoint - ? [...currentTypes] - : [ - ...currentTypes.filter( - (t: string) => t !== "@cloudflare/workers-types", - ), - typesEntrypoint, - ]; - } else { - newTypes = [ - ...currentTypes.filter( - (t: string) => !t.startsWith("@cloudflare/workers-types"), - ), + if (!explicitEntrypoint) { + newTypes + .filter((t: string) => t !== "@cloudflare/workers-types") + .push(typesEntrypoint); + } + } + if (!ctx.template.skipWranglerTypegen) { + // if generated types include runtime types, remove workers-types + const typegen = readFile( ctx.template.typesPath ?? "./worker-configuration.d.ts", - ...(ctx.template.compatibilityFlags?.includes("nodejs_compat") - ? ["node"] - : []), - ]; + ).split("\n"); + if ( + typegen.some((line) => + line.includes("// Runtime types generated with workerd"), + ) + ) { + newTypes.filter( + (t: string) => !t.startsWith("@cloudflare/workers-types"), + ); + } + if (ctx.template.compatibilityFlags?.includes("nodejs_compat")) { + newTypes.push("node"); + } + newTypes.push(ctx.template.typesPath ?? "./worker-configuration.d.ts"); } if (newTypes.sort() === currentTypes.sort()) { return; From 673a36da633e25903c5d9e4bbe92c03f95d6a7c8 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Tue, 15 Apr 2025 08:37:53 +0100 Subject: [PATCH 09/17] fixups --- .../src/__tests__/workers.test.ts | 32 ++++++++++++++++--- packages/create-cloudflare/src/cli.ts | 2 +- packages/create-cloudflare/src/workers.ts | 22 ++++++------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/packages/create-cloudflare/src/__tests__/workers.test.ts b/packages/create-cloudflare/src/__tests__/workers.test.ts index 716cb18287aa..2d67edf76b93 100644 --- a/packages/create-cloudflare/src/__tests__/workers.test.ts +++ b/packages/create-cloudflare/src/__tests__/workers.test.ts @@ -38,6 +38,7 @@ describe("updateTsConfig", () => { test("installing workers types", async () => { ctx.template.installWorkersTypes = true; + ctx.template.skipWranglerTypegen = true; await updateTsConfig(ctx); expect(writeFile).toHaveBeenCalled(); @@ -55,6 +56,7 @@ describe("updateTsConfig", () => { test("latest entrypoint not found", async () => { ctx.template.installWorkersTypes = true; + ctx.template.skipWranglerTypegen = true; vi.mocked(getLatestTypesEntrypoint).mockReturnValue(null); await updateTsConfig(ctx); @@ -63,6 +65,7 @@ describe("updateTsConfig", () => { test("don't clobber existing entrypoints", async () => { ctx.template.installWorkersTypes = true; + ctx.template.skipWranglerTypegen = true; vi.mocked(readFile).mockImplementation( () => `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, @@ -74,17 +77,36 @@ describe("updateTsConfig", () => { ); }); - test("will remove workers-types when generating types", async () => { - vi.mocked(readFile).mockImplementation( - () => - `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, - ); + test("will remove workers-types when generating types, if generated types include runtime types", async () => { + vi.mocked(readFile).mockImplementation((path) => { + console.log("path", path); + if (path.includes("tsconfig.json")) { + return `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`; + } else { + return "// Runtime types generated with workerd"; + } + }); await updateTsConfig(ctx); expect(vi.mocked(writeFile).mock.calls[0][1]).not.toContain( `"@cloudflare/workers-types/2021-03-20"`, ); }); + test("will NOT remove workers-types when generating types, if generated types don't include runtime types", async () => { + vi.mocked(readFile).mockImplementation((path) => { + if (path.includes("tsconfig.json")) { + return `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`; + } else { + return "no runtime types here"; + } + }); + await updateTsConfig(ctx); + + expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( + `"@cloudflare/workers-types/2021-03-20"`, + ); + }); + test("will add generated types file", async () => { await updateTsConfig(ctx); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( diff --git a/packages/create-cloudflare/src/cli.ts b/packages/create-cloudflare/src/cli.ts index 9c9bd7965fdb..f1dfb47026ca 100644 --- a/packages/create-cloudflare/src/cli.ts +++ b/packages/create-cloudflare/src/cli.ts @@ -170,7 +170,7 @@ const configure = async (ctx: C3Context) => { if (ctx.template.installWorkersTypes) { await installWorkersTypes(ctx); } - if (ctx.template.skipWranglerTypegen) { + if (!ctx.template.skipWranglerTypegen) { await generateWorkersTypes(ctx); } diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 5c60b95f0f16..f544c9ea77f3 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -1,4 +1,4 @@ -import { existsSync, read } from "fs"; +import { existsSync } from "fs"; import { join, resolve } from "path"; import { warn } from "@cloudflare/cli"; import { brandColor, dim } from "@cloudflare/cli/colors"; @@ -61,13 +61,11 @@ export async function updateTsConfig(ctx: C3Context) { if (!existsSync(tsconfigPath)) { return; } - const tsconfig = readFile(tsconfigPath); - try { const config = jsonc.parse(tsconfig); const currentTypes = config.compilerOptions?.types ?? []; - const newTypes: string[] = currentTypes; + let newTypes: string[] = [...currentTypes]; if (ctx.template.installWorkersTypes) { const entrypointVersion = getLatestTypesEntrypoint(ctx); if (entrypointVersion === null) { @@ -77,16 +75,18 @@ export async function updateTsConfig(ctx: C3Context) { const explicitEntrypoint = (currentTypes as string[]).some((t) => t.match(/@cloudflare\/workers-types\/\d{4}-\d{2}-\d{2}/), ); - // If a type declaration with an explicit entrypoint exists, leave the types as is + // If a type declaration with an explicit entrypoint exists, leave the types as is. // Otherwise, add the latest entrypoint if (!explicitEntrypoint) { - newTypes - .filter((t: string) => t !== "@cloudflare/workers-types") - .push(typesEntrypoint); + newTypes = newTypes.filter( + (t: string) => t !== "@cloudflare/workers-types", + ); + newTypes.push(typesEntrypoint); } } if (!ctx.template.skipWranglerTypegen) { - // if generated types include runtime types, remove workers-types + newTypes.push(ctx.template.typesPath ?? "./worker-configuration.d.ts"); + // if generated types include runtime types, remove @cloudflare/workers-types const typegen = readFile( ctx.template.typesPath ?? "./worker-configuration.d.ts", ).split("\n"); @@ -95,14 +95,14 @@ export async function updateTsConfig(ctx: C3Context) { line.includes("// Runtime types generated with workerd"), ) ) { - newTypes.filter( + newTypes = newTypes.filter( (t: string) => !t.startsWith("@cloudflare/workers-types"), ); } + // add node types if nodejs_compat is enabled if (ctx.template.compatibilityFlags?.includes("nodejs_compat")) { newTypes.push("node"); } - newTypes.push(ctx.template.typesPath ?? "./worker-configuration.d.ts"); } if (newTypes.sort() === currentTypes.sort()) { return; From 70cf9aa3cacf668b55d7353451ec79da67493687 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Wed, 16 Apr 2025 00:28:59 +0100 Subject: [PATCH 10/17] f --- packages/create-cloudflare/e2e-tests/frameworks.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-cloudflare/e2e-tests/frameworks.test.ts b/packages/create-cloudflare/e2e-tests/frameworks.test.ts index 9ec617326f4d..0273948ae379 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks.test.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks.test.ts @@ -384,7 +384,7 @@ const verifyBuildCfTypesScript = async ( ); expect(hasEnvInterfacePre).toBe(true); - expect(outputFileContent[1]).match( + expect(outputFileContent[2]).match( /\/\/ Runtime types generated with workerd@1\.\d{8}\.\d \d{4}-\d{2}-\d{2} ([a-z_]+,?)*/, ); }; From 4ea8163a16f8b3f977b5421f2c492be3884addc8 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Tue, 6 May 2025 11:15:09 +0100 Subject: [PATCH 11/17] use workersTypes enum instead --- .../src/__tests__/workers.test.ts | 14 ++++++-------- packages/create-cloudflare/src/cli.ts | 5 ++--- packages/create-cloudflare/src/templates.ts | 8 ++++---- packages/create-cloudflare/src/workers.ts | 6 +++--- .../templates/docusaurus/pages/c3.ts | 2 +- .../templates/docusaurus/workers/c3.ts | 2 +- .../create-cloudflare/templates/gatsby/pages/c3.ts | 2 +- .../templates/gatsby/workers/c3.ts | 2 +- .../create-cloudflare/templates/qwik/pages/c3.ts | 2 +- .../qwik/pages/templates/worker-configuration.d.ts | 4 ++++ .../create-cloudflare/templates/qwik/workers/c3.ts | 2 +- .../workers/templates/worker-configuration.d.ts | 4 ++++ .../create-cloudflare/templates/remix/pages/c3.ts | 2 +- .../pages/templates/worker-configuration.d.ts | 4 ++++ .../templates/remix/workers/c3.ts | 2 +- .../workers/templates/worker-configuration.d.ts | 4 ++++ 16 files changed, 39 insertions(+), 26 deletions(-) create mode 100644 packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts create mode 100644 packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts create mode 100644 packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts create mode 100644 packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts diff --git a/packages/create-cloudflare/src/__tests__/workers.test.ts b/packages/create-cloudflare/src/__tests__/workers.test.ts index 2d67edf76b93..49513d315afa 100644 --- a/packages/create-cloudflare/src/__tests__/workers.test.ts +++ b/packages/create-cloudflare/src/__tests__/workers.test.ts @@ -24,8 +24,7 @@ describe("updateTsConfig", () => { beforeEach(() => { ctx = createTestContext(); ctx.args.ts = true; - ctx.template.installWorkersTypes = false; - ctx.template.skipWranglerTypegen = false; + ctx.template.workersTypes = "generated"; vi.mocked(existsSync).mockImplementation(() => true); vi.mocked(getLatestTypesEntrypoint).mockReturnValue(mockCompatDate); @@ -37,8 +36,8 @@ describe("updateTsConfig", () => { }); test("installing workers types", async () => { - ctx.template.installWorkersTypes = true; - ctx.template.skipWranglerTypegen = true; + ctx.template.workersTypes = "installed"; + await updateTsConfig(ctx); expect(writeFile).toHaveBeenCalled(); @@ -55,8 +54,8 @@ describe("updateTsConfig", () => { }); test("latest entrypoint not found", async () => { - ctx.template.installWorkersTypes = true; - ctx.template.skipWranglerTypegen = true; + ctx.template.workersTypes = "installed"; + vi.mocked(getLatestTypesEntrypoint).mockReturnValue(null); await updateTsConfig(ctx); @@ -64,8 +63,7 @@ describe("updateTsConfig", () => { }); test("don't clobber existing entrypoints", async () => { - ctx.template.installWorkersTypes = true; - ctx.template.skipWranglerTypegen = true; + ctx.template.workersTypes = "installed"; vi.mocked(readFile).mockImplementation( () => `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, diff --git a/packages/create-cloudflare/src/cli.ts b/packages/create-cloudflare/src/cli.ts index f1dfb47026ca..fb9fd6ccf626 100644 --- a/packages/create-cloudflare/src/cli.ts +++ b/packages/create-cloudflare/src/cli.ts @@ -167,10 +167,9 @@ const configure = async (ctx: C3Context) => { addWranglerToGitIgnore(ctx); await updatePackageScripts(ctx); - if (ctx.template.installWorkersTypes) { + if (ctx.template.workersTypes === "installed") { await installWorkersTypes(ctx); - } - if (!ctx.template.skipWranglerTypegen) { + } else if (ctx.template.workersTypes === "generated") { await generateWorkersTypes(ctx); } diff --git a/packages/create-cloudflare/src/templates.ts b/packages/create-cloudflare/src/templates.ts index d5bb2b481697..77706aecd794 100644 --- a/packages/create-cloudflare/src/templates.ts +++ b/packages/create-cloudflare/src/templates.ts @@ -150,11 +150,8 @@ export type TemplateConfig = { bindings?: Record; - /** Default false. For frameworks that are pinned to Wrangler 3. */ - installWorkersTypes?: boolean; - /** Default false. To accomodate SSG frameworks etc. */ - skipWranglerTypegen?: boolean; + workersTypes?: "generated" | "installed" | "none"; }; type CopyFiles = (StaticFileMap | VariantInfo) & { @@ -614,6 +611,9 @@ export const createContext = async ( const directory = dirname(path); const originalCWD = process.cwd(); + // set default to generate types + template.workersTypes ??= "generated"; + template.typesPath ??= "worker-configuration.d.ts"; return { project: { name, path }, // We need to maintain a reference to the original args diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index f544c9ea77f3..049c154e021a 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -32,7 +32,7 @@ export async function generateWorkersTypes(ctx: C3Context) { cwd: ctx.project.path, silent: true, startText: "Generating types for your application", - doneText: `${brandColor("generated")} ${dim(`to \`${ctx.template.typesPath ?? "worker-configuration.d.ts"}\` via \`${typesCmd.join(" ")}\``)}`, + doneText: `${brandColor("generated")} ${dim(`to \`${ctx.template.typesPath}\` via \`${typesCmd.join(" ")}\``)}`, }); if (ctx.template.compatibilityFlags?.includes("nodejs_compat")) { @@ -66,7 +66,7 @@ export async function updateTsConfig(ctx: C3Context) { const config = jsonc.parse(tsconfig); const currentTypes = config.compilerOptions?.types ?? []; let newTypes: string[] = [...currentTypes]; - if (ctx.template.installWorkersTypes) { + if (ctx.template.workersTypes === "installed") { const entrypointVersion = getLatestTypesEntrypoint(ctx); if (entrypointVersion === null) { return; @@ -84,7 +84,7 @@ export async function updateTsConfig(ctx: C3Context) { newTypes.push(typesEntrypoint); } } - if (!ctx.template.skipWranglerTypegen) { + if (ctx.template.workersTypes === "generated") { newTypes.push(ctx.template.typesPath ?? "./worker-configuration.d.ts"); // if generated types include runtime types, remove @cloudflare/workers-types const typegen = readFile( diff --git a/packages/create-cloudflare/templates/docusaurus/pages/c3.ts b/packages/create-cloudflare/templates/docusaurus/pages/c3.ts index aced59dc2f7a..f37ff3355f63 100644 --- a/packages/create-cloudflare/templates/docusaurus/pages/c3.ts +++ b/packages/create-cloudflare/templates/docusaurus/pages/c3.ts @@ -27,6 +27,6 @@ const config: TemplateConfig = { devScript: "preview", deployScript: "deploy", previewScript: "preview", - skipWranglerTypegen: false, + workersTypes: "none", }; export default config; diff --git a/packages/create-cloudflare/templates/docusaurus/workers/c3.ts b/packages/create-cloudflare/templates/docusaurus/workers/c3.ts index 806c456d01f5..50da496aa880 100644 --- a/packages/create-cloudflare/templates/docusaurus/workers/c3.ts +++ b/packages/create-cloudflare/templates/docusaurus/workers/c3.ts @@ -29,6 +29,6 @@ const config: TemplateConfig = { devScript: "start", deployScript: "deploy", previewScript: "preview", - skipWranglerTypegen: true, + workersTypes: "none", }; export default config; diff --git a/packages/create-cloudflare/templates/gatsby/pages/c3.ts b/packages/create-cloudflare/templates/gatsby/pages/c3.ts index bbe079a91d8d..17820fa592af 100644 --- a/packages/create-cloudflare/templates/gatsby/pages/c3.ts +++ b/packages/create-cloudflare/templates/gatsby/pages/c3.ts @@ -47,6 +47,6 @@ const config: TemplateConfig = { devScript: "develop", deployScript: "deploy", previewScript: "preview", - skipWranglerTypegen: true, + workersTypes: "none", }; export default config; diff --git a/packages/create-cloudflare/templates/gatsby/workers/c3.ts b/packages/create-cloudflare/templates/gatsby/workers/c3.ts index e86db793f86c..71f5dd2b1784 100644 --- a/packages/create-cloudflare/templates/gatsby/workers/c3.ts +++ b/packages/create-cloudflare/templates/gatsby/workers/c3.ts @@ -49,6 +49,6 @@ const config: TemplateConfig = { devScript: "develop", deployScript: "deploy", previewScript: "preview", - skipWranglerTypegen: true, + workersTypes: "none", }; export default config; diff --git a/packages/create-cloudflare/templates/qwik/pages/c3.ts b/packages/create-cloudflare/templates/qwik/pages/c3.ts index 6a1747cb47ea..8e9a84f14936 100644 --- a/packages/create-cloudflare/templates/qwik/pages/c3.ts +++ b/packages/create-cloudflare/templates/qwik/pages/c3.ts @@ -146,6 +146,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + workersTypes: "installed", }; export default config; diff --git a/packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts new file mode 100644 index 000000000000..a0b76efdd358 --- /dev/null +++ b/packages/create-cloudflare/templates/qwik/pages/templates/worker-configuration.d.ts @@ -0,0 +1,4 @@ +// Generated by Wrangler +// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` +interface Env { +} diff --git a/packages/create-cloudflare/templates/qwik/workers/c3.ts b/packages/create-cloudflare/templates/qwik/workers/c3.ts index da324850e6bc..5ca426c1b740 100644 --- a/packages/create-cloudflare/templates/qwik/workers/c3.ts +++ b/packages/create-cloudflare/templates/qwik/workers/c3.ts @@ -148,6 +148,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + workersTypes: "installed", }; export default config; diff --git a/packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts new file mode 100644 index 000000000000..a0b76efdd358 --- /dev/null +++ b/packages/create-cloudflare/templates/qwik/workers/templates/worker-configuration.d.ts @@ -0,0 +1,4 @@ +// Generated by Wrangler +// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` +interface Env { +} diff --git a/packages/create-cloudflare/templates/remix/pages/c3.ts b/packages/create-cloudflare/templates/remix/pages/c3.ts index ae8596597db3..7c11e41db704 100644 --- a/packages/create-cloudflare/templates/remix/pages/c3.ts +++ b/packages/create-cloudflare/templates/remix/pages/c3.ts @@ -65,6 +65,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + workersTypes: "installed", }; export default config; diff --git a/packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts new file mode 100644 index 000000000000..5b2319b3f29f --- /dev/null +++ b/packages/create-cloudflare/templates/remix/pages/templates/worker-configuration.d.ts @@ -0,0 +1,4 @@ +// Generated by Wrangler +// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen` +interface Env { +} diff --git a/packages/create-cloudflare/templates/remix/workers/c3.ts b/packages/create-cloudflare/templates/remix/workers/c3.ts index af587725d709..1b201a0f2ec6 100644 --- a/packages/create-cloudflare/templates/remix/workers/c3.ts +++ b/packages/create-cloudflare/templates/remix/workers/c3.ts @@ -48,6 +48,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", - installWorkersTypes: true, + workersTypes: "installed", }; export default config; diff --git a/packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts b/packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts new file mode 100644 index 000000000000..5b2319b3f29f --- /dev/null +++ b/packages/create-cloudflare/templates/remix/workers/templates/worker-configuration.d.ts @@ -0,0 +1,4 @@ +// Generated by Wrangler +// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen` +interface Env { +} From 5b80895f1f98d82cc1cefce14562bca90bbf9504 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Tue, 6 May 2025 11:56:12 +0100 Subject: [PATCH 12/17] set env interface and types path in one place --- .../e2e-tests/frameworks.test.ts | 30 +++++--- .../frameworks/framework-test-config.ts | 72 ------------------- packages/create-cloudflare/src/templates.ts | 3 + packages/create-cloudflare/src/workers.ts | 3 +- .../templates/hono/pages/c3.ts | 5 +- .../templates/hono/workers/c3.ts | 4 +- .../templates/next/pages/c3.ts | 8 ++- .../templates/next/workers/c3.ts | 8 ++- .../templates/svelte/pages/c3.ts | 5 +- .../templates/svelte/workers/c3.ts | 5 +- 10 files changed, 47 insertions(+), 96 deletions(-) diff --git a/packages/create-cloudflare/e2e-tests/frameworks.test.ts b/packages/create-cloudflare/e2e-tests/frameworks.test.ts index 0273948ae379..cfb16cfe44f2 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks.test.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks.test.ts @@ -176,7 +176,11 @@ describe.concurrent( project.path, logStream, ); - await verifyBuildCfTypesScript(testConfig, project.path, logStream); + await verifyBuildCfTypesScript( + frameworkConfig, + project.path, + logStream, + ); await verifyBuildScript(testConfig, project.path, logStream); } catch (e) { console.error("ERROR", e); @@ -353,11 +357,11 @@ const verifyPreviewScript = async ( }; const verifyBuildCfTypesScript = async ( - { verifyBuildCfTypes }: FrameworkTestConfig, + { workersTypes, typesPath, envInterfaceName }: TemplateConfig, projectPath: string, logStream: Writable, ) => { - if (!verifyBuildCfTypes) { + if (workersTypes === "none") { return; } @@ -370,23 +374,27 @@ const verifyBuildCfTypesScript = async ( await waitForExit(buildTypesProc); - const { outputFile, envInterfaceName } = verifyBuildCfTypes; - - const outputFileContent = readFile(join(projectPath, outputFile)).split("\n"); + const outputFileContent = readFile( + join(projectPath, typesPath ?? "worker-configuration.d.ts"), + ).split("\n"); // the file contains the env interface const hasEnvInterfacePre = outputFileContent.some( (line) => // old type gen - some framework templates pin older versions of wrangler - line === `interface ${envInterfaceName} {` || + line === `interface ${envInterfaceName ?? "Env"} {` || // new after importable env change - line === `interface ${envInterfaceName} extends Cloudflare.Env {}`, + line === + `interface ${envInterfaceName ?? "Env"} extends Cloudflare.Env {}`, ); expect(hasEnvInterfacePre).toBe(true); - expect(outputFileContent[2]).match( - /\/\/ Runtime types generated with workerd@1\.\d{8}\.\d \d{4}-\d{2}-\d{2} ([a-z_]+,?)*/, - ); + // if the types were installed, only the Env types will be present + if (workersTypes === "generated") { + expect(outputFileContent[2]).match( + /\/\/ Runtime types generated with workerd@1\.\d{8}\.\d \d{4}-\d{2}-\d{2} ([a-z_]+,?)*/, + ); + } }; const verifyBuildScript = async ( diff --git a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts index dea941585179..a4cea2cc50d9 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts @@ -16,10 +16,6 @@ export default function getFrameworkTestConfig(pm: string) { expectedText: "Hello from Cloudflare", previewArgs: ["--host=127.0.0.1"], }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, flags: ["--no-install", "--no-git-init"], }, "astro:pages": { @@ -40,10 +36,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, flags: [ "--skip-houston", "--no-install", @@ -72,10 +64,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, flags: [ "--skip-houston", "--no-install", @@ -150,10 +138,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/api/v1/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, verifyBuild: { outputDir: "./dist/analog/public", script: "build", @@ -192,10 +176,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Congratulations! Your app is running.", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, flags: ["--style", "sass"], }, "gatsby:pages": { @@ -250,10 +230,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Hello!", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "CloudflareBindings", - }, promptHandlers: [ { matcher: /Do you want to install project dependencies\?/, @@ -273,10 +249,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/message", expectedText: "Hello Hono!", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "CloudflareBindings", - }, promptHandlers: [ { matcher: /Do you want to install project dependencies\?/, @@ -374,10 +346,6 @@ export default function getFrameworkTestConfig(pm: string) { }, ], testCommitMessage: true, - verifyBuildCfTypes: { - outputFile: "env.d.ts", - envInterfaceName: "CloudflareEnv", - }, verifyDeploy: { route: "/", expectedText: "Create Next App", @@ -414,10 +382,6 @@ export default function getFrameworkTestConfig(pm: string) { "@/*", "--src-dir", ], - verifyBuildCfTypes: { - outputFile: "cloudflare-env.d.ts", - envInterfaceName: "CloudflareEnv", - }, verifyPreview: { previewArgs: ["--"], route: "/test", @@ -455,10 +419,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, verifyBuild: { outputDir: "./dist", script: "build", @@ -486,10 +446,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "react:pages": { argv: ["--platform", "pages"], @@ -510,10 +466,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite + React", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "react:workers": { argv: ["--platform", "workers"], @@ -542,10 +494,6 @@ export default function getFrameworkTestConfig(pm: string) { // not actually running the client side JS. expectedText: "Vite + React + TS", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, solid: { promptHandlers: [ @@ -570,10 +518,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Hello world", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "svelte:pages": { argv: ["--platform", "pages"], @@ -602,10 +546,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "./src/worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "svelte:workers": { argv: ["--platform", "workers"], @@ -628,10 +568,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, - verifyBuildCfTypes: { - outputFile: "./src/worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, "vue:pages": { argv: ["--platform", "pages"], @@ -645,10 +581,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite App", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, flags: ["--ts"], }, "vue:workers": { @@ -664,10 +596,6 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite App", }, - verifyBuildCfTypes: { - outputFile: "worker-configuration.d.ts", - envInterfaceName: "Env", - }, }, }; } diff --git a/packages/create-cloudflare/src/templates.ts b/packages/create-cloudflare/src/templates.ts index 77706aecd794..0825960d2c57 100644 --- a/packages/create-cloudflare/src/templates.ts +++ b/packages/create-cloudflare/src/templates.ts @@ -144,6 +144,8 @@ export type TemplateConfig = { /** The file path to the generated types file. Defaults to worker-configuration.d.ts*/ typesPath?: string; + /** The name of the Env type generated by wrangler types. Defaults to `Env`*/ + envInterfaceName?: string; /** The file path of the template. This is used internally and isn't a user facing config value.*/ path?: string; @@ -614,6 +616,7 @@ export const createContext = async ( // set default to generate types template.workersTypes ??= "generated"; template.typesPath ??= "worker-configuration.d.ts"; + template.envInterfaceName ??= "Env"; return { project: { name, path }, // We need to maintain a reference to the original args diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 049c154e021a..7b8bf6c88584 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -83,8 +83,7 @@ export async function updateTsConfig(ctx: C3Context) { ); newTypes.push(typesEntrypoint); } - } - if (ctx.template.workersTypes === "generated") { + } else if (ctx.template.workersTypes === "generated") { newTypes.push(ctx.template.typesPath ?? "./worker-configuration.d.ts"); // if generated types include runtime types, remove @cloudflare/workers-types const typegen = readFile( diff --git a/packages/create-cloudflare/templates/hono/pages/c3.ts b/packages/create-cloudflare/templates/hono/pages/c3.ts index 857cea6d92a9..7af984988205 100644 --- a/packages/create-cloudflare/templates/hono/pages/c3.ts +++ b/packages/create-cloudflare/templates/hono/pages/c3.ts @@ -19,6 +19,8 @@ const generate = async (ctx: C3Context) => { logRaw(""); // newline }; +const envInterfaceName = "CloudflareBindings"; + const config: TemplateConfig = { configVersion: 1, id: "hono", @@ -33,12 +35,13 @@ const config: TemplateConfig = { generate, transformPackageJson: async () => ({ scripts: { - "cf-typegen": "wrangler types --env-interface CloudflareBindings", + "cf-typegen": `wrangler types --env-interface ${envInterfaceName}`, preview: "vite build && wrangler pages dev", }, }), devScript: "dev", deployScript: "deploy", previewScript: "preview", + envInterfaceName, }; export default config; diff --git a/packages/create-cloudflare/templates/hono/workers/c3.ts b/packages/create-cloudflare/templates/hono/workers/c3.ts index 2b544aa3717e..95cbfd1577ed 100644 --- a/packages/create-cloudflare/templates/hono/workers/c3.ts +++ b/packages/create-cloudflare/templates/hono/workers/c3.ts @@ -19,6 +19,7 @@ const generate = async (ctx: C3Context) => { logRaw(""); // newline }; +const envInterfaceName = "CloudflareBindings"; const config: TemplateConfig = { configVersion: 1, id: "hono", @@ -32,11 +33,12 @@ const config: TemplateConfig = { generate, transformPackageJson: async () => ({ scripts: { - "cf-typegen": "wrangler types --env-interface CloudflareBindings", + "cf-typegen": `wrangler types --env-interface ${envInterfaceName}`, }, }), devScript: "dev", deployScript: "deploy", previewScript: "dev", + envInterfaceName, }; export default config; diff --git a/packages/create-cloudflare/templates/next/pages/c3.ts b/packages/create-cloudflare/templates/next/pages/c3.ts index 25b7ce0a7f41..15afef64864d 100644 --- a/packages/create-cloudflare/templates/next/pages/c3.ts +++ b/packages/create-cloudflare/templates/next/pages/c3.ts @@ -155,6 +155,9 @@ const addDevDependencies = async (installEslintPlugin: boolean) => { }); }; +const envInterfaceName = "CloudflareEnv"; +const typesPath = "./env.d.ts"; + export default { configVersion: 1, id: "next", @@ -212,7 +215,7 @@ export default { preview: `${pagesBuildRunCommand} && wrangler pages dev`, deploy: `${pagesBuildRunCommand} && wrangler pages deploy`, ...(usesTypescript(ctx) && { - "cf-typegen": `wrangler types --env-interface CloudflareEnv env.d.ts`, + "cf-typegen": `wrangler types --env-interface ${envInterfaceName} ${typesPath}`, }), }, }; @@ -221,5 +224,6 @@ export default { previewScript: "preview", deployScript: "deploy", compatibilityFlags: ["nodejs_compat"], - typesPath: "./env.d.ts", + typesPath, + envInterfaceName, } as TemplateConfig; diff --git a/packages/create-cloudflare/templates/next/workers/c3.ts b/packages/create-cloudflare/templates/next/workers/c3.ts index 5a8834950f86..04ce5a1ac68e 100644 --- a/packages/create-cloudflare/templates/next/workers/c3.ts +++ b/packages/create-cloudflare/templates/next/workers/c3.ts @@ -42,6 +42,8 @@ const updateNextConfig = (usesTs: boolean) => { s.stop(`${brandColor(`updated`)} ${dim(`\`${configFile}\``)}`); }; +const envInterfaceName = "CloudflareBindings"; +const typesPath = "./cloudflare-env.d.ts"; export default { configVersion: 1, id: "next", @@ -59,13 +61,13 @@ export default { scripts: { deploy: `opennextjs-cloudflare build && opennextjs-cloudflare deploy`, preview: `opennextjs-cloudflare build && opennextjs-cloudflare preview`, - "cf-typegen": `wrangler types --env-interface CloudflareEnv ./cloudflare-env.d.ts`, + "cf-typegen": `wrangler types --env-interface ${envInterfaceName} ${typesPath}`, }, }), devScript: "dev", previewScript: "preview", deployScript: "deploy", - - typesPath: "./cloudflare-env.d.ts", + typesPath, + envInterfaceName, compatibilityFlags: ["nodejs_compat"], } as TemplateConfig; diff --git a/packages/create-cloudflare/templates/svelte/pages/c3.ts b/packages/create-cloudflare/templates/svelte/pages/c3.ts index d87f48e128ea..7c2b6fa17a92 100644 --- a/packages/create-cloudflare/templates/svelte/pages/c3.ts +++ b/packages/create-cloudflare/templates/svelte/pages/c3.ts @@ -123,6 +123,7 @@ const updateTypeDefinitions = (ctx: C3Context) => { }); }; +const typesPath = "src/worker-configuration.d.ts"; const config: TemplateConfig = { configVersion: 1, id: "svelte", @@ -145,7 +146,7 @@ const config: TemplateConfig = { if (usesTypescript(ctx)) { scripts = { ...scripts, - "cf-typegen": `wrangler types ./src/worker-configuration.d.ts`, + "cf-typegen": `wrangler types ${typesPath}`, }; } @@ -154,6 +155,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", - typesPath: "./src/worker-configuration.d.ts", + typesPath, }; export default config; diff --git a/packages/create-cloudflare/templates/svelte/workers/c3.ts b/packages/create-cloudflare/templates/svelte/workers/c3.ts index 47d43649c1c4..cda88ca08784 100644 --- a/packages/create-cloudflare/templates/svelte/workers/c3.ts +++ b/packages/create-cloudflare/templates/svelte/workers/c3.ts @@ -93,6 +93,7 @@ const updateTypeDefinitions = (ctx: C3Context) => { }); }; +const typesPath = "./src/worker-configuration.d.ts"; const config: TemplateConfig = { configVersion: 1, id: "svelte", @@ -114,7 +115,7 @@ const config: TemplateConfig = { if (usesTypescript(ctx)) { scripts = { ...scripts, - "cf-typegen": `wrangler types ./src/worker-configuration.d.ts`, + "cf-typegen": `wrangler types ${typesPath}`, }; } @@ -123,6 +124,6 @@ const config: TemplateConfig = { devScript: "dev", deployScript: "deploy", previewScript: "preview", - typesPath: "./src/worker-configuration.d.ts", + typesPath, }; export default config; From 74f28ea937f33405dcb40535a23ecf8a528b8cdb Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Tue, 6 May 2025 12:19:27 +0100 Subject: [PATCH 13/17] set defaults in test too --- packages/create-cloudflare/e2e-tests/frameworks.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/create-cloudflare/e2e-tests/frameworks.test.ts b/packages/create-cloudflare/e2e-tests/frameworks.test.ts index cfb16cfe44f2..9bea35ed5ffc 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks.test.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks.test.ts @@ -81,7 +81,9 @@ describe.concurrent( Object.entries(frameworkTests).forEach(([frameworkKey, testConfig]) => { const frameworkConfig = getFrameworkConfig(frameworkKey); - + frameworkConfig.workersTypes ??= "generated"; + frameworkConfig.typesPath ??= "worker-configuration.d.ts"; + frameworkConfig.envInterfaceName ??= "Env"; test({ experimental }).runIf( shouldRunTest(frameworkConfig.id, testConfig), )( From 3723079ec95e73d8f336a1da9e44835b9d021970 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Wed, 7 May 2025 12:09:49 +0100 Subject: [PATCH 14/17] pr feedback --- .../e2e-tests/frameworks.test.ts | 10 +-- .../src/__tests__/workers.test.ts | 15 +++-- packages/create-cloudflare/src/templates.ts | 20 ++++-- packages/create-cloudflare/src/workers.ts | 62 +++++++++++++++---- 4 files changed, 76 insertions(+), 31 deletions(-) diff --git a/packages/create-cloudflare/e2e-tests/frameworks.test.ts b/packages/create-cloudflare/e2e-tests/frameworks.test.ts index 9bea35ed5ffc..d52d9f21ccc5 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks.test.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks.test.ts @@ -80,10 +80,12 @@ describe.concurrent( }); Object.entries(frameworkTests).forEach(([frameworkKey, testConfig]) => { - const frameworkConfig = getFrameworkConfig(frameworkKey); - frameworkConfig.workersTypes ??= "generated"; - frameworkConfig.typesPath ??= "worker-configuration.d.ts"; - frameworkConfig.envInterfaceName ??= "Env"; + const frameworkConfig = { + workersTypes: "generated" as const, + typesPath: "worker-configuration.d.ts", + envInterfaceName: "Env", + ...getFrameworkConfig(frameworkKey), + }; test({ experimental }).runIf( shouldRunTest(frameworkConfig.id, testConfig), )( diff --git a/packages/create-cloudflare/src/__tests__/workers.test.ts b/packages/create-cloudflare/src/__tests__/workers.test.ts index 49513d315afa..c2c21a6501a5 100644 --- a/packages/create-cloudflare/src/__tests__/workers.test.ts +++ b/packages/create-cloudflare/src/__tests__/workers.test.ts @@ -38,7 +38,7 @@ describe("updateTsConfig", () => { test("installing workers types", async () => { ctx.template.workersTypes = "installed"; - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(writeFile).toHaveBeenCalled(); @@ -49,7 +49,7 @@ describe("updateTsConfig", () => { test("tsconfig.json not found", async () => { vi.mocked(existsSync).mockImplementation(() => false); - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(writeFile).not.toHaveBeenCalled(); }); @@ -57,7 +57,7 @@ describe("updateTsConfig", () => { ctx.template.workersTypes = "installed"; vi.mocked(getLatestTypesEntrypoint).mockReturnValue(null); - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(writeFile).not.toHaveBeenCalled(); }); @@ -68,7 +68,7 @@ describe("updateTsConfig", () => { () => `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, ); - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `"@cloudflare/workers-types/2021-03-20"`, @@ -77,14 +77,13 @@ describe("updateTsConfig", () => { test("will remove workers-types when generating types, if generated types include runtime types", async () => { vi.mocked(readFile).mockImplementation((path) => { - console.log("path", path); if (path.includes("tsconfig.json")) { return `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`; } else { return "// Runtime types generated with workerd"; } }); - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(vi.mocked(writeFile).mock.calls[0][1]).not.toContain( `"@cloudflare/workers-types/2021-03-20"`, ); @@ -98,7 +97,7 @@ describe("updateTsConfig", () => { return "no runtime types here"; } }); - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `"@cloudflare/workers-types/2021-03-20"`, @@ -106,7 +105,7 @@ describe("updateTsConfig", () => { }); test("will add generated types file", async () => { - await updateTsConfig(ctx); + await updateTsConfig(ctx, false); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `./worker-configuration.d.ts`, ); diff --git a/packages/create-cloudflare/src/templates.ts b/packages/create-cloudflare/src/templates.ts index 0825960d2c57..f0d332c431c5 100644 --- a/packages/create-cloudflare/src/templates.ts +++ b/packages/create-cloudflare/src/templates.ts @@ -142,7 +142,7 @@ export type TemplateConfig = { /** The key of the package.json "scripts" entry for previewing the project. Defaults to undefined (there might not be such script) */ previewScript?: string; - /** The file path to the generated types file. Defaults to worker-configuration.d.ts*/ + /** The path to the generated types file. Defaults to `worker-configuration.d.ts` */ typesPath?: string; /** The name of the Env type generated by wrangler types. Defaults to `Env`*/ envInterfaceName?: string; @@ -152,7 +152,12 @@ export type TemplateConfig = { bindings?: Record; - /** Default false. To accomodate SSG frameworks etc. */ + /** + * Source for runtime types: + * "generated" = types are generated by wrangler types. Default. + * "installed" = types are installed from @cloudflare/workers-types. + * "none" = no runtime types are provided (e.g. framework for purely static sites). + */ workersTypes?: "generated" | "installed" | "none"; }; @@ -565,6 +570,13 @@ export const createContext = async ( } } + template = { + workersTypes: "generated", + typesPath: "worker-configuration.d.ts", + envInterfaceName: "Env", + ...template, + }; + const path = resolve(projectName); const languageVariants = template.copyFiles && @@ -613,10 +625,6 @@ export const createContext = async ( const directory = dirname(path); const originalCWD = process.cwd(); - // set default to generate types - template.workersTypes ??= "generated"; - template.typesPath ??= "worker-configuration.d.ts"; - template.envInterfaceName ??= "Env"; return { project: { name, path }, // We need to maintain a reference to the original args diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 7b8bf6c88584..a80733c7c5fb 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -1,13 +1,21 @@ import { existsSync } from "fs"; -import { join, resolve } from "path"; +import { join } from "path"; import { warn } from "@cloudflare/cli"; import { brandColor, dim } from "@cloudflare/cli/colors"; +import TOML from "@iarna/toml"; import { runCommand } from "helpers/command"; import { getLatestTypesEntrypoint } from "helpers/compatDate"; import { readFile, readJSON, usesTypescript, writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; +import { parse as jsoncParse } from "jsonc-parser"; import * as jsonc from "jsonc-parser"; +import { + readWranglerJson, + readWranglerToml, + wranglerJsonExists, + wranglerTomlExists, +} from "./wrangler/config"; import type { C3Context, PackageJson } from "types"; /** @@ -18,9 +26,12 @@ export async function generateWorkersTypes(ctx: C3Context) { if (!usesTypescript(ctx)) { return; } - const packageJsonPath = resolve("package.json"); + const packageJsonPath = join(ctx.project.path, "package.json"); + if (!existsSync(packageJsonPath)) { + return; + } const packageManifest = readJSON(packageJsonPath) as PackageJson; - if (!Object.keys(packageManifest.scripts ?? {}).includes("cf-typegen")) { + if (!packageManifest.scripts?.["cf-typegen"]) { return; } @@ -35,19 +46,43 @@ export async function generateWorkersTypes(ctx: C3Context) { doneText: `${brandColor("generated")} ${dim(`to \`${ctx.template.typesPath}\` via \`${typesCmd.join(" ")}\``)}`, }); - if (ctx.template.compatibilityFlags?.includes("nodejs_compat")) { + const usesNodeCompat = await maybeInstallNodeTypes(ctx, npm); + + delete packageManifest["devDependencies"]?.["@cloudflare/workers-types"]; + + writeFile(packageJsonPath, JSON.stringify(packageManifest, null, 2)); + await updateTsConfig(ctx, usesNodeCompat); +} + +const maybeInstallNodeTypes = async (ctx: C3Context, npm: string) => { + let parsedConfig: Record = {}; + if (wranglerJsonExists(ctx)) { + const wranglerJsonStr = readWranglerJson(ctx); + parsedConfig = jsoncParse(wranglerJsonStr, undefined, { + allowTrailingComma: true, + }); + } else if (wranglerTomlExists(ctx)) { + const wranglerTomlStr = readWranglerToml(ctx); + parsedConfig = TOML.parse(wranglerTomlStr); + } + + const compatibility_flags = Array.isArray(parsedConfig["compatibility_flags"]) + ? parsedConfig["compatibility_flags"] + : []; + + if ( + compatibility_flags.includes("nodejs_compat") || + compatibility_flags.includes("nodejs_compat_v2") + ) { await installPackages(["@types/node"], { dev: true, startText: "Installing @types/node", doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, }); + return true; } - - delete packageManifest["devDependencies"]?.["@cloudflare/workers-types"]; - - writeFile(packageJsonPath, JSON.stringify(packageManifest, null, 2)); - await updateTsConfig(ctx); -} + return false; +}; /** * update `types` in tsconfig: @@ -56,7 +91,7 @@ export async function generateWorkersTypes(ctx: C3Context) { * - add generated types file if types were generated * - add node if node compat */ -export async function updateTsConfig(ctx: C3Context) { +export async function updateTsConfig(ctx: C3Context, usesNodeCompat: boolean) { const tsconfigPath = join(ctx.project.path, "tsconfig.json"); if (!existsSync(tsconfigPath)) { return; @@ -99,7 +134,7 @@ export async function updateTsConfig(ctx: C3Context) { ); } // add node types if nodejs_compat is enabled - if (ctx.template.compatibilityFlags?.includes("nodejs_compat")) { + if (usesNodeCompat) { newTypes.push("node"); } } @@ -143,5 +178,6 @@ export async function installWorkersTypes(ctx: C3Context) { startText: "Installing @cloudflare/workers-types", doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, }); - await updateTsConfig(ctx); + const usesNodeCompat = await maybeInstallNodeTypes(ctx, npm); + await updateTsConfig(ctx, usesNodeCompat); } From 34a9edc008786d02f55560274016fec787ba2d50 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Wed, 7 May 2025 15:15:55 +0100 Subject: [PATCH 15/17] update tests --- .../e2e-tests/frameworks.test.ts | 65 ++++++++++--------- .../framework-test-config-experimental.ts | 1 + .../frameworks/framework-test-config.ts | 27 ++++++++ .../src/__tests__/workers.test.ts | 14 ++-- packages/create-cloudflare/src/workers.ts | 20 +++--- 5 files changed, 80 insertions(+), 47 deletions(-) diff --git a/packages/create-cloudflare/e2e-tests/frameworks.test.ts b/packages/create-cloudflare/e2e-tests/frameworks.test.ts index d52d9f21ccc5..bb3483849867 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks.test.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks.test.ts @@ -12,6 +12,7 @@ import { import { detectPackageManager } from "helpers/packageManagers"; import { retry } from "helpers/retry"; import { sleep } from "helpers/sleep"; +import * as jsonc from "jsonc-parser"; import { fetch } from "undici"; import { beforeAll, describe, expect } from "vitest"; import { deleteProject, deleteWorker } from "../scripts/common"; @@ -41,12 +42,9 @@ import type { Writable } from "stream"; type FrameworkTestConfig = RunnerConfig & { testCommitMessage: boolean; + nodeCompat: boolean; unsupportedPms?: string[]; unsupportedOSs?: string[]; - verifyBuildCfTypes?: { - outputFile: string; - envInterfaceName: string; - }; verifyBuild?: { outputDir: string; script: string; @@ -180,11 +178,8 @@ describe.concurrent( project.path, logStream, ); - await verifyBuildCfTypesScript( - frameworkConfig, - project.path, - logStream, - ); + + await verifyTypes(testConfig, frameworkConfig, project.path); await verifyBuildScript(testConfig, project.path, logStream); } catch (e) { console.error("ERROR", e); @@ -360,45 +355,53 @@ const verifyPreviewScript = async ( } }; -const verifyBuildCfTypesScript = async ( - { workersTypes, typesPath, envInterfaceName }: TemplateConfig, +const verifyTypes = async ( + { nodeCompat }: FrameworkTestConfig, + { + workersTypes, + typesPath = "./worker-configuration.d.ts", + envInterfaceName = "Env", + }: TemplateConfig, projectPath: string, - logStream: Writable, ) => { if (workersTypes === "none") { return; } - // Run the `cf-typegen` script to generate types for bindings in fixture - const buildTypesProc = spawnWithLogging( - [pm, "run", "cf-typegen"], - { cwd: projectPath }, - logStream, - ); - - await waitForExit(buildTypesProc); + const outputFileContent = readFile(join(projectPath, typesPath)).split("\n"); - const outputFileContent = readFile( - join(projectPath, typesPath ?? "worker-configuration.d.ts"), - ).split("\n"); - - // the file contains the env interface - const hasEnvInterfacePre = outputFileContent.some( + const hasEnvInterface = outputFileContent.some( (line) => // old type gen - some framework templates pin older versions of wrangler - line === `interface ${envInterfaceName ?? "Env"} {` || + line === `interface ${envInterfaceName} {` || // new after importable env change - line === - `interface ${envInterfaceName ?? "Env"} extends Cloudflare.Env {}`, + line === `interface ${envInterfaceName} extends Cloudflare.Env {}`, ); - expect(hasEnvInterfacePre).toBe(true); + expect(hasEnvInterface).toBe(true); - // if the types were installed, only the Env types will be present + // if the runtime types were installed, they wont be in this file if (workersTypes === "generated") { expect(outputFileContent[2]).match( /\/\/ Runtime types generated with workerd@1\.\d{8}\.\d \d{4}-\d{2}-\d{2} ([a-z_]+,?)*/, ); } + + const tsconfigPath = join(projectPath, "tsconfig.json"); + const tsconfigTypes = jsonc.parse(readFile(tsconfigPath)).compilerOptions + ?.types; + if (workersTypes === "generated") { + expect(tsconfigTypes).toContain(typesPath); + } + if (workersTypes === "installed") { + expect( + tsconfigTypes.some((x: string) => + x.includes("@cloudflare/workers-types"), + ), + ).toBe(true); + } + if (nodeCompat) { + expect(tsconfigTypes).toContain(`node`); + } }; const verifyBuildScript = async ( diff --git a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config-experimental.ts b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config-experimental.ts index f2ba3b1f2bf9..c9bdf731b9e0 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config-experimental.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config-experimental.ts @@ -25,6 +25,7 @@ export default function getFrameworkTestConfigExperimental() { route: "/", expectedText: "Hello world", }, + nodeCompat: true, }, }; } diff --git a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts index a4cea2cc50d9..997d47753b4b 100644 --- a/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts +++ b/packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts @@ -16,6 +16,7 @@ export default function getFrameworkTestConfig(pm: string) { expectedText: "Hello from Cloudflare", previewArgs: ["--host=127.0.0.1"], }, + nodeCompat: false, flags: ["--no-install", "--no-git-init"], }, "astro:pages": { @@ -36,6 +37,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: true, flags: [ "--skip-houston", "--no-install", @@ -64,6 +66,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: true, flags: [ "--skip-houston", "--no-install", @@ -88,6 +91,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Dinosaurs are cool", }, + nodeCompat: false, flags: [`--package-manager`, pm], promptHandlers: [ // { @@ -114,6 +118,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Dinosaurs are cool", }, + nodeCompat: false, flags: [`--package-manager`, pm], promptHandlers: [ { @@ -144,6 +149,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/api/v1/test", expectedText: "C3_TEST", }, + nodeCompat: false, flags: ["--skipTailwind"], }, "angular:pages": { @@ -160,6 +166,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Congratulations! Your app is running.", }, + nodeCompat: false, flags: ["--style", "sass"], }, "angular:workers": { @@ -176,6 +183,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Congratulations! Your app is running.", }, + nodeCompat: false, flags: ["--style", "sass"], }, "gatsby:pages": { @@ -197,6 +205,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Gatsby!", }, + nodeCompat: false, }, "gatsby:workers": { argv: ["--platform", "workers"], @@ -217,6 +226,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Gatsby!", }, + nodeCompat: false, }, "hono:pages": { argv: ["--platform", "pages"], @@ -230,6 +240,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Hello!", }, + nodeCompat: false, promptHandlers: [ { matcher: /Do you want to install project dependencies\?/, @@ -249,6 +260,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/message", expectedText: "Hello Hono!", }, + nodeCompat: false, promptHandlers: [ { matcher: /Do you want to install project dependencies\?/, @@ -275,6 +287,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Welcome to Qwik", }, + nodeCompat: true, }, "qwik:workers": { argv: ["--platform", "workers"], @@ -296,6 +309,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Welcome to Qwik", }, + nodeCompat: true, }, "remix:pages": { argv: ["--platform", "pages"], @@ -317,6 +331,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: false, flags: ["--typescript", "--no-install", "--no-git-init"], }, "remix:workers": { @@ -333,6 +348,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: false, flags: ["--typescript", "--no-install", "--no-git-init"], }, "next:pages": { @@ -356,6 +372,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Create Next App", }, + nodeCompat: true, flags: [ "--typescript", "--no-install", @@ -391,6 +408,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Create Next App", }, + nodeCompat: true, // see https://github.com/cloudflare/next-on-pages/blob/main/packages/next-on-pages/docs/supported.md#operating-systems unsupportedOSs: ["win32"], unsupportedPms: [ @@ -415,6 +433,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Welcome to Nuxt!", }, + nodeCompat: false, verifyPreview: { route: "/test", expectedText: "C3_TEST", @@ -446,6 +465,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: false, }, "react:pages": { argv: ["--platform", "pages"], @@ -466,6 +486,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite + React", }, + nodeCompat: false, }, "react:workers": { argv: ["--platform", "workers"], @@ -494,6 +515,7 @@ export default function getFrameworkTestConfig(pm: string) { // not actually running the client side JS. expectedText: "Vite + React + TS", }, + nodeCompat: false, }, solid: { promptHandlers: [ @@ -518,6 +540,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Hello world", }, + nodeCompat: true, }, "svelte:pages": { argv: ["--platform", "pages"], @@ -546,6 +569,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: false, }, "svelte:workers": { argv: ["--platform", "workers"], @@ -568,6 +592,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/test", expectedText: "C3_TEST", }, + nodeCompat: false, }, "vue:pages": { argv: ["--platform", "pages"], @@ -581,6 +606,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite App", }, + nodeCompat: false, flags: ["--ts"], }, "vue:workers": { @@ -596,6 +622,7 @@ export default function getFrameworkTestConfig(pm: string) { route: "/", expectedText: "Vite App", }, + nodeCompat: false, }, }; } diff --git a/packages/create-cloudflare/src/__tests__/workers.test.ts b/packages/create-cloudflare/src/__tests__/workers.test.ts index c2c21a6501a5..4dde1445ab01 100644 --- a/packages/create-cloudflare/src/__tests__/workers.test.ts +++ b/packages/create-cloudflare/src/__tests__/workers.test.ts @@ -38,7 +38,7 @@ describe("updateTsConfig", () => { test("installing workers types", async () => { ctx.template.workersTypes = "installed"; - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(writeFile).toHaveBeenCalled(); @@ -49,7 +49,7 @@ describe("updateTsConfig", () => { test("tsconfig.json not found", async () => { vi.mocked(existsSync).mockImplementation(() => false); - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(writeFile).not.toHaveBeenCalled(); }); @@ -57,7 +57,7 @@ describe("updateTsConfig", () => { ctx.template.workersTypes = "installed"; vi.mocked(getLatestTypesEntrypoint).mockReturnValue(null); - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(writeFile).not.toHaveBeenCalled(); }); @@ -68,7 +68,7 @@ describe("updateTsConfig", () => { () => `{ "compilerOptions": { "types" : ["@cloudflare/workers-types/2021-03-20"]} }`, ); - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `"@cloudflare/workers-types/2021-03-20"`, @@ -83,7 +83,7 @@ describe("updateTsConfig", () => { return "// Runtime types generated with workerd"; } }); - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(vi.mocked(writeFile).mock.calls[0][1]).not.toContain( `"@cloudflare/workers-types/2021-03-20"`, ); @@ -97,7 +97,7 @@ describe("updateTsConfig", () => { return "no runtime types here"; } }); - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `"@cloudflare/workers-types/2021-03-20"`, @@ -105,7 +105,7 @@ describe("updateTsConfig", () => { }); test("will add generated types file", async () => { - await updateTsConfig(ctx, false); + await updateTsConfig(ctx, { usesNodeCompat: false }); expect(vi.mocked(writeFile).mock.calls[0][1]).toContain( `./worker-configuration.d.ts`, ); diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index a80733c7c5fb..1a544627db64 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -8,7 +8,6 @@ import { getLatestTypesEntrypoint } from "helpers/compatDate"; import { readFile, readJSON, usesTypescript, writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; -import { parse as jsoncParse } from "jsonc-parser"; import * as jsonc from "jsonc-parser"; import { readWranglerJson, @@ -51,14 +50,14 @@ export async function generateWorkersTypes(ctx: C3Context) { delete packageManifest["devDependencies"]?.["@cloudflare/workers-types"]; writeFile(packageJsonPath, JSON.stringify(packageManifest, null, 2)); - await updateTsConfig(ctx, usesNodeCompat); + await updateTsConfig(ctx, { usesNodeCompat }); } const maybeInstallNodeTypes = async (ctx: C3Context, npm: string) => { let parsedConfig: Record = {}; if (wranglerJsonExists(ctx)) { const wranglerJsonStr = readWranglerJson(ctx); - parsedConfig = jsoncParse(wranglerJsonStr, undefined, { + parsedConfig = jsonc.parse(wranglerJsonStr, undefined, { allowTrailingComma: true, }); } else if (wranglerTomlExists(ctx)) { @@ -91,7 +90,10 @@ const maybeInstallNodeTypes = async (ctx: C3Context, npm: string) => { * - add generated types file if types were generated * - add node if node compat */ -export async function updateTsConfig(ctx: C3Context, usesNodeCompat: boolean) { +export async function updateTsConfig( + ctx: C3Context, + { usesNodeCompat }: { usesNodeCompat: boolean }, +) { const tsconfigPath = join(ctx.project.path, "tsconfig.json"); if (!existsSync(tsconfigPath)) { return; @@ -133,10 +135,10 @@ export async function updateTsConfig(ctx: C3Context, usesNodeCompat: boolean) { (t: string) => !t.startsWith("@cloudflare/workers-types"), ); } - // add node types if nodejs_compat is enabled - if (usesNodeCompat) { - newTypes.push("node"); - } + } + // add node types if nodejs_compat is enabled + if (usesNodeCompat) { + newTypes.push("node"); } if (newTypes.sort() === currentTypes.sort()) { return; @@ -179,5 +181,5 @@ export async function installWorkersTypes(ctx: C3Context) { doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, }); const usesNodeCompat = await maybeInstallNodeTypes(ctx, npm); - await updateTsConfig(ctx, usesNodeCompat); + await updateTsConfig(ctx, { usesNodeCompat }); } From 2de086c56fdd4098c184e8cb75a29ee8e71d8b49 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Thu, 8 May 2025 10:19:20 +0100 Subject: [PATCH 16/17] tidy up --- packages/create-cloudflare/src/cli.ts | 9 ++--- packages/create-cloudflare/src/workers.ts | 41 ++++++++++++----------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/packages/create-cloudflare/src/cli.ts b/packages/create-cloudflare/src/cli.ts index fb9fd6ccf626..2ddfce1b6ebe 100644 --- a/packages/create-cloudflare/src/cli.ts +++ b/packages/create-cloudflare/src/cli.ts @@ -34,7 +34,7 @@ import { updatePackageScripts, } from "./templates"; import { validateProjectDirectory } from "./validators"; -import { generateWorkersTypes, installWorkersTypes } from "./workers"; +import { addTypes } from "./workers"; import { updateWranglerConfig } from "./wrangler/config"; import type { C3Args, C3Context } from "types"; @@ -167,11 +167,8 @@ const configure = async (ctx: C3Context) => { addWranglerToGitIgnore(ctx); await updatePackageScripts(ctx); - if (ctx.template.workersTypes === "installed") { - await installWorkersTypes(ctx); - } else if (ctx.template.workersTypes === "generated") { - await generateWorkersTypes(ctx); - } + + await addTypes(ctx); await offerGit(ctx); await gitCommit(ctx); diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 1a544627db64..8dfe883939f0 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -17,14 +17,26 @@ import { } from "./wrangler/config"; import type { C3Context, PackageJson } from "types"; +export async function addTypes(ctx: C3Context) { + if (!usesTypescript(ctx) || ctx.template.workersTypes === "none") { + return; + } + const { npm } = detectPackageManager(); + + if (ctx.template.workersTypes === "installed") { + await installWorkersTypes(npm); + } else if (ctx.template.workersTypes === "generated") { + await generateWorkersTypes(ctx, npm); + } + const usesNodeCompat = await maybeInstallNodeTypes(ctx, npm); + await updateTsConfig(ctx, { usesNodeCompat }); +} + /** * Generate types using the `cf-typegen` script and update tsconfig */ -export async function generateWorkersTypes(ctx: C3Context) { - if (!usesTypescript(ctx)) { - return; - } +async function generateWorkersTypes(ctx: C3Context, npm: string) { const packageJsonPath = join(ctx.project.path, "package.json"); if (!existsSync(packageJsonPath)) { return; @@ -34,8 +46,6 @@ export async function generateWorkersTypes(ctx: C3Context) { return; } - const { npm } = detectPackageManager(); - const typesCmd = [npm, "run", "cf-typegen"]; await runCommand(typesCmd, { @@ -45,12 +55,10 @@ export async function generateWorkersTypes(ctx: C3Context) { doneText: `${brandColor("generated")} ${dim(`to \`${ctx.template.typesPath}\` via \`${typesCmd.join(" ")}\``)}`, }); - const usesNodeCompat = await maybeInstallNodeTypes(ctx, npm); - - delete packageManifest["devDependencies"]?.["@cloudflare/workers-types"]; - - writeFile(packageJsonPath, JSON.stringify(packageManifest, null, 2)); - await updateTsConfig(ctx, { usesNodeCompat }); + if (packageManifest["devDependencies"]?.["@cloudflare/workers-types"]) { + delete packageManifest["devDependencies"]?.["@cloudflare/workers-types"]; + writeFile(packageJsonPath, JSON.stringify(packageManifest, null, 2)); + } } const maybeInstallNodeTypes = async (ctx: C3Context, npm: string) => { @@ -169,17 +177,10 @@ export async function updateTsConfig( * Installs the latest version of the `@cloudflare/workers-types` package * and updates the .tsconfig file to use the latest entrypoint version. */ -export async function installWorkersTypes(ctx: C3Context) { - if (!usesTypescript(ctx)) { - return; - } - const { npm } = detectPackageManager(); - +async function installWorkersTypes(npm: string) { await installPackages(["@cloudflare/workers-types"], { dev: true, startText: "Installing @cloudflare/workers-types", doneText: `${brandColor("installed")} ${dim(`via ${npm}`)}`, }); - const usesNodeCompat = await maybeInstallNodeTypes(ctx, npm); - await updateTsConfig(ctx, { usesNodeCompat }); } From c5ca33b045fa4a7f26ab99ae10b5fe6966b29b11 Mon Sep 17 00:00:00 2001 From: emily-shen <69125074+emily-shen@users.noreply.github.com> Date: Thu, 8 May 2025 10:20:54 +0100 Subject: [PATCH 17/17] Update packages/create-cloudflare/src/workers.ts Co-authored-by: Victor Berchet --- packages/create-cloudflare/src/workers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 8dfe883939f0..b784d66b24a5 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -73,13 +73,13 @@ const maybeInstallNodeTypes = async (ctx: C3Context, npm: string) => { parsedConfig = TOML.parse(wranglerTomlStr); } - const compatibility_flags = Array.isArray(parsedConfig["compatibility_flags"]) + const compatibilityFlags = Array.isArray(parsedConfig["compatibility_flags"]) ? parsedConfig["compatibility_flags"] : []; if ( - compatibility_flags.includes("nodejs_compat") || - compatibility_flags.includes("nodejs_compat_v2") + compatibilityFlags.includes("nodejs_compat") || + compatibilityFlags.includes("nodejs_compat_v2") ) { await installPackages(["@types/node"], { dev: true,