wrangler 2.3.2 → 2.4.0
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/package.json +2 -2
- package/src/__tests__/dev.test.tsx +26 -0
- package/src/__tests__/index.test.ts +2 -0
- package/src/__tests__/pages.test.ts +55 -1
- package/src/api/dev.ts +2 -0
- package/src/dev/dev.tsx +3 -0
- package/src/dev/local.tsx +134 -18
- package/src/dev/start-server.ts +14 -1
- package/src/dev.tsx +18 -1
- package/src/dialogs.tsx +1 -2
- package/src/index.tsx +1 -2
- package/src/pages/publish.tsx +20 -0
- package/wrangler-dist/cli.d.ts +2 -0
- package/wrangler-dist/cli.js +1053 -958
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wrangler",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Command-line interface for all things Cloudflare Workers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wrangler",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"@databases/sql": "^3.2.0",
|
|
120
120
|
"@iarna/toml": "^3.0.0",
|
|
121
121
|
"@microsoft/api-extractor": "^7.28.3",
|
|
122
|
-
"@miniflare/tre": "^3.0.0-next.
|
|
122
|
+
"@miniflare/tre": "^3.0.0-next.6",
|
|
123
123
|
"@types/better-sqlite3": "^7.6.0",
|
|
124
124
|
"@types/busboy": "^1.5.0",
|
|
125
125
|
"@types/command-exists": "^1.2.0",
|
|
@@ -830,6 +830,31 @@ describe("wrangler dev", () => {
|
|
|
830
830
|
});
|
|
831
831
|
|
|
832
832
|
describe("inspector port", () => {
|
|
833
|
+
it("should connect WebSocket server with --experimental-local", async () => {
|
|
834
|
+
writeWranglerToml({
|
|
835
|
+
main: "./index.js",
|
|
836
|
+
});
|
|
837
|
+
fs.writeFileSync(
|
|
838
|
+
"index.js",
|
|
839
|
+
`export default {
|
|
840
|
+
async fetch(request, env, ctx ){
|
|
841
|
+
console.log('Hello World LOGGING');
|
|
842
|
+
},
|
|
843
|
+
};`
|
|
844
|
+
);
|
|
845
|
+
await runWrangler("dev --experimental-local");
|
|
846
|
+
|
|
847
|
+
expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9229);
|
|
848
|
+
expect(std).toMatchInlineSnapshot(`
|
|
849
|
+
Object {
|
|
850
|
+
"debug": "",
|
|
851
|
+
"err": "",
|
|
852
|
+
"out": "",
|
|
853
|
+
"warn": "",
|
|
854
|
+
}
|
|
855
|
+
`);
|
|
856
|
+
});
|
|
857
|
+
|
|
833
858
|
it("should use 9229 as the default port", async () => {
|
|
834
859
|
writeWranglerToml({
|
|
835
860
|
main: "index.js",
|
|
@@ -1178,6 +1203,7 @@ describe("wrangler dev", () => {
|
|
|
1178
1203
|
--tsconfig Path to a custom tsconfig.json file [string]
|
|
1179
1204
|
-l, --local Run on my machine [boolean] [default: false]
|
|
1180
1205
|
--experimental-local Run on my machine using the Cloudflare Workers runtime [boolean] [default: false]
|
|
1206
|
+
--experimental-local-remote-kv Read/write KV data from/to real namespaces on the Cloudflare network [boolean] [default: false]
|
|
1181
1207
|
--minify Minify the script [boolean]
|
|
1182
1208
|
--node-compat Enable node.js compatibility [boolean]
|
|
1183
1209
|
--persist Enable persistence for local mode, using default path: .wrangler/state [boolean]
|
|
@@ -51,6 +51,7 @@ describe("wrangler", () => {
|
|
|
51
51
|
wrangler logout 🚪 Logout from Cloudflare
|
|
52
52
|
wrangler whoami 🕵️ Retrieve your user info and test your auth config
|
|
53
53
|
wrangler types 📝 Generate types from bindings & module rules in config
|
|
54
|
+
wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
|
|
54
55
|
|
|
55
56
|
Flags:
|
|
56
57
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -96,6 +97,7 @@ describe("wrangler", () => {
|
|
|
96
97
|
wrangler logout 🚪 Logout from Cloudflare
|
|
97
98
|
wrangler whoami 🕵️ Retrieve your user info and test your auth config
|
|
98
99
|
wrangler types 📝 Generate types from bindings & module rules in config
|
|
100
|
+
wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
|
|
99
101
|
|
|
100
102
|
Flags:
|
|
101
103
|
-c, --config Path to .toml configuration file [string]
|
|
@@ -1165,16 +1165,21 @@ describe("pages", () => {
|
|
|
1165
1165
|
const body = init.body as FormData;
|
|
1166
1166
|
const manifest = JSON.parse(body.get("manifest") as string);
|
|
1167
1167
|
|
|
1168
|
-
// for Functions projects, we auto-generate a `_worker.js
|
|
1168
|
+
// for Functions projects, we auto-generate a `_worker.js`,
|
|
1169
|
+
// `functions-filepath-routing-config.json`, and `_routes.json`
|
|
1169
1170
|
// file, based on the contents of `/functions`
|
|
1170
1171
|
const generatedWorkerJS = body.get("_worker.js") as Blob;
|
|
1171
1172
|
const generatedRoutesJSON = await (
|
|
1172
1173
|
body.get("_routes.json") as Blob
|
|
1173
1174
|
).text();
|
|
1175
|
+
const generatedFilepathRoutingConfig = await (
|
|
1176
|
+
body.get("functions-filepath-routing-config.json") as Blob
|
|
1177
|
+
).text();
|
|
1174
1178
|
|
|
1175
1179
|
// make sure this is all we uploaded
|
|
1176
1180
|
expect([...body.keys()]).toEqual([
|
|
1177
1181
|
"manifest",
|
|
1182
|
+
"functions-filepath-routing-config.json",
|
|
1178
1183
|
"_worker.js",
|
|
1179
1184
|
"_routes.json",
|
|
1180
1185
|
]);
|
|
@@ -1202,6 +1207,25 @@ describe("pages", () => {
|
|
|
1202
1207
|
include: ["/hello"],
|
|
1203
1208
|
exclude: [],
|
|
1204
1209
|
});
|
|
1210
|
+
|
|
1211
|
+
// Make sure the routing config is valid json
|
|
1212
|
+
const parsedFilepathRoutingConfig = JSON.parse(
|
|
1213
|
+
generatedFilepathRoutingConfig
|
|
1214
|
+
);
|
|
1215
|
+
// The actual shape doesn't matter that much since this
|
|
1216
|
+
// is only used for display in Dash, but it's still useful for
|
|
1217
|
+
// tracking unexpected changes to this config.
|
|
1218
|
+
expect(parsedFilepathRoutingConfig).toStrictEqual({
|
|
1219
|
+
routes: [
|
|
1220
|
+
{
|
|
1221
|
+
routePath: "/hello",
|
|
1222
|
+
mountPath: "/",
|
|
1223
|
+
method: "",
|
|
1224
|
+
module: ["hello.js:onRequest"],
|
|
1225
|
+
},
|
|
1226
|
+
],
|
|
1227
|
+
baseURL: "/",
|
|
1228
|
+
});
|
|
1205
1229
|
});
|
|
1206
1230
|
|
|
1207
1231
|
return {
|
|
@@ -1456,10 +1480,14 @@ describe("pages", () => {
|
|
|
1456
1480
|
const customRoutesJSON = await (
|
|
1457
1481
|
body.get("_routes.json") as Blob
|
|
1458
1482
|
).text();
|
|
1483
|
+
const generatedFilepathRoutingConfig = await (
|
|
1484
|
+
body.get("functions-filepath-routing-config.json") as Blob
|
|
1485
|
+
).text();
|
|
1459
1486
|
|
|
1460
1487
|
// make sure this is all we uploaded
|
|
1461
1488
|
expect([...body.keys()]).toEqual([
|
|
1462
1489
|
"manifest",
|
|
1490
|
+
"functions-filepath-routing-config.json",
|
|
1463
1491
|
"_worker.js",
|
|
1464
1492
|
"_routes.json",
|
|
1465
1493
|
]);
|
|
@@ -1481,6 +1509,32 @@ describe("pages", () => {
|
|
|
1481
1509
|
include: ["/hello"],
|
|
1482
1510
|
exclude: [],
|
|
1483
1511
|
});
|
|
1512
|
+
|
|
1513
|
+
// Make sure the routing config is valid json
|
|
1514
|
+
const parsedFilepathRoutingConfig = JSON.parse(
|
|
1515
|
+
generatedFilepathRoutingConfig
|
|
1516
|
+
);
|
|
1517
|
+
// The actual shape doesn't matter that much since this
|
|
1518
|
+
// is only used for display in Dash, but it's still useful for
|
|
1519
|
+
// tracking unexpected changes to this config.
|
|
1520
|
+
console.log(generatedFilepathRoutingConfig);
|
|
1521
|
+
expect(parsedFilepathRoutingConfig).toStrictEqual({
|
|
1522
|
+
routes: [
|
|
1523
|
+
{
|
|
1524
|
+
routePath: "/goodbye",
|
|
1525
|
+
mountPath: "/",
|
|
1526
|
+
method: "",
|
|
1527
|
+
module: ["goodbye.ts:onRequest"],
|
|
1528
|
+
},
|
|
1529
|
+
{
|
|
1530
|
+
routePath: "/hello",
|
|
1531
|
+
mountPath: "/",
|
|
1532
|
+
method: "",
|
|
1533
|
+
module: ["hello.js:onRequest"],
|
|
1534
|
+
},
|
|
1535
|
+
],
|
|
1536
|
+
baseURL: "/",
|
|
1537
|
+
});
|
|
1484
1538
|
});
|
|
1485
1539
|
|
|
1486
1540
|
return {
|
package/src/api/dev.ts
CHANGED
package/src/dev/dev.tsx
CHANGED
|
@@ -155,6 +155,7 @@ export type DevProps = {
|
|
|
155
155
|
sendMetrics: boolean | undefined;
|
|
156
156
|
testScheduled: boolean | undefined;
|
|
157
157
|
experimentalLocal: boolean | undefined;
|
|
158
|
+
experimentalLocalRemoteKv: boolean | undefined;
|
|
158
159
|
};
|
|
159
160
|
|
|
160
161
|
export function DevImplementation(props: DevProps): JSX.Element {
|
|
@@ -326,6 +327,8 @@ function DevSession(props: DevSessionProps) {
|
|
|
326
327
|
onReady={props.onReady}
|
|
327
328
|
enablePagesAssetsServiceBinding={props.enablePagesAssetsServiceBinding}
|
|
328
329
|
experimentalLocal={props.experimentalLocal}
|
|
330
|
+
accountId={props.accountId}
|
|
331
|
+
experimentalLocalRemoteKv={props.experimentalLocalRemoteKv}
|
|
329
332
|
/>
|
|
330
333
|
) : (
|
|
331
334
|
<Remote
|
package/src/dev/local.tsx
CHANGED
|
@@ -4,10 +4,10 @@ import { realpathSync } from "node:fs";
|
|
|
4
4
|
import { readFile, writeFile } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import chalk from "chalk";
|
|
7
|
-
import getPort from "get-port";
|
|
8
7
|
import { npxImport } from "npx-import";
|
|
9
8
|
import { useState, useEffect, useRef } from "react";
|
|
10
9
|
import onExit from "signal-exit";
|
|
10
|
+
import { performApiFetch } from "../cfetch/internal";
|
|
11
11
|
import { registerWorker } from "../dev-registry";
|
|
12
12
|
import useInspector from "../inspect";
|
|
13
13
|
import { logger } from "../logger";
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "../module-collection";
|
|
18
18
|
import { getBasePath } from "../paths";
|
|
19
19
|
import { waitForPortToBeAvailable } from "../proxy";
|
|
20
|
+
import { requireAuth } from "../user";
|
|
20
21
|
import type { Config } from "../config";
|
|
21
22
|
import type { WorkerRegistry } from "../dev-registry";
|
|
22
23
|
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
@@ -38,9 +39,11 @@ import type { EsbuildBundle } from "./use-esbuild";
|
|
|
38
39
|
import type {
|
|
39
40
|
Miniflare as Miniflare3Type,
|
|
40
41
|
MiniflareOptions as Miniflare3Options,
|
|
42
|
+
CloudflareFetch,
|
|
41
43
|
} from "@miniflare/tre";
|
|
42
44
|
import type { MiniflareOptions } from "miniflare";
|
|
43
45
|
import type { ChildProcess } from "node:child_process";
|
|
46
|
+
import type { RequestInit } from "undici";
|
|
44
47
|
|
|
45
48
|
export interface LocalProps {
|
|
46
49
|
name: string | undefined;
|
|
@@ -67,15 +70,29 @@ export interface LocalProps {
|
|
|
67
70
|
logPrefix?: string;
|
|
68
71
|
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
69
72
|
testScheduled?: boolean;
|
|
70
|
-
experimentalLocal
|
|
73
|
+
experimentalLocal: boolean | undefined;
|
|
74
|
+
accountId: string | undefined; // Account ID? In local mode??? :exploding_head:
|
|
75
|
+
experimentalLocalRemoteKv: boolean | undefined;
|
|
71
76
|
}
|
|
72
77
|
|
|
78
|
+
type InspectorJSON = {
|
|
79
|
+
id: string;
|
|
80
|
+
title: string;
|
|
81
|
+
type: "node";
|
|
82
|
+
description: string;
|
|
83
|
+
webSocketDebuggerUrl: string;
|
|
84
|
+
devtoolsFrontendUrl: string;
|
|
85
|
+
devtoolsFrontendUrlCompat: string;
|
|
86
|
+
faviconUrl: string;
|
|
87
|
+
url: string;
|
|
88
|
+
}[];
|
|
89
|
+
|
|
73
90
|
export function Local(props: LocalProps) {
|
|
74
91
|
const { inspectorUrl } = useLocalWorker(props);
|
|
75
92
|
useInspector({
|
|
76
93
|
inspectorUrl,
|
|
77
94
|
port: props.inspectorPort,
|
|
78
|
-
logToTerminal: false,
|
|
95
|
+
logToTerminal: props.experimentalLocal ?? false,
|
|
79
96
|
});
|
|
80
97
|
return null;
|
|
81
98
|
}
|
|
@@ -105,6 +122,8 @@ function useLocalWorker({
|
|
|
105
122
|
logPrefix,
|
|
106
123
|
enablePagesAssetsServiceBinding,
|
|
107
124
|
experimentalLocal,
|
|
125
|
+
accountId,
|
|
126
|
+
experimentalLocalRemoteKv,
|
|
108
127
|
}: LocalProps) {
|
|
109
128
|
// TODO: pass vars via command line
|
|
110
129
|
const local = useRef<ChildProcess>();
|
|
@@ -209,8 +228,19 @@ function useLocalWorker({
|
|
|
209
228
|
});
|
|
210
229
|
|
|
211
230
|
if (experimentalLocal) {
|
|
212
|
-
const mf3Options = await transformLocalOptions(
|
|
231
|
+
const mf3Options = await transformLocalOptions({
|
|
232
|
+
miniflare2Options: options,
|
|
233
|
+
format,
|
|
234
|
+
bundle,
|
|
235
|
+
kvNamespaces: bindings?.kv_namespaces,
|
|
236
|
+
r2Buckets: bindings?.r2_buckets,
|
|
237
|
+
authenticatedAccountId: accountId,
|
|
238
|
+
kvRemote: experimentalLocalRemoteKv,
|
|
239
|
+
inspectorPort,
|
|
240
|
+
});
|
|
241
|
+
|
|
213
242
|
const current = experimentalLocalRef.current;
|
|
243
|
+
|
|
214
244
|
if (current === undefined) {
|
|
215
245
|
// If we don't have an active Miniflare instance, create a new one
|
|
216
246
|
const Miniflare = await getMiniflare3Constructor();
|
|
@@ -230,6 +260,34 @@ function useLocalWorker({
|
|
|
230
260
|
logger.log("⎔ Reloading experimental local server.");
|
|
231
261
|
await current.setOptions(mf3Options);
|
|
232
262
|
}
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
// fetch the inspector JSON response from the DevTools Inspector protocol
|
|
266
|
+
const inspectorJSONArr = (await (
|
|
267
|
+
await fetch(`http://127.0.0.1:${inspectorPort}/json`)
|
|
268
|
+
).json()) as InspectorJSON;
|
|
269
|
+
|
|
270
|
+
const foundInspectorURL = inspectorJSONArr?.find((inspectorJSON) =>
|
|
271
|
+
inspectorJSON.id.startsWith("core:user")
|
|
272
|
+
)?.webSocketDebuggerUrl;
|
|
273
|
+
if (foundInspectorURL === undefined) {
|
|
274
|
+
setInspectorUrl(undefined);
|
|
275
|
+
} else {
|
|
276
|
+
const url = new URL(foundInspectorURL);
|
|
277
|
+
// Force inspector URL to be different on each reload so `useEffect`
|
|
278
|
+
// in `useInspector` is re-run to connect to newly restarted
|
|
279
|
+
// `workerd` server when updating options. Can't use a query param
|
|
280
|
+
// here as that seems to cause an infinite connection loop, can't
|
|
281
|
+
// use a hash as those are forbidden by `ws`, so username it is.
|
|
282
|
+
url.username = `${Date.now()}-${Math.floor(
|
|
283
|
+
Math.random() * Number.MAX_SAFE_INTEGER
|
|
284
|
+
)}`;
|
|
285
|
+
setInspectorUrl(url.toString());
|
|
286
|
+
}
|
|
287
|
+
} catch (error: unknown) {
|
|
288
|
+
logger.error("Error attempting to retrieve Debugger URL:", error);
|
|
289
|
+
}
|
|
290
|
+
|
|
233
291
|
return;
|
|
234
292
|
}
|
|
235
293
|
|
|
@@ -367,6 +425,8 @@ function useLocalWorker({
|
|
|
367
425
|
onReady,
|
|
368
426
|
enablePagesAssetsServiceBinding,
|
|
369
427
|
experimentalLocal,
|
|
428
|
+
accountId,
|
|
429
|
+
experimentalLocalRemoteKv,
|
|
370
430
|
]);
|
|
371
431
|
|
|
372
432
|
// Rather than disposing the Miniflare instance on every reload, only dispose
|
|
@@ -683,24 +743,65 @@ export function setupNodeOptions({
|
|
|
683
743
|
return nodeOptions;
|
|
684
744
|
}
|
|
685
745
|
|
|
686
|
-
|
|
687
|
-
|
|
746
|
+
export interface SetupMiniflare3Options {
|
|
747
|
+
// Regular Miniflare 2 options to transform
|
|
748
|
+
miniflare2Options: MiniflareOptions;
|
|
749
|
+
// Miniflare 3 requires all modules to be manually specified
|
|
750
|
+
format: CfScriptFormat;
|
|
751
|
+
bundle: EsbuildBundle;
|
|
752
|
+
|
|
753
|
+
// Miniflare 3 accepts namespace/bucket names in addition to binding names.
|
|
754
|
+
// This means multiple workers persisting to the same location can have
|
|
755
|
+
// different binding names for the same namespace/bucket. Therefore, we need
|
|
756
|
+
// the full KV/R2 arrays. This is also required for remote KV storage, as
|
|
757
|
+
// we need actual namespace IDs to connect to.
|
|
758
|
+
kvNamespaces: CfKvNamespace[] | undefined;
|
|
759
|
+
r2Buckets: CfR2Bucket[] | undefined;
|
|
760
|
+
|
|
761
|
+
// Account ID to use for authenticated Cloudflare fetch. If true, prompt
|
|
762
|
+
// user for ID if multiple available.
|
|
763
|
+
authenticatedAccountId: string | true | undefined;
|
|
764
|
+
// Whether to read/write from/to real KV namespaces
|
|
765
|
+
kvRemote: boolean | undefined;
|
|
766
|
+
inspectorPort: number;
|
|
688
767
|
}
|
|
689
768
|
|
|
690
|
-
export async function transformLocalOptions(
|
|
691
|
-
|
|
692
|
-
format
|
|
693
|
-
bundle
|
|
694
|
-
|
|
769
|
+
export async function transformLocalOptions({
|
|
770
|
+
miniflare2Options,
|
|
771
|
+
format,
|
|
772
|
+
bundle,
|
|
773
|
+
kvNamespaces,
|
|
774
|
+
r2Buckets,
|
|
775
|
+
authenticatedAccountId,
|
|
776
|
+
kvRemote,
|
|
777
|
+
inspectorPort,
|
|
778
|
+
}: SetupMiniflare3Options): Promise<Miniflare3Options> {
|
|
779
|
+
// Build authenticated Cloudflare API fetch function if required
|
|
780
|
+
let cloudflareFetch: CloudflareFetch | undefined;
|
|
781
|
+
if (kvRemote && authenticatedAccountId !== undefined) {
|
|
782
|
+
const preferredAccountId =
|
|
783
|
+
authenticatedAccountId === true ? undefined : authenticatedAccountId;
|
|
784
|
+
const accountId = await requireAuth({ account_id: preferredAccountId });
|
|
785
|
+
cloudflareFetch = (resource, searchParams, init) => {
|
|
786
|
+
resource = `/accounts/${accountId}/${resource}`;
|
|
787
|
+
// Miniflare and Wrangler's `undici` versions may be slightly different,
|
|
788
|
+
// but their `RequestInit` types *should* be compatible
|
|
789
|
+
return performApiFetch(resource, init as RequestInit, searchParams);
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
695
793
|
const options: Miniflare3Options = {
|
|
696
|
-
...
|
|
794
|
+
...miniflare2Options,
|
|
697
795
|
// Miniflare 3 distinguishes between binding name and namespace/bucket IDs.
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
r2Buckets:
|
|
702
|
-
|
|
796
|
+
kvNamespaces: Object.fromEntries(
|
|
797
|
+
kvNamespaces?.map(({ binding, id }) => [binding, id]) ?? []
|
|
798
|
+
),
|
|
799
|
+
r2Buckets: Object.fromEntries(
|
|
800
|
+
r2Buckets?.map(({ binding, bucket_name }) => [binding, bucket_name]) ?? []
|
|
801
|
+
),
|
|
802
|
+
inspectorPort,
|
|
703
803
|
verbose: true,
|
|
804
|
+
cloudflareFetch,
|
|
704
805
|
};
|
|
705
806
|
|
|
706
807
|
if (format === "modules") {
|
|
@@ -729,6 +830,21 @@ export async function transformLocalOptions(
|
|
|
729
830
|
];
|
|
730
831
|
}
|
|
731
832
|
|
|
833
|
+
if (kvRemote) {
|
|
834
|
+
// `kvPersist` is always assigned a truthy value in `setupMiniflareOptions`
|
|
835
|
+
assert(options.kvPersist);
|
|
836
|
+
const kvRemoteCache =
|
|
837
|
+
options.kvPersist === true
|
|
838
|
+
? // If storing in temporary directory, find this path from the bundle
|
|
839
|
+
// output path
|
|
840
|
+
path.join(path.dirname(bundle.path), ".mf", "kv-remote")
|
|
841
|
+
: // Otherwise, `kvPersist` looks like `.../kv`, so rewrite it to
|
|
842
|
+
// `kv-remote` since the expected metadata format for remote storage
|
|
843
|
+
// is different to local
|
|
844
|
+
path.join(path.dirname(options.kvPersist), "kv-remote");
|
|
845
|
+
options.kvPersist = `remote:?cache=${encodeURIComponent(kvRemoteCache)}`;
|
|
846
|
+
}
|
|
847
|
+
|
|
732
848
|
return options;
|
|
733
849
|
}
|
|
734
850
|
|
|
@@ -740,7 +856,7 @@ export async function getMiniflare3Constructor(): Promise<typeof Miniflare> {
|
|
|
740
856
|
({ Miniflare } = await npxImport<
|
|
741
857
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
742
858
|
typeof import("@miniflare/tre")
|
|
743
|
-
>("@miniflare/tre@3.0.0-next.
|
|
859
|
+
>("@miniflare/tre@3.0.0-next.6"));
|
|
744
860
|
}
|
|
745
861
|
return Miniflare;
|
|
746
862
|
}
|
package/src/dev/start-server.ts
CHANGED
|
@@ -127,6 +127,8 @@ export async function startDevServer(
|
|
|
127
127
|
usageModel: props.usageModel,
|
|
128
128
|
workerDefinitions,
|
|
129
129
|
experimentalLocal: props.experimentalLocal,
|
|
130
|
+
accountId: props.accountId,
|
|
131
|
+
experimentalLocalRemoteKv: props.experimentalLocalRemoteKv,
|
|
130
132
|
});
|
|
131
133
|
|
|
132
134
|
return {
|
|
@@ -303,6 +305,8 @@ export async function startLocalServer({
|
|
|
303
305
|
logPrefix,
|
|
304
306
|
enablePagesAssetsServiceBinding,
|
|
305
307
|
experimentalLocal,
|
|
308
|
+
accountId,
|
|
309
|
+
experimentalLocalRemoteKv,
|
|
306
310
|
}: LocalProps) {
|
|
307
311
|
let local: ChildProcess | undefined;
|
|
308
312
|
let experimentalLocalRef: Miniflare3Type | undefined;
|
|
@@ -396,7 +400,16 @@ export async function startLocalServer({
|
|
|
396
400
|
});
|
|
397
401
|
|
|
398
402
|
if (experimentalLocal) {
|
|
399
|
-
const mf3Options = await transformLocalOptions(
|
|
403
|
+
const mf3Options = await transformLocalOptions({
|
|
404
|
+
miniflare2Options: options,
|
|
405
|
+
format,
|
|
406
|
+
bundle,
|
|
407
|
+
kvNamespaces: bindings?.kv_namespaces,
|
|
408
|
+
r2Buckets: bindings?.r2_buckets,
|
|
409
|
+
authenticatedAccountId: accountId,
|
|
410
|
+
kvRemote: experimentalLocalRemoteKv,
|
|
411
|
+
inspectorPort,
|
|
412
|
+
});
|
|
400
413
|
const Miniflare = await getMiniflare3Constructor();
|
|
401
414
|
const mf = new Miniflare(mf3Options);
|
|
402
415
|
const runtimeURL = await mf.ready;
|
package/src/dev.tsx
CHANGED
|
@@ -65,6 +65,7 @@ interface DevArgs {
|
|
|
65
65
|
tsconfig?: string;
|
|
66
66
|
local?: boolean;
|
|
67
67
|
"experimental-local"?: boolean;
|
|
68
|
+
"experimental-local-remote-kv"?: boolean;
|
|
68
69
|
minify?: boolean;
|
|
69
70
|
var?: string[];
|
|
70
71
|
define?: string[];
|
|
@@ -237,11 +238,25 @@ export function devOptions(yargs: Argv<CommonYargsOptions>): Argv<DevArgs> {
|
|
|
237
238
|
type: "boolean",
|
|
238
239
|
default: false,
|
|
239
240
|
})
|
|
241
|
+
.option("experimental-local-remote-kv", {
|
|
242
|
+
describe:
|
|
243
|
+
"Read/write KV data from/to real namespaces on the Cloudflare network",
|
|
244
|
+
type: "boolean",
|
|
245
|
+
default: false,
|
|
246
|
+
})
|
|
240
247
|
.check((argv) => {
|
|
241
248
|
if (argv.local && argv["experimental-local"]) {
|
|
242
249
|
throw new Error(
|
|
243
250
|
"--local and --experimental-local are mutually exclusive. " +
|
|
244
|
-
"Please
|
|
251
|
+
"Please enable one or the other."
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
if (
|
|
255
|
+
argv["experimental-local-remote-kv"] &&
|
|
256
|
+
!argv["experimental-local"]
|
|
257
|
+
) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
"--experimental-local-remote-kv requires --experimental-local to be enabled."
|
|
245
260
|
);
|
|
246
261
|
}
|
|
247
262
|
return true;
|
|
@@ -461,6 +476,7 @@ export async function startDev(args: StartDevOptions) {
|
|
|
461
476
|
sendMetrics={configParam.send_metrics}
|
|
462
477
|
testScheduled={args["test-scheduled"]}
|
|
463
478
|
experimentalLocal={args.experimentalLocal}
|
|
479
|
+
experimentalLocalRemoteKv={args.experimentalLocalRemoteKv}
|
|
464
480
|
/>
|
|
465
481
|
);
|
|
466
482
|
}
|
|
@@ -582,6 +598,7 @@ export async function startApiDev(args: StartDevOptions) {
|
|
|
582
598
|
sendMetrics: configParam.send_metrics,
|
|
583
599
|
testScheduled: args.testScheduled,
|
|
584
600
|
experimentalLocal: args.experimentalLocal,
|
|
601
|
+
experimentalLocalRemoteKv: args.experimentalLocalRemoteKv,
|
|
585
602
|
});
|
|
586
603
|
}
|
|
587
604
|
|
package/src/dialogs.tsx
CHANGED
|
@@ -153,8 +153,7 @@ export async function fromDashMessagePrompt(
|
|
|
153
153
|
): Promise<boolean | void> {
|
|
154
154
|
if (deploySource === "dash") {
|
|
155
155
|
logger.warn(
|
|
156
|
-
`You are about to publish a Workers Service that was last published via the Cloudflare Dashboard
|
|
157
|
-
Edits that have been made via the dashboard will be overridden by your local code and config.`
|
|
156
|
+
`You are about to publish a Workers Service that was last published via the Cloudflare Dashboard.\nEdits that have been made via the dashboard will be overridden by your local code and config.`
|
|
158
157
|
);
|
|
159
158
|
|
|
160
159
|
if (!isInteractive() || CI.isCI()) return true;
|
package/src/index.tsx
CHANGED
|
@@ -554,8 +554,7 @@ export function createCLIParser(argv: string[]) {
|
|
|
554
554
|
"🚧`wrangler deployments` is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose";
|
|
555
555
|
wrangler.command(
|
|
556
556
|
"deployments",
|
|
557
|
-
|
|
558
|
-
// "🚢 Logs the 10 most recent deployments with 'Version ID', 'Version number','Author email', 'Created on' and 'Latest deploy'",
|
|
557
|
+
"🚢 Displays the 10 most recent deployments for a worker",
|
|
559
558
|
(yargs) => {
|
|
560
559
|
yargs
|
|
561
560
|
.option("name", {
|
package/src/pages/publish.tsx
CHANGED
|
@@ -275,11 +275,20 @@ export const Handler = async ({
|
|
|
275
275
|
? join(tmpdir(), `_routes-${Math.random()}.json`)
|
|
276
276
|
: undefined;
|
|
277
277
|
|
|
278
|
+
// Routing configuration displayed in the Functions tab of a deployment in Dash
|
|
279
|
+
let filepathRoutingConfig: string | undefined;
|
|
280
|
+
|
|
278
281
|
if (!_workerJS && existsSync(functionsDirectory)) {
|
|
279
282
|
const outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.js`);
|
|
283
|
+
const outputConfigPath = join(
|
|
284
|
+
tmpdir(),
|
|
285
|
+
`functions-filepath-routing-config-${Math.random()}.json`
|
|
286
|
+
);
|
|
287
|
+
|
|
280
288
|
try {
|
|
281
289
|
await buildFunctions({
|
|
282
290
|
outfile,
|
|
291
|
+
outputConfigPath,
|
|
283
292
|
functionsDirectory,
|
|
284
293
|
onEnd: () => {},
|
|
285
294
|
buildOutputDirectory: dirname(outfile),
|
|
@@ -292,6 +301,7 @@ export const Handler = async ({
|
|
|
292
301
|
});
|
|
293
302
|
|
|
294
303
|
builtFunctions = readFileSync(outfile, "utf-8");
|
|
304
|
+
filepathRoutingConfig = readFileSync(outputConfigPath, "utf-8");
|
|
295
305
|
} catch (e) {
|
|
296
306
|
if (e instanceof FunctionsNoRoutesError) {
|
|
297
307
|
logger.warn(
|
|
@@ -335,6 +345,16 @@ export const Handler = async ({
|
|
|
335
345
|
logger.log(`✨ Uploading _redirects`);
|
|
336
346
|
}
|
|
337
347
|
|
|
348
|
+
if (filepathRoutingConfig) {
|
|
349
|
+
formData.append(
|
|
350
|
+
"functions-filepath-routing-config.json",
|
|
351
|
+
new File(
|
|
352
|
+
[filepathRoutingConfig],
|
|
353
|
+
"functions-filepath-routing-config.json"
|
|
354
|
+
)
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
338
358
|
/**
|
|
339
359
|
* Advanced Mode
|
|
340
360
|
* https://developers.cloudflare.com/pages/platform/functions/#advanced-mode
|
package/wrangler-dist/cli.d.ts
CHANGED