From 5b85dc949b1f7c8d5e8d083b37dd84d38c4ea978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20F=C3=B6ldi?= Date: Wed, 6 Mar 2024 11:30:16 +0100 Subject: [PATCH] Add support for new bindings to wrangler types (#5089) * Add support for new bindings to `wrangler types` * Actually Workers AI is also Fetcher * Add test * Add changeset * Format changelog * Use `unknown` for AI binding * Make bindings config type validation stricter * Fix typecheck failure as discussed --- .changeset/curvy-ghosts-destroy.md | 46 +++++++++++++++++++ .../src/__tests__/type-generation.test.ts | 26 ++++++++++- packages/wrangler/src/config/environment.ts | 2 +- packages/wrangler/src/type-generation.ts | 41 +++++++++++++++++ 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 .changeset/curvy-ghosts-destroy.md diff --git a/.changeset/curvy-ghosts-destroy.md b/.changeset/curvy-ghosts-destroy.md new file mode 100644 index 000000000000..4bc5869a3b76 --- /dev/null +++ b/.changeset/curvy-ghosts-destroy.md @@ -0,0 +1,46 @@ +--- +"wrangler": patch +--- + +fix: include all currently existing bindings in `wrangler types` + +Add support for Email Send, Vectorize, Hyperdrive, mTLS, Browser Rendering and Workers AI bindings in `wrangler types` + +For example, from the following `wrangler.toml` setup: + +```toml +[browser] +binding = "BROWSER" + +[ai] +binding = "AI" + +[[send_email]] +name = "SEND_EMAIL" + +[[vectorize]] +binding = "VECTORIZE" +index_name = "VECTORIZE_NAME" + +[[hyperdrive]] +binding = "HYPERDRIVE" +id = "HYPERDRIVE_ID" + +[[mtls_certificates]] +binding = "MTLS" +certificate_id = "MTLS_CERTIFICATE_ID" +``` + +Previously, nothing would have been included in the generated Environment. +Now, the following will be generated: + +```ts +interface Env { + SEND_EMAIL: SendEmail; + VECTORIZE: VectorizeIndex; + HYPERDRIVE: Hyperdrive; + MTLS: Fetcher; + BROWSER: Fetcher; + AI: Fetcher; +} +``` diff --git a/packages/wrangler/src/__tests__/type-generation.test.ts b/packages/wrangler/src/__tests__/type-generation.test.ts index c29ff1ee8cd7..82e53c35f5f5 100644 --- a/packages/wrangler/src/__tests__/type-generation.test.ts +++ b/packages/wrangler/src/__tests__/type-generation.test.ts @@ -4,9 +4,13 @@ import { dedent } from "../utils/dedent"; import { mockConsoleMethods } from "./helpers/mock-console"; import { runInTempDir } from "./helpers/run-in-tmp"; import { runWrangler } from "./helpers/run-wrangler"; -import type { Config } from "../config"; +import type { EnvironmentNonInheritable } from "../config/environment"; -const bindingsConfigMock: Partial = { +const bindingsConfigMock: Omit< + EnvironmentNonInheritable, + "define" | "tail_consumers" | "constellation" | "cloudchamber" +> & + Record = { kv_namespaces: [{ binding: "TEST_KV_NAMESPACE", id: "1234" }], vars: { SOMETHING: "asdasdfasdf", @@ -62,6 +66,18 @@ const bindingsConfigMock: Partial = { dispatch_namespaces: [ { binding: "NAMESPACE_BINDING", namespace: "NAMESPACE_ID" }, ], + send_email: [{ name: "SEND_EMAIL_BINDING" }], + vectorize: [{ binding: "VECTORIZE_BINDING", index_name: "VECTORIZE_NAME" }], + hyperdrive: [{ binding: "HYPERDRIVE_BINDING", id: "HYPERDRIVE_ID" }], + mtls_certificates: [ + { binding: "MTLS_BINDING", certificate_id: "MTLS_CERTIFICATE_ID" }, + ], + browser: { + binding: "BROWSER_BINDING", + }, + ai: { + binding: "AI_BINDING", + }, logfwdr: { bindings: [{ name: "LOGFWDR_BINDING", destination: "LOGFWDR_DESTINATION" }], }, @@ -201,6 +217,12 @@ describe("generateTypes()", () => { SOME_TEXT_BLOB2: string; testing_unsafe: any; TEST_QUEUE_BINDING: Queue; + SEND_EMAIL_BINDING: SendEmail; + VECTORIZE_BINDING: VectorizeIndex; + HYPERDRIVE_BINDING: Hyperdrive; + MTLS_BINDING: Fetcher; + BROWSER_BINDING: Fetcher; + AI_BINDING: unknown; } declare module \\"*.txt\\" { const value: string; diff --git a/packages/wrangler/src/config/environment.ts b/packages/wrangler/src/config/environment.ts index 613277e19a98..dbf977e80a40 100644 --- a/packages/wrangler/src/config/environment.ts +++ b/packages/wrangler/src/config/environment.ts @@ -328,7 +328,7 @@ export type DurableObjectBindings = { * If any of these fields are defined at the top-level then they should also be specifically defined * for each named environment. */ -interface EnvironmentNonInheritable { +export interface EnvironmentNonInheritable { /** * A map of values to substitute when deploying your worker. * diff --git a/packages/wrangler/src/type-generation.ts b/packages/wrangler/src/type-generation.ts index 54b85228add7..7328605ff9b4 100644 --- a/packages/wrangler/src/type-generation.ts +++ b/packages/wrangler/src/type-generation.ts @@ -95,6 +95,12 @@ export async function typesHandler( rules: config.rules, queues: config.queues, constellation: config.constellation, + send_email: config.send_email, + vectorize: config.vectorize, + hyperdrive: config.hyperdrive, + mtls_certificates: config.mtls_certificates, + browser: config.browser, + ai: config.ai, secrets, }; @@ -240,6 +246,41 @@ async function generateTypes( } } + if (configToDTS.send_email) { + for (const sendEmail of configToDTS.send_email) { + envTypeStructure.push(`${sendEmail.name}: SendEmail;`); + } + } + + if (configToDTS.vectorize) { + for (const vectorize of configToDTS.vectorize) { + envTypeStructure.push(`${vectorize.binding}: VectorizeIndex;`); + } + } + + if (configToDTS.hyperdrive) { + for (const hyperdrive of configToDTS.hyperdrive) { + envTypeStructure.push(`${hyperdrive.binding}: Hyperdrive;`); + } + } + + if (configToDTS.mtls_certificates) { + for (const mtlsCertificate of configToDTS.mtls_certificates) { + envTypeStructure.push(`${mtlsCertificate.binding}: Fetcher;`); + } + } + + if (configToDTS.browser) { + // The BrowserWorker type in @cloudflare/puppeteer is of type + // { fetch: typeof fetch }, but workers-types doesn't include it + // and Fetcher is valid for the purposes of handing it to puppeteer + envTypeStructure.push(`${configToDTS.browser.binding}: Fetcher;`); + } + + if (configToDTS.ai) { + envTypeStructure.push(`${configToDTS.ai.binding}: unknown;`); + } + const modulesTypeStructure: string[] = []; if (configToDTS.rules) { const moduleTypeMap = {