diff --git a/.changeset/beige-results-flow.md b/.changeset/beige-results-flow.md new file mode 100644 index 000000000000..3425c18594ad --- /dev/null +++ b/.changeset/beige-results-flow.md @@ -0,0 +1,11 @@ +--- +"@cloudflare/vite-plugin": patch +--- + +Support Hyperdrive local connection strings from `.env` files + +You can now define your Hyperdrive local connection string in a `.env` file using the `CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_` variable. + +```sh +CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_PROD_DB="postgres://user:password@127.0.0.1:5432/testdb" +``` diff --git a/packages/vite-plugin-cloudflare/playground/bindings/.env b/packages/vite-plugin-cloudflare/playground/bindings/.env new file mode 100644 index 000000000000..435034d90afa --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/bindings/.env @@ -0,0 +1,2 @@ +# To test whether vite plugin could configure the hyperdrive binding properly +CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@example.com:3456/testdb" diff --git a/packages/vite-plugin-cloudflare/playground/bindings/__tests__/worker.spec.ts b/packages/vite-plugin-cloudflare/playground/bindings/__tests__/worker.spec.ts index dd54c1f5c9a4..b3bc399c571d 100644 --- a/packages/vite-plugin-cloudflare/playground/bindings/__tests__/worker.spec.ts +++ b/packages/vite-plugin-cloudflare/playground/bindings/__tests__/worker.spec.ts @@ -25,3 +25,8 @@ test("ratelimit support", async () => { const response = await getTextResponse("/rate-limit"); expect(response).toBe("Rate limit binding works: first: true, second: false"); }); + +test("hyperdrive support", async () => { + const response = await getTextResponse("/hyperdrive"); + expect(response).toBe("Hyperdrive binding works"); +}); diff --git a/packages/vite-plugin-cloudflare/playground/bindings/src/index.ts b/packages/vite-plugin-cloudflare/playground/bindings/src/index.ts index a4e5283ce1ea..4520a0cdebb5 100644 --- a/packages/vite-plugin-cloudflare/playground/bindings/src/index.ts +++ b/packages/vite-plugin-cloudflare/playground/bindings/src/index.ts @@ -61,6 +61,18 @@ export default { } ); } + case "/hyperdrive": { + if ( + typeof env.HYPERDRIVE.connect !== "function" || + typeof env.HYPERDRIVE.connectionString !== "string" + ) { + return new Response("Hyperdrive binding is not configured properly", { + status: 500, + }); + } + + return new Response("Hyperdrive binding works"); + } case "/hello-world": { const value = Math.floor(Date.now() * Math.random()).toString(36); await env.HELLO_WORLD.set(value); diff --git a/packages/vite-plugin-cloudflare/playground/bindings/worker-configuration.d.ts b/packages/vite-plugin-cloudflare/playground/bindings/worker-configuration.d.ts index 5ff75b054ab0..69686c53bb66 100644 --- a/packages/vite-plugin-cloudflare/playground/bindings/worker-configuration.d.ts +++ b/packages/vite-plugin-cloudflare/playground/bindings/worker-configuration.d.ts @@ -7,6 +7,7 @@ declare namespace Cloudflare { IMAGES: ImagesBinding; WAE: AnalyticsEngineDataset; RATE_LIMITER: RateLimit; + HYPERDRIVE: Hyperdrive; } } interface Env extends Cloudflare.Env {} diff --git a/packages/vite-plugin-cloudflare/playground/bindings/wrangler.jsonc b/packages/vite-plugin-cloudflare/playground/bindings/wrangler.jsonc index e1f3f91354f8..ec364f8ce90d 100644 --- a/packages/vite-plugin-cloudflare/playground/bindings/wrangler.jsonc +++ b/packages/vite-plugin-cloudflare/playground/bindings/wrangler.jsonc @@ -23,6 +23,12 @@ "binding": "WAE", }, ], + "hyperdrive": [ + { + "binding": "HYPERDRIVE", + "id": "test-hyperdrive-id", + }, + ], "unsafe": { "bindings": [ { diff --git a/packages/vite-plugin-cloudflare/src/plugin-config.ts b/packages/vite-plugin-cloudflare/src/plugin-config.ts index d57093164388..136c2200704f 100644 --- a/packages/vite-plugin-cloudflare/src/plugin-config.ts +++ b/packages/vite-plugin-cloudflare/src/plugin-config.ts @@ -112,6 +112,15 @@ export function resolvePluginConfig( experimental: pluginConfig.experimental ?? {}, }; const root = userConfig.root ? path.resolve(userConfig.root) : process.cwd(); + const prefixedEnv = vite.loadEnv(viteEnv.mode, root, [ + "CLOUDFLARE_", + // TODO: Remove deprecated WRANGLER prefix support in next major version + "WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_", + ]); + + // Merge the loaded env variables into process.env so that they are available to + // wrangler when it loads the worker configuration files. + Object.assign(process.env, prefixedEnv); if (viteEnv.isPreview) { return { @@ -122,12 +131,7 @@ export function resolvePluginConfig( } const configPaths = new Set(); - const { CLOUDFLARE_ENV: cloudflareEnv } = vite.loadEnv( - viteEnv.mode, - root, - /* prefixes */ "" - ); - + const cloudflareEnv = prefixedEnv.CLOUDFLARE_ENV; const entryWorkerConfigPath = getValidatedWranglerConfigPath( root, pluginConfig.configPath