Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wrangler] Changes for the next Miniflare version #3951

Merged
merged 11 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/clever-bears-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"wrangler": minor
---

feat: add support for breakpoint debugging to `wrangler dev`'s `--remote` and `--no-bundle` modes

Previously, breakpoint debugging using Wrangler's DevTools was only supported
in local mode, when using Wrangler's built-in bundler. This change extends that
to remote development, and `--no-bundle`.

When using `--remote` and `--no-bundle` together, uncaught errors will now be
source-mapped when logged too.
27 changes: 27 additions & 0 deletions .changeset/twelve-numbers-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
"wrangler": minor
---

feat: add support for Visual Studio Code's built-in breakpoint debugger

Wrangler now supports breakpoint debugging with Visual Studio Code's debugger.
Create a `.vscode/launch.json` file with the following contents...

```json
{
"configurations": [
{
"name": "Wrangler",
"type": "node",
"request": "attach",
"port": 9229,
"cwd": "/",
"resolveSourceMapLocations": null,
"attachExistingChildren": false,
"autoAttachChildProcesses": false
}
]
}
```

...then run `wrangler dev`, and launch the configuration.
9 changes: 3 additions & 6 deletions fixtures/pages-workerjs-directory/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,9 @@ describe("Pages _worker.js/ directory", () => {
await stop();
}

expect(existsSync(join(tmpDir, "./v3/d1/D1"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/d1/elsewhere"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/kv/KV"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/kv/other_kv"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/r2/R2"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/r2/other_r2"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/d1"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/kv"))).toBeTruthy();
expect(existsSync(join(tmpDir, "./v3/r2"))).toBeTruthy();
});

it("should bundle", async ({ expect }) => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"patchedDependencies": {
"ink@3.2.0": "patches/ink@3.2.0.patch",
"toucan-js@3.2.2": "patches/toucan-js@3.2.2.patch",
"@cloudflare/component-listbox@1.10.4": "patches/@cloudflare__component-listbox@1.10.4.patch"
"@cloudflare/component-listbox@1.10.6": "patches/@cloudflare__component-listbox@1.10.6.patch"
}
}
}
2 changes: 1 addition & 1 deletion packages/workers-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@cloudflare/component-code-block": "^4.1.2",
"@cloudflare/component-icon": "^11.5.1",
"@cloudflare/component-input": "^8.1.1",
"@cloudflare/component-listbox": "^1.10.4",
"@cloudflare/component-listbox": "^1.10.6",
"@cloudflare/component-loading": "^6.1.1",
"@cloudflare/component-textarea": "^4.1.1",
"@cloudflare/component-toast": "^5.1.0",
Expand Down
7 changes: 4 additions & 3 deletions packages/wrangler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,12 @@
"blake3-wasm": "^2.1.5",
"chokidar": "^3.5.3",
"esbuild": "0.17.19",
"miniflare": "3.20230904.0",
"miniflare": "3.20230918.0",
"nanoid": "^3.3.3",
"path-to-regexp": "^6.2.0",
"selfsigned": "^2.0.1",
"source-map": "^0.7.4",
"source-map": "0.6.1",
"source-map-support": "0.5.21",
"xxhash-wasm": "^1.0.1"
},
"devDependencies": {
Expand All @@ -122,7 +123,6 @@
"@cloudflare/workers-types": "^4.20230724.0",
"@iarna/toml": "^3.0.0",
"@microsoft/api-extractor": "^7.28.3",
"@types/better-sqlite3": "^7.6.0",
"@types/body-parser": "^1.19.2",
"@types/busboy": "^1.5.0",
"@types/command-exists": "^1.2.0",
Expand All @@ -136,6 +136,7 @@
"@types/react": "^17.0.37",
"@types/serve-static": "^1.13.10",
"@types/signal-exit": "^3.0.1",
"@types/source-map-support": "^0.5.7",
"@types/supports-color": "^8.1.1",
"@types/ws": "^8.5.3",
"@types/yargs": "^17.0.10",
Expand Down
14 changes: 12 additions & 2 deletions packages/wrangler/src/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7945,7 +7945,12 @@ export default{
const bigModule = Buffer.alloc(10_000_000);
randomFillSync(bigModule);
await printBundleSize({ name: "index.js", content: "" }, [
{ name: "index.js", content: bigModule, type: "buffer" },
{
name: "index.js",
filePath: undefined,
content: bigModule,
type: "buffer",
},
]);

expect(std).toMatchInlineSnapshot(`
Expand All @@ -7968,7 +7973,12 @@ export default{
const bigModule = Buffer.alloc(10_000_000);
randomFillSync(bigModule);
await printBundleSize({ name: "index.js", content: "" }, [
{ name: "index.js", content: bigModule, type: "buffer" },
{
name: "index.js",
filePath: undefined,
content: bigModule,
type: "buffer",
},
]);

expect(std).toMatchInlineSnapshot(`
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/__tests__/jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jest.mock("child_process", () => {
return {
__esModule: true,
...jest.requireActual("child_process"),
default: jest.requireActual("child_process"),
spawnSync: jest.fn().mockImplementation((binary, ...args) => {
if (binary === "cloudflared") return { error: true };
return jest.requireActual("child_process").spawnSync(binary, ...args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export async function createUploadWorkerBundleContents(
function createWorkerBundleFormData(workerBundle: BundleResult): FormData {
const mainModule = {
name: path.basename(workerBundle.resolvedEntryPointPath),
filePath: workerBundle.resolvedEntryPointPath,
content: readFileSync(workerBundle.resolvedEntryPointPath, {
encoding: "utf-8",
}),
Expand Down
42 changes: 15 additions & 27 deletions packages/wrangler/src/d1/execute.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import assert from "node:assert";
import { existsSync } from "node:fs";
import { mkdir } from "node:fs/promises";
import path from "node:path";
import chalk from "chalk";
import { Static, Text } from "ink";
import Table from "ink-table";
import { Miniflare } from "miniflare";
import React from "react";
import { fetchResult } from "../cfetch";
import { readConfig } from "../config";
Expand All @@ -29,7 +28,7 @@ import type {
StrictYargsOptionsToInterface,
} from "../yargs-types";
import type { Database } from "./types";
import type { D1SuccessResponse } from "miniflare";
import type { D1Result } from "@cloudflare/workers-types/experimental";

export type QueryResult = {
results: Record<string, string | number | boolean>[];
Expand Down Expand Up @@ -204,10 +203,8 @@ export async function executeSql({
? await executeLocally({
config,
name,
shouldPrompt,
queries,
persistTo,
json,
})
: await executeRemotely({
config,
Expand All @@ -224,17 +221,13 @@ export async function executeSql({
async function executeLocally({
config,
name,
shouldPrompt,
queries,
persistTo,
json,
}: {
config: Config;
name: string;
shouldPrompt: boolean | undefined;
queries: string[];
persistTo: string | undefined;
json: boolean | undefined;
}) {
const localDB = getDatabaseInfoFromConfig(config, name);
if (!localDB) {
Expand All @@ -245,30 +238,25 @@ async function executeLocally({

const id = localDB.previewDatabaseUuid ?? localDB.uuid;
const persistencePath = getLocalPersistencePath(persistTo, config.configPath);
const dbDir = path.join(persistencePath, "v3", "d1", id);
const dbPath = path.join(dbDir, `db.sqlite`);

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { D1Gateway, NoOpLog, createFileStorage } = require("miniflare");
const storage = createFileStorage(dbDir);
const d1Persist = path.join(persistencePath, "v3", "d1");

if (!existsSync(dbDir)) {
const ok =
json ||
!shouldPrompt ||
(await confirm(`About to create ${readableRelative(dbPath)}, ok?`));
if (!ok) return null;
await mkdir(dbDir, { recursive: true });
}
logger.log(`🌀 Loading ${id} from ${readableRelative(d1Persist)}`);

logger.log(`🌀 Loading DB at ${readableRelative(dbPath)}`);
const mf = new Miniflare({
modules: true,
script: "",
d1Persist,
d1Databases: { DATABASE: id },
});
const db = await mf.getD1Database("DATABASE");

const db = new D1Gateway(new NoOpLog(), storage);
let results: D1SuccessResponse | D1SuccessResponse[];
let results: D1Result<Record<string, string | number | boolean>>[];
try {
results = db.query(queries.map((query) => ({ sql: query })));
results = await db.batch(queries.map((query) => db.prepare(query)));
} catch (e: unknown) {
throw (e as { cause?: unknown })?.cause ?? e;
} finally {
await mf.dispose();
}
assert(Array.isArray(results));
return results.map<QueryResult>((result) => ({
Expand Down
3 changes: 3 additions & 0 deletions packages/wrangler/src/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
// We want to know if the build is for development or publishing
// This could potentially cause issues as we no longer have identical behaviour between dev and deploy?
targetConsumer: "deploy",
local: false,
}
);

Expand Down Expand Up @@ -558,6 +559,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
if (assets.manifest) {
modules.push({
name: "__STATIC_CONTENT_MANIFEST",
filePath: undefined,
content: JSON.stringify(assets.manifest),
type: "text",
});
Expand All @@ -571,6 +573,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
name: scriptName,
main: {
name: path.basename(resolvedEntryPointPath),
filePath: resolvedEntryPointPath,
content: content,
type: bundleType,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { Metafile } from "esbuild";
const ONE_KIB_BYTES = 1024;
const ALLOWED_INITIAL_MAX = ONE_KIB_BYTES * 1024; // Current max is 1 MiB

async function getSize(modules: CfModule[]) {
async function getSize(modules: Pick<CfModule, "content">[]) {
const gzipSize = gzipSync(
await new Blob(modules.map((file) => file.content)).arrayBuffer()
).byteLength;
Expand Down
21 changes: 11 additions & 10 deletions packages/wrangler/src/deployment-bundle/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export async function bundleWorker(
disableModuleCollection?: boolean;
isOutfile?: boolean;
forPages?: boolean;
local: boolean;
}
): Promise<BundleResult> {
const {
Expand Down Expand Up @@ -175,12 +176,16 @@ export async function bundleWorker(
isOutfile,
forPages,
additionalModules = [],
local,
} = options;

// We create a temporary directory for any one-off files we
// need to create. This is separate from the main build
// directory (`destination`).
const tmpDir = await tmp.dir({ unsafeCleanup: true });
const unsafeTmpDir = await tmp.dir({ unsafeCleanup: true });
// Make sure we resolve all files relative to the actual temporary directory,
// without symlinks, otherwise `esbuild` will generate invalid source maps.
const tmpDirPath = fs.realpathSync(unsafeTmpDir.path);

const entryDirectory = path.dirname(entry.file);
let moduleCollector = createModuleCollector({
Expand Down Expand Up @@ -215,10 +220,10 @@ export async function bundleWorker(
// we need to extract that file to an accessible place before injecting
// it in, hence this code here.

const checkedFetchFileToInject = path.join(tmpDir.path, "checked-fetch.js");
const checkedFetchFileToInject = path.join(tmpDirPath, "checked-fetch.js");

if (checkFetch && !fs.existsSync(checkedFetchFileToInject)) {
fs.mkdirSync(tmpDir.path, {
fs.mkdirSync(tmpDirPath, {
recursive: true,
});
fs.writeFileSync(
Expand Down Expand Up @@ -253,7 +258,7 @@ export async function bundleWorker(
{
name: "miniflare3-json-error",
path: "templates/middleware/middleware-miniflare3-json-error.ts",
active: targetConsumer === "dev",
active: targetConsumer === "dev" && local,
},
{
name: "serve-static-assets",
Expand Down Expand Up @@ -320,7 +325,7 @@ export async function bundleWorker(
) {
inputEntry = await applyMiddlewareLoaderFacade(
entry,
tmpDir.path,
tmpDirPath,
activeMiddleware,
doBindings
);
Expand Down Expand Up @@ -450,7 +455,7 @@ export async function bundleWorker(
stop,
sourceMapPath,
sourceMapMetadata: {
tmpDir: tmpDir.path,
tmpDir: tmpDirPath,
entryDirectory: entry.directory,
},
moduleCollector,
Expand Down Expand Up @@ -482,10 +487,6 @@ async function applyMiddlewareLoaderFacade(
// and then we load the middleware - this insertion and loading is
// different for each format.

// Make sure we resolve all files relative to the actual temporary directory,
// otherwise we'll have issues with source maps
tmpDirPath = fs.realpathSync(tmpDirPath);

// We need to import each of the middlewares, so we need to generate a
// random, unique identifier that we can use for the import.
// Middlewares are required to be default exports so we can import to any name.
Expand Down
9 changes: 9 additions & 0 deletions packages/wrangler/src/deployment-bundle/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ export interface CfModule {
* './src/index.js'
*/
name: string;
/**
* The absolute path of the module on disk, or `undefined` if this is a
* virtual module. Used as the source URL for this module, so source maps are
* correctly resolved.
*
* @example
* '/path/to/src/index.js'
*/
filePath: string | undefined;
/**
* The module content, usually JavaScript or WASM code.
*
Expand Down
Loading