Skip to content

Commit e8580ed

Browse files
emily-shenCarmenPopoviciu
authored andcommitted
stop gpp crashing with internal DOs
1 parent 1ad6c6b commit e8580ed

File tree

5 files changed

+117
-15
lines changed

5 files changed

+117
-15
lines changed

fixtures/get-platform-proxy/tests/get-platform-proxy.env.test.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import path from "path";
22
import { D1Database, R2Bucket } from "@cloudflare/workers-types";
3-
import { beforeEach, describe, expect, it, vi } from "vitest";
3+
import {
4+
afterEach,
5+
beforeEach,
6+
describe,
7+
expect,
8+
it,
9+
MockInstance,
10+
vi,
11+
} from "vitest";
412
import { getPlatformProxy } from "./shared";
513
import type { Hyperdrive, KVNamespace } from "@cloudflare/workers-types";
614
import type { Unstable_DevWorker } from "wrangler";
@@ -197,6 +205,55 @@ describe("getPlatformProxy - env", () => {
197205
}
198206
});
199207

208+
describe("DO warnings", () => {
209+
let warn = {} as MockInstance<typeof console.warn>;
210+
beforeEach(() => {
211+
warn = vi.spyOn(console, "warn").mockImplementation(() => {});
212+
});
213+
afterEach(() => {
214+
warn.mockRestore();
215+
});
216+
217+
it("warns about internal DOs and doesn't crash", async () => {
218+
await getPlatformProxy<Env>({
219+
configPath: path.join(__dirname, "..", "wrangler_internal_do.jsonc"),
220+
});
221+
expect(warn).toMatchInlineSnapshot(`
222+
[MockFunction warn] {
223+
"calls": [
224+
[
225+
"▲ [WARNING]  You have defined bindings to the following internal Durable Objects:
226+
227+
- {"class_name":"MyDurableObject","name":"MY_DURABLE_OBJECT"}
228+
These will not work in local development, but they should work in production.
229+
230+
If you want to develop these locally, you can define your DO "externally" in another worker.
231+
To do this, create another Worker and Wrangler config file. Export your DO from there.
232+
Then, set the \`script_name\` field in your original DO binding to equal the \`name\` field from your new external DO config.
233+
234+
You will be able to develop this locally by running:
235+
npx wrangler dev -c path/to/original/wrangler.json -c path/to/external-do/wrangler.json
236+
237+
",
238+
],
239+
],
240+
"results": [
241+
{
242+
"type": "return",
243+
"value": undefined,
244+
},
245+
],
246+
}
247+
`);
248+
});
249+
it("doesn't warn about external DOs and doesn't crash", async () => {
250+
await getPlatformProxy<Env>({
251+
configPath: path.join(__dirname, "..", "wrangler_external_do.jsonc"),
252+
});
253+
expect(warn).not.toHaveBeenCalled();
254+
});
255+
});
256+
200257
describe("with a target environment", () => {
201258
it("should provide bindings targeting a specified environment and also inherit top-level ones", async () => {
202259
const { env, dispose } = await getPlatformProxy<Env>({
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "external_do",
3+
"main": "src/index.ts",
4+
// external durable object - has script name
5+
"durable_objects": {
6+
"bindings": [
7+
{
8+
"class_name": "MyDurableObject",
9+
"name": "MY_DURABLE_OBJECT",
10+
"script_name": "internal-do",
11+
},
12+
],
13+
},
14+
"migrations": [
15+
{
16+
"new_sqlite_classes": ["MyDurableObject"],
17+
"tag": "v1",
18+
},
19+
],
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "internal_do",
3+
"main": "src/index.ts",
4+
// internal durable object
5+
"durable_objects": {
6+
"bindings": [
7+
{
8+
"class_name": "MyDurableObject",
9+
"name": "MY_DURABLE_OBJECT",
10+
},
11+
],
12+
},
13+
"migrations": [
14+
{
15+
"new_sqlite_classes": ["MyDurableObject"],
16+
"tag": "v1",
17+
},
18+
],
19+
}

packages/wrangler/src/api/integrations/platform/index.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { kCurrentWorker, Miniflare } from "miniflare";
22
import { getAssetsOptions } from "../../../assets";
3-
import { formatConfigSnippet, readConfig } from "../../../config";
3+
import { readConfig } from "../../../config";
4+
import { partitionDurableObjectBindings } from "../../../deployment-bundle/entry";
45
import { DEFAULT_MODULE_RULES } from "../../../deployment-bundle/rules";
56
import { getBindings } from "../../../dev";
67
import { getBoundRegisteredWorkers } from "../../../dev-registry";
@@ -131,24 +132,30 @@ export async function getPlatformProxy<
131132
};
132133
}
133134

135+
// this is only used by getPlatformProxy
134136
async function getMiniflareOptionsFromConfig(
135137
rawConfig: Config,
136138
env: string | undefined,
137139
options: GetPlatformProxyOptions
138140
): Promise<Partial<MiniflareOptions>> {
139141
const bindings = getBindings(rawConfig, env, true, {});
140142

141-
if (bindings.durable_objects) {
142-
logger.warn(dedent`
143-
You have defined an internal Durable Object (ie the binding does not have a script_name field).
144-
You will not be able to develop it locally, but it should work in production.
145-
146-
Alternatively, you can define your DO "externally" in another worker.
147-
To do this, create another Worker + Wrangler config file. Export your DO from there.
148-
Then, set the script_name field in your original DO binding to equal the name field from your new external DO config.
149-
You will be able to develop this locally by running:
150-
npx wrangler dev -c path/to/original/wrangler.toml -c path/to/external-do/wrangler.toml
151-
`);
143+
if (rawConfig["durable_objects"]) {
144+
const { localBindings } = partitionDurableObjectBindings(rawConfig);
145+
if (localBindings.length > 0) {
146+
logger.warn(dedent`
147+
You have defined bindings to the following internal Durable Objects:
148+
${localBindings.map((b) => `- ${JSON.stringify(b)}`).join("\n")}
149+
These will not work in local development, but they should work in production.
150+
151+
If you want to develop these locally, you can define your DO "externally" in another worker.
152+
To do this, create another Worker and Wrangler config file. Export your DO from there.
153+
Then, set the \`script_name\` field in your original DO binding to equal the \`name\` field from your new external DO config.
154+
155+
You will be able to develop this locally by running:
156+
npx wrangler dev -c path/to/original/wrangler.json -c path/to/external-do/wrangler.json
157+
`);
158+
}
152159
}
153160
const workerDefinitions = await getBoundRegisteredWorkers({
154161
name: rawConfig.name,

packages/wrangler/src/deployment-bundle/entry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import path from "node:path";
22
import dedent from "ts-dedent";
33
import { configFileName, formatConfigSnippet } from "../config";
44
import { UserError } from "../errors";
5-
import { logger } from "../logger";
65
import { sniffUserAgent } from "../package-manager";
76
import guessWorkerFormat from "./guess-worker-format";
87
import {
@@ -161,7 +160,7 @@ export async function getEntry(
161160
* Groups the durable object bindings into two lists:
162161
* those that are defined locally and those that refer to a durable object defined in another script.
163162
*/
164-
function partitionDurableObjectBindings(config: Config): {
163+
export function partitionDurableObjectBindings(config: Config): {
165164
localBindings: DurableObjectBindings;
166165
remoteBindings: DurableObjectBindings;
167166
} {

0 commit comments

Comments
 (0)