From 46ff82901ffbcff8a9f33ca47c931d902bfb350d Mon Sep 17 00:00:00 2001 From: Sunil Pai Date: Mon, 4 Apr 2022 01:34:29 -0500 Subject: [PATCH] fix: resolve raw file bindings correctly in `wrangler dev` local mode For `wasm_modules`/`text_blobs`/`data_blobs` in local mode, we need to rewrite the paths as absolute so that they're resolved correctly by miniflare. This also expands some coverage for local mode `wrangler dev`. Fixes https://github.com/cloudflare/wrangler2/issues/740 Fixes https://github.com/cloudflare/wrangler2/issues/416 --- .changeset/flat-ads-flash.md | 10 +++ examples/local-mode-tests/package.json | 4 ++ examples/local-mode-tests/some-data.bin | 1 + examples/local-mode-tests/some-text.txt | 1 + examples/local-mode-tests/src/index.ts | 5 -- examples/local-mode-tests/src/module.ts | 23 ++++++ examples/local-mode-tests/src/sw.ts | 31 ++++++++ .../wrangler.module.toml} | 6 +- .../local-mode-tests/src/wrangler.sw.toml | 13 ++++ .../tests/{index.test.ts => module.test.ts} | 34 +++++++-- examples/local-mode-tests/tests/sw.test.ts | 72 +++++++++++++++++++ examples/local-mode-tests/tsconfig.json | 1 + package-lock.json | 10 ++- packages/wrangler/src/dev/local.tsx | 34 +++++++-- 14 files changed, 228 insertions(+), 17 deletions(-) create mode 100644 .changeset/flat-ads-flash.md create mode 100644 examples/local-mode-tests/some-data.bin create mode 100644 examples/local-mode-tests/some-text.txt delete mode 100644 examples/local-mode-tests/src/index.ts create mode 100644 examples/local-mode-tests/src/module.ts create mode 100644 examples/local-mode-tests/src/sw.ts rename examples/local-mode-tests/{wrangler.toml => src/wrangler.module.toml} (51%) create mode 100644 examples/local-mode-tests/src/wrangler.sw.toml rename examples/local-mode-tests/tests/{index.test.ts => module.test.ts} (61%) create mode 100644 examples/local-mode-tests/tests/sw.test.ts diff --git a/.changeset/flat-ads-flash.md b/.changeset/flat-ads-flash.md new file mode 100644 index 000000000000..956b52d97325 --- /dev/null +++ b/.changeset/flat-ads-flash.md @@ -0,0 +1,10 @@ +--- +"wrangler": patch +--- + +fix: resolve raw file bindings correctly in `wrangler dev` local mode + +For `wasm_modules`/`text_blobs`/`data_blobs` in local mode, we need to rewrite the paths as absolute so that they're resolved correctly by miniflare. This also expands some coverage for local mode `wrangler dev`. + +Fixes https://github.com/cloudflare/wrangler2/issues/740 +Fixes https://github.com/cloudflare/wrangler2/issues/416 diff --git a/examples/local-mode-tests/package.json b/examples/local-mode-tests/package.json index ee0116fa10a6..b116e22e097d 100644 --- a/examples/local-mode-tests/package.json +++ b/examples/local-mode-tests/package.json @@ -5,8 +5,12 @@ "description": "", "main": "index.js", "scripts": { + "check:type": "tsc", "test": "npx jest --forceExit" }, + "devDependencies": { + "@cloudflare/workers-types": "^3.2.0" + }, "keywords": [], "author": "", "license": "ISC", diff --git a/examples/local-mode-tests/some-data.bin b/examples/local-mode-tests/some-data.bin new file mode 100644 index 000000000000..3ef856efbbf0 --- /dev/null +++ b/examples/local-mode-tests/some-data.bin @@ -0,0 +1 @@ +Here be some data \ No newline at end of file diff --git a/examples/local-mode-tests/some-text.txt b/examples/local-mode-tests/some-text.txt new file mode 100644 index 000000000000..4aa71e22293e --- /dev/null +++ b/examples/local-mode-tests/some-text.txt @@ -0,0 +1 @@ +Here be some text \ No newline at end of file diff --git a/examples/local-mode-tests/src/index.ts b/examples/local-mode-tests/src/index.ts deleted file mode 100644 index 1f6e34ed9cc6..000000000000 --- a/examples/local-mode-tests/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default { - async fetch(_request: Request): Promise { - return new Response("Hello World!"); - }, -}; diff --git a/examples/local-mode-tests/src/module.ts b/examples/local-mode-tests/src/module.ts new file mode 100644 index 000000000000..65e096ee85d6 --- /dev/null +++ b/examples/local-mode-tests/src/module.ts @@ -0,0 +1,23 @@ +// @ts-expect-error non standard module +import data from "../some-data.bin"; +// @ts-expect-error non standard module +import text from "../some-text.txt"; + +export default { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async fetch(_request: Request, env: any): Promise { + return new Response( + JSON.stringify( + { + VAR1: env.VAR1, + VAR2: env.VAR2, + VAR3: env.VAR3, + text, + data: new TextDecoder().decode(data), + }, + null, + 2 + ) + ); + }, +}; diff --git a/examples/local-mode-tests/src/sw.ts b/examples/local-mode-tests/src/sw.ts new file mode 100644 index 000000000000..2b30d4dc4354 --- /dev/null +++ b/examples/local-mode-tests/src/sw.ts @@ -0,0 +1,31 @@ +// @ts-expect-error non standard module +import data from "../some-data.bin"; +// @ts-expect-error non standard module +import text from "../some-text.txt"; + +addEventListener("fetch", (event: FetchEvent) => { + event.respondWith(handleRequest(event.request)); +}); + +async function handleRequest(_req: Request): Promise { + return new Response( + JSON.stringify( + { + // @ts-expect-error binding + VAR1, + // @ts-expect-error binding + VAR2, + // @ts-expect-error binding + VAR3, + text, + data: new TextDecoder().decode(data), + // @ts-expect-error binding + TEXT, + // @ts-expect-error binding + DATA: new TextDecoder().decode(DATA), + }, + null, + 2 + ) + ); +} diff --git a/examples/local-mode-tests/wrangler.toml b/examples/local-mode-tests/src/wrangler.module.toml similarity index 51% rename from examples/local-mode-tests/wrangler.toml rename to examples/local-mode-tests/src/wrangler.module.toml index 292af6fb61cd..0defd8a46598 100644 --- a/examples/local-mode-tests/wrangler.toml +++ b/examples/local-mode-tests/src/wrangler.module.toml @@ -1,3 +1,7 @@ name = "local-mode-tests" -main = "src/index.ts" compatibility_date = "2022-03-27" + +[vars] +VAR1 = "value1" +VAR2 = 123 +VAR3 = {abc = "def"} diff --git a/examples/local-mode-tests/src/wrangler.sw.toml b/examples/local-mode-tests/src/wrangler.sw.toml new file mode 100644 index 000000000000..4dc66bcd369a --- /dev/null +++ b/examples/local-mode-tests/src/wrangler.sw.toml @@ -0,0 +1,13 @@ +name = "local-mode-tests" +compatibility_date = "2022-03-27" + +[vars] +VAR1 = "value1" +VAR2 = 123 +VAR3 = {abc = "def"} + +[text_blobs] +TEXT = "../some-text.txt" + +[data_blobs] +DATA = "../some-data.bin" diff --git a/examples/local-mode-tests/tests/index.test.ts b/examples/local-mode-tests/tests/module.test.ts similarity index 61% rename from examples/local-mode-tests/tests/index.test.ts rename to examples/local-mode-tests/tests/module.test.ts index 178aa5a97a75..8b83b2cd30f8 100644 --- a/examples/local-mode-tests/tests/index.test.ts +++ b/examples/local-mode-tests/tests/module.test.ts @@ -21,9 +21,23 @@ const isWindows = process.platform === "win32"; let wranglerProcess: ChildProcess; beforeAll(async () => { - wranglerProcess = spawn("npx", ["wrangler", "dev", "--local"], { - shell: isWindows, - }); + wranglerProcess = spawn( + "npx", + [ + "wrangler", + "dev", + "src/module.ts", + "--local", + "--config", + "src/wrangler.module.toml", + "--port", + "9001", + ], + { + shell: isWindows, + stdio: "inherit", + } + ); }); afterAll(async () => { @@ -40,7 +54,17 @@ afterAll(async () => { }); it("renders", async () => { - const response = await waitUntilReady("http://localhost:8787/"); + const response = await waitUntilReady("http://localhost:9001/"); const text = await response.text(); - expect(text).toContain("Hello World!"); + expect(text).toMatchInlineSnapshot(` + "{ + \\"VAR1\\": \\"value1\\", + \\"VAR2\\": 123, + \\"VAR3\\": { + \\"abc\\": \\"def\\" + }, + \\"text\\": \\"Here be some text\\", + \\"data\\": \\"Here be some data\\" + }" + `); }); diff --git a/examples/local-mode-tests/tests/sw.test.ts b/examples/local-mode-tests/tests/sw.test.ts new file mode 100644 index 000000000000..7c50d56cc398 --- /dev/null +++ b/examples/local-mode-tests/tests/sw.test.ts @@ -0,0 +1,72 @@ +import { spawn } from "child_process"; +import { fetch } from "undici"; +import type { ChildProcess } from "child_process"; +import type { Response } from "undici"; + +const waitUntilReady = async (url: string): Promise => { + let response: Response | undefined = undefined; + + while (response === undefined) { + await new Promise((resolvePromise) => setTimeout(resolvePromise, 100)); + + try { + response = await fetch(url); + } catch {} + } + + return response as Response; +}; +const isWindows = process.platform === "win32"; + +let wranglerProcess: ChildProcess; + +beforeAll(async () => { + wranglerProcess = spawn( + "npx", + [ + "wrangler", + "dev", + "src/sw.ts", + "--local", + "--config", + "src/wrangler.sw.toml", + "--port", + "9002", + ], + { + shell: isWindows, + stdio: "inherit", + } + ); +}); + +afterAll(async () => { + await new Promise((resolve, reject) => { + wranglerProcess.once("exit", (code) => { + if (!code) { + resolve(code); + } else { + reject(code); + } + }); + wranglerProcess.kill(); + }); +}); + +it("renders", async () => { + const response = await waitUntilReady("http://localhost:9002/"); + const text = await response.text(); + expect(text).toMatchInlineSnapshot(` + "{ + \\"VAR1\\": \\"value1\\", + \\"VAR2\\": 123, + \\"VAR3\\": { + \\"abc\\": \\"def\\" + }, + \\"text\\": \\"Here be some text\\", + \\"data\\": \\"Here be some data\\", + \\"TEXT\\": \\"Here be some text\\", + \\"DATA\\": \\"Here be some data\\" + }" + `); +}); diff --git a/examples/local-mode-tests/tsconfig.json b/examples/local-mode-tests/tsconfig.json index af50e9574fc1..f0be002be4b5 100644 --- a/examples/local-mode-tests/tsconfig.json +++ b/examples/local-mode-tests/tsconfig.json @@ -9,6 +9,7 @@ "target": "esnext", "strict": true, "noEmit": true, + "types": ["@cloudflare/workers-types", "jest"], "skipLibCheck": true } } diff --git a/package-lock.json b/package-lock.json index 5cf9c98a7d17..7adf7eb6862d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,10 @@ }, "examples/local-mode-tests": { "version": "1.0.0", - "license": "ISC" + "license": "ISC", + "devDependencies": { + "@cloudflare/workers-types": "^3.2.0" + } }, "examples/pages-functions-app": { "version": "0.0.0", @@ -25779,7 +25782,10 @@ } }, "local-mode-tests": { - "version": "file:examples/local-mode-tests" + "version": "file:examples/local-mode-tests", + "requires": { + "@cloudflare/workers-types": "^3.2.0" + } }, "localforage": { "version": "1.10.0", diff --git a/packages/wrangler/src/dev/local.tsx b/packages/wrangler/src/dev/local.tsx index 32f0bb7296e2..c0f4a5cbb789 100644 --- a/packages/wrangler/src/dev/local.tsx +++ b/packages/wrangler/src/dev/local.tsx @@ -83,9 +83,35 @@ function useLocalWorker({ const scriptPath = realpathSync(bundle.path); - const wasmBindings = { ...bindings.wasm_modules }; - const textBlobBindings = { ...bindings.text_blobs }; - const dataBlobBindings = { ...bindings.data_blobs }; + // the wasm_modules/text_blobs/data_blobs bindings are + // relative to process.cwd(), but the actual worker bundle + // is in the temp output directory; so we rewrite the paths to be absolute, + // letting miniflare resolve them correctly + + // wasm + const wasmBindings: Record = {}; + for (const [name, filePath] of Object.entries( + bindings.wasm_modules || {} + )) { + wasmBindings[name] = path.join(process.cwd(), filePath); + } + + // text + const textBlobBindings: Record = {}; + for (const [name, filePath] of Object.entries( + bindings.text_blobs || {} + )) { + textBlobBindings[name] = path.join(process.cwd(), filePath); + } + + // data + const dataBlobBindings: Record = {}; + for (const [name, filePath] of Object.entries( + bindings.data_blobs || {} + )) { + dataBlobBindings[name] = path.join(process.cwd(), filePath); + } + if (format === "service-worker") { for (const { type, name } of bundle.modules) { if (type === "compiled-wasm") { @@ -187,7 +213,7 @@ function useLocalWorker({ }); local.current.stdout?.on("data", (data: Buffer) => { - console.log(`${data.toString()}`); + process.stdout.write(data); }); local.current.stderr?.on("data", (data: Buffer) => {