wrangler 2.0.27 → 2.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/wrangler.js +1 -1
- package/package.json +6 -4
- package/src/__tests__/configuration.test.ts +27 -27
- package/src/__tests__/dev.test.tsx +8 -6
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
- package/src/__tests__/helpers/mock-known-routes.ts +7 -0
- package/src/__tests__/index.test.ts +30 -30
- package/src/__tests__/publish.test.ts +59 -18
- package/src/__tests__/tail.test.ts +34 -0
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/worker-namespace.test.ts +37 -35
- package/src/bundle.ts +1 -1
- package/src/cfetch/internal.ts +64 -3
- package/src/config/environment.ts +1 -1
- package/src/config/index.ts +4 -4
- package/src/config/validation.ts +3 -3
- package/src/create-worker-upload-form.ts +29 -26
- package/src/dev/remote.tsx +10 -1
- package/src/dev.tsx +34 -6
- package/src/{worker-namespace.ts → dispatch-namespace.ts} +18 -18
- package/src/index.tsx +54 -8
- package/src/metrics/send-event.ts +5 -5
- package/src/publish.ts +19 -4
- package/src/worker.ts +3 -2
- package/src/zones.ts +91 -0
- package/wrangler-dist/cli.d.ts +7 -3
- package/wrangler-dist/cli.js +5623 -799
|
@@ -4,7 +4,7 @@ import { mockConsoleMethods } from "./helpers/mock-console";
|
|
|
4
4
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
5
5
|
import { runWrangler } from "./helpers/run-wrangler";
|
|
6
6
|
|
|
7
|
-
describe("
|
|
7
|
+
describe("dispatch-namespace", () => {
|
|
8
8
|
runInTempDir();
|
|
9
9
|
const std = mockConsoleMethods();
|
|
10
10
|
mockAccountId();
|
|
@@ -14,8 +14,8 @@ describe("worker-namespace", () => {
|
|
|
14
14
|
unsetAllMocks();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it("should should display a list of available subcommands, for
|
|
18
|
-
await runWrangler("
|
|
17
|
+
it("should should display a list of available subcommands, for dispatch-namespace with no subcommand", async () => {
|
|
18
|
+
await runWrangler("dispatch-namespace");
|
|
19
19
|
|
|
20
20
|
// wait a tick for the help menu to be printed
|
|
21
21
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -24,16 +24,16 @@ describe("worker-namespace", () => {
|
|
|
24
24
|
Object {
|
|
25
25
|
"debug": "",
|
|
26
26
|
"err": "",
|
|
27
|
-
"out": "wrangler
|
|
27
|
+
"out": "wrangler dispatch-namespace
|
|
28
28
|
|
|
29
|
-
📦 Interact with a
|
|
29
|
+
📦 Interact with a dispatch namespace
|
|
30
30
|
|
|
31
31
|
Commands:
|
|
32
|
-
wrangler
|
|
33
|
-
wrangler
|
|
34
|
-
wrangler
|
|
35
|
-
wrangler
|
|
36
|
-
wrangler
|
|
32
|
+
wrangler dispatch-namespace list List all dispatch namespaces
|
|
33
|
+
wrangler dispatch-namespace get <name> Get information about a dispatch namespace
|
|
34
|
+
wrangler dispatch-namespace create <name> Create a dispatch namespace
|
|
35
|
+
wrangler dispatch-namespace delete <name> Delete a dispatch namespace
|
|
36
|
+
wrangler dispatch-namespace rename <old-name> <new-name> Rename a dispatch namespace
|
|
37
37
|
|
|
38
38
|
Flags:
|
|
39
39
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -73,19 +73,19 @@ describe("worker-namespace", () => {
|
|
|
73
73
|
|
|
74
74
|
it("should display help for create", async () => {
|
|
75
75
|
await expect(
|
|
76
|
-
runWrangler("
|
|
76
|
+
runWrangler("dispatch-namespace create")
|
|
77
77
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
78
78
|
`"Not enough non-option arguments: got 0, need at least 1"`
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
expect(std.out).toMatchInlineSnapshot(`
|
|
82
82
|
"
|
|
83
|
-
wrangler
|
|
83
|
+
wrangler dispatch-namespace create <name>
|
|
84
84
|
|
|
85
|
-
Create a
|
|
85
|
+
Create a dispatch namespace
|
|
86
86
|
|
|
87
87
|
Positionals:
|
|
88
|
-
name Name of the
|
|
88
|
+
name Name of the dispatch namespace [string] [required]
|
|
89
89
|
|
|
90
90
|
Flags:
|
|
91
91
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -97,11 +97,11 @@ describe("worker-namespace", () => {
|
|
|
97
97
|
it("should attempt to create the given namespace", async () => {
|
|
98
98
|
const namespaceName = "my-namespace";
|
|
99
99
|
const requests = mockCreateRequest(namespaceName);
|
|
100
|
-
await runWrangler(`
|
|
100
|
+
await runWrangler(`dispatch-namespace create ${namespaceName}`);
|
|
101
101
|
expect(requests.count).toEqual(1);
|
|
102
102
|
|
|
103
103
|
expect(std.out).toMatchInlineSnapshot(
|
|
104
|
-
`"Created
|
|
104
|
+
`"Created dispatch namespace \\"my-namespace\\" with ID \\"some-namespace-id\\""`
|
|
105
105
|
);
|
|
106
106
|
});
|
|
107
107
|
});
|
|
@@ -125,19 +125,19 @@ describe("worker-namespace", () => {
|
|
|
125
125
|
|
|
126
126
|
it("should display help for delete", async () => {
|
|
127
127
|
await expect(
|
|
128
|
-
runWrangler("
|
|
128
|
+
runWrangler("dispatch-namespace create")
|
|
129
129
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
130
130
|
`"Not enough non-option arguments: got 0, need at least 1"`
|
|
131
131
|
);
|
|
132
132
|
|
|
133
133
|
expect(std.out).toMatchInlineSnapshot(`
|
|
134
134
|
"
|
|
135
|
-
wrangler
|
|
135
|
+
wrangler dispatch-namespace create <name>
|
|
136
136
|
|
|
137
|
-
Create a
|
|
137
|
+
Create a dispatch namespace
|
|
138
138
|
|
|
139
139
|
Positionals:
|
|
140
|
-
name Name of the
|
|
140
|
+
name Name of the dispatch namespace [string] [required]
|
|
141
141
|
|
|
142
142
|
Flags:
|
|
143
143
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -149,11 +149,11 @@ describe("worker-namespace", () => {
|
|
|
149
149
|
it("should try to delete the given namespace", async () => {
|
|
150
150
|
const namespaceName = "my-namespace";
|
|
151
151
|
const requests = mockDeleteRequest(namespaceName);
|
|
152
|
-
await runWrangler(`
|
|
152
|
+
await runWrangler(`dispatch-namespace delete ${namespaceName}`);
|
|
153
153
|
expect(requests.count).toBe(1);
|
|
154
154
|
|
|
155
155
|
expect(std.out).toMatchInlineSnapshot(
|
|
156
|
-
`"Deleted
|
|
156
|
+
`"Deleted dispatch namespace \\"my-namespace\\""`
|
|
157
157
|
);
|
|
158
158
|
});
|
|
159
159
|
});
|
|
@@ -183,19 +183,19 @@ describe("worker-namespace", () => {
|
|
|
183
183
|
|
|
184
184
|
it("should display help for get", async () => {
|
|
185
185
|
await expect(
|
|
186
|
-
runWrangler("
|
|
186
|
+
runWrangler("dispatch-namespace get")
|
|
187
187
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
188
188
|
`"Not enough non-option arguments: got 0, need at least 1"`
|
|
189
189
|
);
|
|
190
190
|
|
|
191
191
|
expect(std.out).toMatchInlineSnapshot(`
|
|
192
192
|
"
|
|
193
|
-
wrangler
|
|
193
|
+
wrangler dispatch-namespace get <name>
|
|
194
194
|
|
|
195
|
-
Get information about a
|
|
195
|
+
Get information about a dispatch namespace
|
|
196
196
|
|
|
197
197
|
Positionals:
|
|
198
|
-
name Name of the
|
|
198
|
+
name Name of the dispatch namespace [string] [required]
|
|
199
199
|
|
|
200
200
|
Flags:
|
|
201
201
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -207,7 +207,7 @@ describe("worker-namespace", () => {
|
|
|
207
207
|
it("should attempt to get info for the given namespace", async () => {
|
|
208
208
|
const namespaceName = "my-namespace";
|
|
209
209
|
const requests = mockInfoRequest(namespaceName);
|
|
210
|
-
await runWrangler(`
|
|
210
|
+
await runWrangler(`dispatch-namespace get ${namespaceName}`);
|
|
211
211
|
expect(requests.count).toBe(1);
|
|
212
212
|
|
|
213
213
|
expect(std.out).toMatchInlineSnapshot(`
|
|
@@ -248,7 +248,7 @@ describe("worker-namespace", () => {
|
|
|
248
248
|
|
|
249
249
|
it("should list all namespaces", async () => {
|
|
250
250
|
const requests = mockListRequest();
|
|
251
|
-
await runWrangler("
|
|
251
|
+
await runWrangler("dispatch-namespace list");
|
|
252
252
|
expect(requests.count).toBe(1);
|
|
253
253
|
expect(std.out).toMatchInlineSnapshot(`
|
|
254
254
|
"[
|
|
@@ -291,20 +291,20 @@ describe("worker-namespace", () => {
|
|
|
291
291
|
|
|
292
292
|
it("should display help for rename", async () => {
|
|
293
293
|
await expect(
|
|
294
|
-
runWrangler("
|
|
294
|
+
runWrangler("dispatch-namespace rename")
|
|
295
295
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
296
296
|
`"Not enough non-option arguments: got 0, need at least 2"`
|
|
297
297
|
);
|
|
298
298
|
|
|
299
299
|
expect(std.out).toMatchInlineSnapshot(`
|
|
300
300
|
"
|
|
301
|
-
wrangler
|
|
301
|
+
wrangler dispatch-namespace rename <old-name> <new-name>
|
|
302
302
|
|
|
303
|
-
Rename a
|
|
303
|
+
Rename a dispatch namespace
|
|
304
304
|
|
|
305
305
|
Positionals:
|
|
306
|
-
old-name Name of the
|
|
307
|
-
new-name New name of the
|
|
306
|
+
old-name Name of the dispatch namespace [string] [required]
|
|
307
|
+
new-name New name of the dispatch namespace [string] [required]
|
|
308
308
|
|
|
309
309
|
Flags:
|
|
310
310
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -317,10 +317,12 @@ describe("worker-namespace", () => {
|
|
|
317
317
|
const namespaceName = "my-namespace";
|
|
318
318
|
const newName = "new-namespace";
|
|
319
319
|
const requests = mockRenameRequest(namespaceName);
|
|
320
|
-
await runWrangler(
|
|
320
|
+
await runWrangler(
|
|
321
|
+
`dispatch-namespace rename ${namespaceName} ${newName}`
|
|
322
|
+
);
|
|
321
323
|
expect(requests.count).toBe(1);
|
|
322
324
|
expect(std.out).toMatchInlineSnapshot(
|
|
323
|
-
`"Renamed
|
|
325
|
+
`"Renamed dispatch namespace \\"my-namespace\\" to \\"new-namespace\\""`
|
|
324
326
|
);
|
|
325
327
|
});
|
|
326
328
|
});
|
package/src/bundle.ts
CHANGED
|
@@ -380,7 +380,7 @@ async function applyMultiWorkerDevFacade(
|
|
|
380
380
|
services: Config["services"],
|
|
381
381
|
workerDefinitions: WorkerRegistry
|
|
382
382
|
) {
|
|
383
|
-
const targetPath = path.join(tmpDirPath, "
|
|
383
|
+
const targetPath = path.join(tmpDirPath, "multiworker-dev-facade.entry.js");
|
|
384
384
|
const serviceMap = Object.fromEntries(
|
|
385
385
|
(services || []).map((serviceBinding) => [
|
|
386
386
|
serviceBinding.binding,
|
package/src/cfetch/internal.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
-
import
|
|
2
|
+
import Busboy from "busboy";
|
|
3
|
+
import { fetch, File, FormData, Headers } from "undici";
|
|
3
4
|
import { version as wranglerVersion } from "../../package.json";
|
|
4
5
|
import { getEnvironmentVariableFactory } from "../environment-variables";
|
|
5
6
|
import { logger } from "../logger";
|
|
@@ -226,12 +227,72 @@ export async function fetchDashboardScript(
|
|
|
226
227
|
?.startsWith("multipart");
|
|
227
228
|
|
|
228
229
|
if (usesModules) {
|
|
229
|
-
|
|
230
|
+
// Response from edge contains generic "name = worker.js" for dashboard created scripts
|
|
231
|
+
const form = await formData(response);
|
|
232
|
+
const entries = Array.from(form.entries());
|
|
233
|
+
if (entries.length > 1)
|
|
234
|
+
throw new RangeError("Expected only one entry in multipart response");
|
|
235
|
+
const [_, file] = entries[0];
|
|
236
|
+
|
|
237
|
+
if (file instanceof File) {
|
|
238
|
+
return await file.text();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return file ?? "";
|
|
230
242
|
|
|
231
243
|
// Follow up on issue in Undici about multipart/form-data support & replace the workaround: https://github.com/nodejs/undici/issues/974
|
|
232
244
|
// This should be using a builtin formData() parser pattern.
|
|
233
|
-
return file.split("\n").slice(4, -4).join("\n");
|
|
234
245
|
} else {
|
|
235
246
|
return response.text();
|
|
236
247
|
}
|
|
237
248
|
}
|
|
249
|
+
|
|
250
|
+
async function formData({ headers, body }: Response): Promise<FormData> {
|
|
251
|
+
// undici doesn't include a multipart/form-data parser yet, so we parse
|
|
252
|
+
// form data with busboy instead
|
|
253
|
+
const contentType = headers.get("Content-Type") ?? "";
|
|
254
|
+
if (!/multipart\/form-data/.test(contentType))
|
|
255
|
+
throw Error("Need Content-Type for multipart/form-data");
|
|
256
|
+
|
|
257
|
+
const responseFormData = new FormData();
|
|
258
|
+
|
|
259
|
+
let busboy: Busboy.Busboy;
|
|
260
|
+
|
|
261
|
+
const parsedHeaders = Object.fromEntries(
|
|
262
|
+
Array.from(headers).map(([header, value]) => [header.toLowerCase(), value])
|
|
263
|
+
);
|
|
264
|
+
try {
|
|
265
|
+
busboy = Busboy({ headers: parsedHeaders });
|
|
266
|
+
} catch (err) {
|
|
267
|
+
// Error due to headers:
|
|
268
|
+
throw Object.assign(new TypeError(), { cause: err });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
busboy.on("field", (name, value) => {
|
|
272
|
+
responseFormData.append(name, value);
|
|
273
|
+
});
|
|
274
|
+
busboy.on("file", (name, value, info) => {
|
|
275
|
+
const { filename, encoding, mimeType } = info;
|
|
276
|
+
const base64 = encoding.toLowerCase() === "base64";
|
|
277
|
+
const chunks: Buffer[] = [];
|
|
278
|
+
value.on("data", (chunk) => {
|
|
279
|
+
if (base64) chunk = Buffer.from(chunk.toString(), "base64");
|
|
280
|
+
chunks.push(chunk);
|
|
281
|
+
});
|
|
282
|
+
value.on("end", () => {
|
|
283
|
+
const file = new File(chunks, filename, { type: mimeType });
|
|
284
|
+
responseFormData.append(name, file);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
const busboyResolve = new Promise((resolve, reject) => {
|
|
289
|
+
busboy.on("finish", resolve);
|
|
290
|
+
busboy.on("error", (err) => reject(err));
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (body !== null) for await (const chunk of body) busboy.write(chunk);
|
|
294
|
+
busboy.end();
|
|
295
|
+
await busboyResolve;
|
|
296
|
+
|
|
297
|
+
return responseFormData;
|
|
298
|
+
}
|
|
@@ -210,7 +210,7 @@ interface EnvironmentInheritable {
|
|
|
210
210
|
* @default `[]`
|
|
211
211
|
* @nonInheritable
|
|
212
212
|
*/
|
|
213
|
-
|
|
213
|
+
dispatch_namespaces: {
|
|
214
214
|
/** The binding name used to refer to the bound service. */
|
|
215
215
|
binding: string;
|
|
216
216
|
/** The namespace to bind to. */
|
package/src/config/index.ts
CHANGED
|
@@ -91,7 +91,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
91
91
|
unsafe,
|
|
92
92
|
vars,
|
|
93
93
|
wasm_modules,
|
|
94
|
-
|
|
94
|
+
dispatch_namespaces,
|
|
95
95
|
} = bindings;
|
|
96
96
|
|
|
97
97
|
if (data_blobs !== undefined && Object.keys(data_blobs).length > 0) {
|
|
@@ -219,10 +219,10 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
219
219
|
});
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
if (
|
|
222
|
+
if (dispatch_namespaces !== undefined && dispatch_namespaces.length > 0) {
|
|
223
223
|
output.push({
|
|
224
|
-
type: "
|
|
225
|
-
entries:
|
|
224
|
+
type: "dispatch namespaces",
|
|
225
|
+
entries: dispatch_namespaces.map(({ binding, namespace }) => {
|
|
226
226
|
return {
|
|
227
227
|
key: binding,
|
|
228
228
|
value: namespace,
|
package/src/config/validation.ts
CHANGED
|
@@ -899,7 +899,7 @@ function normalizeAndValidateEnvironment(
|
|
|
899
899
|
|
|
900
900
|
experimental(diagnostics, rawEnv, "unsafe");
|
|
901
901
|
experimental(diagnostics, rawEnv, "services");
|
|
902
|
-
experimental(diagnostics, rawEnv, "
|
|
902
|
+
experimental(diagnostics, rawEnv, "dispatch_namespaces");
|
|
903
903
|
|
|
904
904
|
const route = normalizeAndValidateRoute(diagnostics, topLevelEnv, rawEnv);
|
|
905
905
|
|
|
@@ -1085,13 +1085,13 @@ function normalizeAndValidateEnvironment(
|
|
|
1085
1085
|
validateBindingArray(envName, validateServiceBinding),
|
|
1086
1086
|
[]
|
|
1087
1087
|
),
|
|
1088
|
-
|
|
1088
|
+
dispatch_namespaces: notInheritable(
|
|
1089
1089
|
diagnostics,
|
|
1090
1090
|
topLevelEnv,
|
|
1091
1091
|
rawConfig,
|
|
1092
1092
|
rawEnv,
|
|
1093
1093
|
envName,
|
|
1094
|
-
"
|
|
1094
|
+
"dispatch_namespaces",
|
|
1095
1095
|
validateBindingArray(envName, validateWorkerNamespaceBinding),
|
|
1096
1096
|
[]
|
|
1097
1097
|
),
|
|
@@ -23,6 +23,31 @@ export function toMimeType(type: CfModuleType): string {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
type WorkerMetadataBinding =
|
|
27
|
+
// If you add any new binding types here, also add it to safeBindings
|
|
28
|
+
// under validateUnsafeBinding in config/validation.ts
|
|
29
|
+
| { type: "plain_text"; name: string; text: string }
|
|
30
|
+
| { type: "json"; name: string; json: unknown }
|
|
31
|
+
| { type: "wasm_module"; name: string; part: string }
|
|
32
|
+
| { type: "text_blob"; name: string; part: string }
|
|
33
|
+
| { type: "data_blob"; name: string; part: string }
|
|
34
|
+
| { type: "kv_namespace"; name: string; namespace_id: string }
|
|
35
|
+
| {
|
|
36
|
+
type: "durable_object_namespace";
|
|
37
|
+
name: string;
|
|
38
|
+
class_name: string;
|
|
39
|
+
script_name?: string;
|
|
40
|
+
environment?: string;
|
|
41
|
+
}
|
|
42
|
+
| { type: "r2_bucket"; name: string; bucket_name: string }
|
|
43
|
+
| { type: "service"; name: string; service: string; environment?: string }
|
|
44
|
+
| { type: "namespace"; name: string; namespace: string }
|
|
45
|
+
| {
|
|
46
|
+
type: "logfwdr";
|
|
47
|
+
name: string;
|
|
48
|
+
destination: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
26
51
|
export interface WorkerMetadata {
|
|
27
52
|
/** The name of the entry point module. Only exists when the worker is in the ES module format */
|
|
28
53
|
main_module?: string;
|
|
@@ -33,31 +58,8 @@ export interface WorkerMetadata {
|
|
|
33
58
|
usage_model?: "bundled" | "unbound";
|
|
34
59
|
migrations?: CfDurableObjectMigrations;
|
|
35
60
|
capnp_schema?: string;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
bindings: (
|
|
39
|
-
| { type: "plain_text"; name: string; text: string }
|
|
40
|
-
| { type: "json"; name: string; json: unknown }
|
|
41
|
-
| { type: "wasm_module"; name: string; part: string }
|
|
42
|
-
| { type: "text_blob"; name: string; part: string }
|
|
43
|
-
| { type: "data_blob"; name: string; part: string }
|
|
44
|
-
| { type: "kv_namespace"; name: string; namespace_id: string }
|
|
45
|
-
| {
|
|
46
|
-
type: "durable_object_namespace";
|
|
47
|
-
name: string;
|
|
48
|
-
class_name: string;
|
|
49
|
-
script_name?: string;
|
|
50
|
-
environment?: string;
|
|
51
|
-
}
|
|
52
|
-
| { type: "r2_bucket"; name: string; bucket_name: string }
|
|
53
|
-
| { type: "service"; name: string; service: string; environment?: string }
|
|
54
|
-
| { type: "namespace"; name: string; namespace: string }
|
|
55
|
-
| {
|
|
56
|
-
type: "logfwdr";
|
|
57
|
-
name: string;
|
|
58
|
-
destination: string;
|
|
59
|
-
}
|
|
60
|
-
)[];
|
|
61
|
+
bindings: WorkerMetadataBinding[];
|
|
62
|
+
keep_bindings: WorkerMetadataBinding["type"][];
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/**
|
|
@@ -123,7 +125,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
123
125
|
});
|
|
124
126
|
});
|
|
125
127
|
|
|
126
|
-
bindings.
|
|
128
|
+
bindings.dispatch_namespaces?.forEach(({ binding, namespace }) => {
|
|
127
129
|
metadataBindings.push({
|
|
128
130
|
name: binding,
|
|
129
131
|
type: "namespace",
|
|
@@ -255,6 +257,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
255
257
|
...(usage_model && { usage_model }),
|
|
256
258
|
...(migrations && { migrations }),
|
|
257
259
|
capnp_schema: bindings.logfwdr?.schema,
|
|
260
|
+
keep_bindings: ["plain_text", "json"],
|
|
258
261
|
};
|
|
259
262
|
|
|
260
263
|
formData.set("metadata", JSON.stringify(metadata));
|
package/src/dev/remote.tsx
CHANGED
|
@@ -182,7 +182,7 @@ export function useWorker(props: {
|
|
|
182
182
|
} = props;
|
|
183
183
|
const [session, setSession] = useState<CfPreviewSession | undefined>();
|
|
184
184
|
const [token, setToken] = useState<CfPreviewToken | undefined>();
|
|
185
|
-
|
|
185
|
+
const [restartCounter, setRestartCounter] = useState<number>(0);
|
|
186
186
|
// This is the most reliable way to detect whether
|
|
187
187
|
// something's "happened" in our system; We make a ref and
|
|
188
188
|
// mark it once we log our initial message. Refs are vars!
|
|
@@ -237,6 +237,7 @@ export function useWorker(props: {
|
|
|
237
237
|
props.routes,
|
|
238
238
|
props.zone,
|
|
239
239
|
props.sendMetrics,
|
|
240
|
+
restartCounter,
|
|
240
241
|
]);
|
|
241
242
|
|
|
242
243
|
// This effect uses the session to upload the worker and create a preview
|
|
@@ -314,6 +315,7 @@ export function useWorker(props: {
|
|
|
314
315
|
compatibility_date: compatibilityDate,
|
|
315
316
|
compatibility_flags: compatibilityFlags,
|
|
316
317
|
usage_model: usageModel,
|
|
318
|
+
keep_bindings: true,
|
|
317
319
|
};
|
|
318
320
|
|
|
319
321
|
const workerAccount: CfAccount = {
|
|
@@ -379,6 +381,13 @@ export function useWorker(props: {
|
|
|
379
381
|
logger.error(
|
|
380
382
|
`${errorMessage}\n${solutionMessage}\n${onboardingLink}`
|
|
381
383
|
);
|
|
384
|
+
} else if (err.code === 10049) {
|
|
385
|
+
logger.log("Preview token expired, fetching a new one");
|
|
386
|
+
// code 10049 happens when the preview token expires
|
|
387
|
+
// since we want a new preview token when this happens,
|
|
388
|
+
// lets increment the counter, and trigger a rerun of
|
|
389
|
+
// the useEffect above
|
|
390
|
+
setRestartCounter((prevCount) => prevCount + 1);
|
|
382
391
|
} else {
|
|
383
392
|
logger.error("Error on remote worker:", err);
|
|
384
393
|
}
|
package/src/dev.tsx
CHANGED
|
@@ -63,6 +63,8 @@ interface DevArgs {
|
|
|
63
63
|
tsconfig?: string;
|
|
64
64
|
local?: boolean;
|
|
65
65
|
minify?: boolean;
|
|
66
|
+
var?: string[];
|
|
67
|
+
define?: string[];
|
|
66
68
|
"node-compat"?: boolean;
|
|
67
69
|
"experimental-enable-local-persistence"?: boolean;
|
|
68
70
|
"live-reload"?: boolean;
|
|
@@ -129,7 +131,6 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
|
|
|
129
131
|
.option("ip", {
|
|
130
132
|
describe: "IP address to listen on",
|
|
131
133
|
type: "string",
|
|
132
|
-
default: "0.0.0.0",
|
|
133
134
|
})
|
|
134
135
|
.option("port", {
|
|
135
136
|
describe: "Port to listen on",
|
|
@@ -196,6 +197,19 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
|
|
|
196
197
|
describe: "Protocol to forward requests to host on, defaults to https.",
|
|
197
198
|
choices: ["http", "https"] as const,
|
|
198
199
|
})
|
|
200
|
+
.option("var", {
|
|
201
|
+
describe:
|
|
202
|
+
"A key-value pair to be injected into the script as a variable",
|
|
203
|
+
type: "string",
|
|
204
|
+
requiresArg: true,
|
|
205
|
+
array: true,
|
|
206
|
+
})
|
|
207
|
+
.option("define", {
|
|
208
|
+
describe: "A key-value pair to be substituted in the script",
|
|
209
|
+
type: "string",
|
|
210
|
+
requiresArg: true,
|
|
211
|
+
array: true,
|
|
212
|
+
})
|
|
199
213
|
.option("jsx-factory", {
|
|
200
214
|
describe: "The function that is called for each JSX element",
|
|
201
215
|
type: "string",
|
|
@@ -427,22 +441,36 @@ export async function startDev(args: StartDevOptions) {
|
|
|
427
441
|
const getLocalPort = memoizeGetPort(DEFAULT_LOCAL_PORT);
|
|
428
442
|
const getInspectorPort = memoizeGetPort(DEFAULT_INSPECTOR_PORT);
|
|
429
443
|
|
|
444
|
+
const cliVars =
|
|
445
|
+
args.var?.reduce<Record<string, string>>((collectVars, v) => {
|
|
446
|
+
const [key, ...value] = v.split(":");
|
|
447
|
+
collectVars[key] = value.join("");
|
|
448
|
+
return collectVars;
|
|
449
|
+
}, {}) || {};
|
|
450
|
+
|
|
451
|
+
const cliDefines =
|
|
452
|
+
args.define?.reduce<Record<string, string>>((collectDefines, d) => {
|
|
453
|
+
const [key, ...value] = d.split(":");
|
|
454
|
+
collectDefines[key] = value.join("");
|
|
455
|
+
return collectDefines;
|
|
456
|
+
}, {}) || {};
|
|
457
|
+
|
|
430
458
|
// eslint-disable-next-line no-inner-declarations
|
|
431
459
|
async function getDevReactElement(configParam: Config) {
|
|
432
460
|
// now log all available bindings into the terminal
|
|
433
461
|
const bindings = await getBindings(configParam, {
|
|
434
462
|
kv: args.kv,
|
|
435
|
-
vars: args.vars,
|
|
463
|
+
vars: { ...args.vars, ...cliVars },
|
|
436
464
|
durableObjects: args.durableObjects,
|
|
437
465
|
r2: args.r2,
|
|
438
466
|
});
|
|
439
467
|
|
|
440
|
-
// mask anything that was overridden in .dev.vars
|
|
468
|
+
// mask anything that was overridden in .dev.vars or cli args
|
|
441
469
|
// so that we don't log potential secrets into the terminal
|
|
442
470
|
const maskedVars = { ...bindings.vars };
|
|
443
471
|
for (const key of Object.keys(maskedVars)) {
|
|
444
472
|
if (maskedVars[key] !== configParam.vars[key]) {
|
|
445
|
-
// This means it was overridden in .dev.vars
|
|
473
|
+
// This means it was overridden in .dev.vars or cli args
|
|
446
474
|
// so let's mask it
|
|
447
475
|
maskedVars[key] = "(hidden)";
|
|
448
476
|
}
|
|
@@ -477,7 +505,7 @@ export async function startDev(args: StartDevOptions) {
|
|
|
477
505
|
minify={args.minify ?? config.minify}
|
|
478
506
|
nodeCompat={nodeCompat}
|
|
479
507
|
build={config.build || {}}
|
|
480
|
-
define={config.define}
|
|
508
|
+
define={{ ...config.define, ...cliDefines }}
|
|
481
509
|
initialMode={args.local ? "local" : "remote"}
|
|
482
510
|
jsxFactory={args["jsx-factory"] || config.jsx_factory}
|
|
483
511
|
jsxFragment={args["jsx-fragment"] || config.jsx_fragment}
|
|
@@ -615,7 +643,7 @@ async function getBindings(
|
|
|
615
643
|
) || []),
|
|
616
644
|
...(args.r2 || []),
|
|
617
645
|
],
|
|
618
|
-
|
|
646
|
+
dispatch_namespaces: configParam.dispatch_namespaces,
|
|
619
647
|
services: configParam.services,
|
|
620
648
|
unsafe: configParam.unsafe?.bindings,
|
|
621
649
|
logfwdr: configParam.logfwdr,
|