wrangler 2.0.27 → 2.1.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/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +1141 -369
- package/package.json +6 -4
- package/src/__tests__/api-dev.test.ts +19 -0
- package/src/__tests__/configuration.test.ts +27 -27
- package/src/__tests__/dev.test.tsx +8 -6
- package/src/__tests__/helpers/hello-world-worker.js +5 -0
- package/src/__tests__/helpers/mock-cfetch.ts +4 -4
- package/src/__tests__/helpers/mock-console.ts +11 -2
- 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 +37 -37
- package/src/__tests__/init.test.ts +356 -5
- package/src/__tests__/jest.setup.ts +13 -0
- package/src/__tests__/middleware.test.ts +768 -0
- package/src/__tests__/pages.test.ts +829 -104
- package/src/__tests__/paths.test.ts +17 -0
- package/src/__tests__/publish.test.ts +512 -445
- package/src/__tests__/tail.test.ts +79 -72
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/worker-namespace.test.ts +37 -35
- package/src/api/dev.ts +93 -28
- package/src/bundle.ts +239 -12
- package/src/cfetch/internal.ts +64 -3
- package/src/cli.ts +1 -1
- 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/dev.tsx +3 -1
- package/src/dev/local.tsx +319 -171
- package/src/dev/remote.tsx +16 -4
- package/src/dev/start-server.ts +416 -0
- package/src/dev/use-esbuild.ts +4 -0
- package/src/dev.tsx +340 -166
- package/src/dialogs.tsx +12 -0
- package/src/{worker-namespace.ts → dispatch-namespace.ts} +18 -18
- package/src/entry.ts +2 -1
- package/src/index.tsx +59 -12
- package/src/init.ts +291 -16
- package/src/metrics/send-event.ts +6 -5
- package/src/miniflare-cli/assets.ts +130 -476
- package/src/miniflare-cli/index.ts +39 -33
- package/src/pages/constants.ts +3 -0
- package/src/pages/dev.tsx +8 -3
- package/src/pages/functions/buildPlugin.ts +2 -1
- package/src/pages/functions/buildWorker.ts +2 -1
- package/src/pages/functions/routes-transformation.test.ts +12 -1
- package/src/pages/functions/routes-transformation.ts +7 -1
- package/src/pages/hash.tsx +13 -0
- package/src/pages/publish.tsx +82 -38
- package/src/pages/upload.tsx +3 -18
- package/src/paths.ts +20 -1
- package/src/publish.ts +49 -8
- package/src/tail/filters.ts +1 -5
- package/src/tail/index.ts +6 -3
- package/src/worker.ts +10 -9
- package/src/zones.ts +91 -0
- package/templates/middleware/common.ts +62 -0
- package/templates/middleware/loader-modules.ts +84 -0
- package/templates/middleware/loader-sw.ts +213 -0
- package/templates/middleware/middleware-pretty-error.ts +40 -0
- package/templates/middleware/middleware-scheduled.ts +14 -0
- package/wrangler-dist/cli.d.ts +22 -8
- package/wrangler-dist/cli.js +71020 -65212
|
@@ -3,7 +3,9 @@ import { Headers, Request } from "undici";
|
|
|
3
3
|
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
4
4
|
import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
|
|
5
5
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
6
|
+
import { mockGetZoneFromHostRequest } from "./helpers/mock-get-zone-from-host";
|
|
6
7
|
import { useMockIsTTY } from "./helpers/mock-istty";
|
|
8
|
+
import { mockCollectKnownRoutesRequest } from "./helpers/mock-known-routes";
|
|
7
9
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
8
10
|
import { runWrangler } from "./helpers/run-wrangler";
|
|
9
11
|
import type {
|
|
@@ -12,6 +14,7 @@ import type {
|
|
|
12
14
|
ScheduledEvent,
|
|
13
15
|
AlarmEvent,
|
|
14
16
|
} from "../tail";
|
|
17
|
+
import type { RequestInit } from "undici";
|
|
15
18
|
import type WebSocket from "ws";
|
|
16
19
|
|
|
17
20
|
describe("tail", () => {
|
|
@@ -42,26 +45,58 @@ describe("tail", () => {
|
|
|
42
45
|
|
|
43
46
|
it("creates and then delete tails", async () => {
|
|
44
47
|
const api = mockWebsocketAPIs();
|
|
45
|
-
expect(api.requests.creation.
|
|
48
|
+
expect(api.requests.creation.length).toStrictEqual(0);
|
|
46
49
|
|
|
47
50
|
await runWrangler("tail test-worker");
|
|
48
51
|
|
|
49
52
|
await expect(api.ws.connected).resolves.toBeTruthy();
|
|
50
|
-
expect(api.requests.creation.
|
|
53
|
+
expect(api.requests.creation.length).toStrictEqual(1);
|
|
54
|
+
expect(api.requests.deletion.count).toStrictEqual(0);
|
|
55
|
+
|
|
56
|
+
api.ws.close();
|
|
57
|
+
expect(api.requests.deletion.count).toStrictEqual(1);
|
|
58
|
+
});
|
|
59
|
+
it("should connect to the worker assigned to a given route", async () => {
|
|
60
|
+
const api = mockWebsocketAPIs();
|
|
61
|
+
expect(api.requests.creation.length).toStrictEqual(0);
|
|
62
|
+
|
|
63
|
+
mockGetZoneFromHostRequest("example.com", "test-zone");
|
|
64
|
+
mockCollectKnownRoutesRequest([
|
|
65
|
+
{
|
|
66
|
+
pattern: "example.com/*",
|
|
67
|
+
script: "test-worker",
|
|
68
|
+
},
|
|
69
|
+
]);
|
|
70
|
+
await runWrangler("tail example.com/*");
|
|
71
|
+
|
|
72
|
+
await expect(api.ws.connected).resolves.toBeTruthy();
|
|
73
|
+
expect(api.requests.creation.length).toStrictEqual(1);
|
|
51
74
|
expect(api.requests.deletion.count).toStrictEqual(0);
|
|
52
75
|
|
|
53
76
|
api.ws.close();
|
|
54
77
|
expect(api.requests.deletion.count).toStrictEqual(1);
|
|
55
78
|
});
|
|
56
79
|
|
|
80
|
+
it("should error if a given route is not assigned to the user's zone", async () => {
|
|
81
|
+
mockGetZoneFromHostRequest("example.com", "test-zone");
|
|
82
|
+
mockCollectKnownRoutesRequest([]);
|
|
83
|
+
|
|
84
|
+
await expect(runWrangler("tail example.com/*")).rejects.toThrow();
|
|
85
|
+
});
|
|
86
|
+
it("should error if a given route is not within the user's zone", async () => {
|
|
87
|
+
mockGetZoneFromHostRequest("example.com");
|
|
88
|
+
|
|
89
|
+
await expect(runWrangler("tail example.com/*")).rejects.toThrow();
|
|
90
|
+
});
|
|
91
|
+
|
|
57
92
|
it("creates and then delete tails: legacy envs", async () => {
|
|
58
93
|
const api = mockWebsocketAPIs("some-env", true);
|
|
59
|
-
expect(api.requests.creation.
|
|
94
|
+
expect(api.requests.creation.length).toStrictEqual(0);
|
|
60
95
|
|
|
61
96
|
await runWrangler("tail test-worker --env some-env --legacy-env true");
|
|
62
97
|
|
|
63
98
|
await expect(api.ws.connected).resolves.toBeTruthy();
|
|
64
|
-
expect(api.requests.creation.
|
|
99
|
+
expect(api.requests.creation.length).toStrictEqual(1);
|
|
65
100
|
expect(api.requests.deletion.count).toStrictEqual(0);
|
|
66
101
|
|
|
67
102
|
api.ws.close();
|
|
@@ -70,12 +105,12 @@ describe("tail", () => {
|
|
|
70
105
|
|
|
71
106
|
it("creates and then delete tails: service envs", async () => {
|
|
72
107
|
const api = mockWebsocketAPIs("some-env");
|
|
73
|
-
expect(api.requests.creation.
|
|
108
|
+
expect(api.requests.creation.length).toStrictEqual(0);
|
|
74
109
|
|
|
75
110
|
await runWrangler("tail test-worker --env some-env --legacy-env false");
|
|
76
111
|
|
|
77
112
|
await expect(api.ws.connected).resolves.toBeTruthy();
|
|
78
|
-
expect(api.requests.creation.
|
|
113
|
+
expect(api.requests.creation.length).toStrictEqual(1);
|
|
79
114
|
expect(api.requests.deletion.count).toStrictEqual(0);
|
|
80
115
|
|
|
81
116
|
api.ws.close();
|
|
@@ -109,65 +144,57 @@ describe("tail", () => {
|
|
|
109
144
|
await expect(tooLow).rejects.toThrow();
|
|
110
145
|
|
|
111
146
|
await runWrangler("tail test-worker --sampling-rate 0.25");
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
|
|
147
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
148
|
+
`{"filters":[{"sampling_rate":0.25}]}`
|
|
149
|
+
);
|
|
115
150
|
});
|
|
116
151
|
|
|
117
152
|
it("sends single status filters", async () => {
|
|
118
153
|
const api = mockWebsocketAPIs();
|
|
119
154
|
await runWrangler("tail test-worker --status error");
|
|
120
|
-
|
|
121
|
-
{
|
|
122
|
-
|
|
155
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
156
|
+
`{"filters":[{"outcome":["exception","exceededCpu","exceededMemory","unknown"]}]}`
|
|
157
|
+
);
|
|
123
158
|
});
|
|
124
159
|
|
|
125
160
|
it("sends multiple status filters", async () => {
|
|
126
161
|
const api = mockWebsocketAPIs();
|
|
127
162
|
await runWrangler("tail test-worker --status error --status canceled");
|
|
128
|
-
|
|
129
|
-
{
|
|
130
|
-
|
|
131
|
-
"exception",
|
|
132
|
-
"exceededCpu",
|
|
133
|
-
"exceededMemory",
|
|
134
|
-
"unknown",
|
|
135
|
-
"canceled",
|
|
136
|
-
],
|
|
137
|
-
},
|
|
138
|
-
]);
|
|
163
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
164
|
+
`{"filters":[{"outcome":["exception","exceededCpu","exceededMemory","unknown","canceled"]}]}`
|
|
165
|
+
);
|
|
139
166
|
});
|
|
140
167
|
|
|
141
168
|
it("sends single HTTP method filters", async () => {
|
|
142
169
|
const api = mockWebsocketAPIs();
|
|
143
170
|
await runWrangler("tail test-worker --method POST");
|
|
144
|
-
|
|
145
|
-
{
|
|
146
|
-
|
|
171
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
172
|
+
`{"filters":[{"method":["POST"]}]}`
|
|
173
|
+
);
|
|
147
174
|
});
|
|
148
175
|
|
|
149
176
|
it("sends multiple HTTP method filters", async () => {
|
|
150
177
|
const api = mockWebsocketAPIs();
|
|
151
178
|
await runWrangler("tail test-worker --method POST --method GET");
|
|
152
|
-
|
|
153
|
-
{
|
|
154
|
-
|
|
179
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
180
|
+
`{"filters":[{"method":["POST","GET"]}]}`
|
|
181
|
+
);
|
|
155
182
|
});
|
|
156
183
|
|
|
157
184
|
it("sends header filters without a query", async () => {
|
|
158
185
|
const api = mockWebsocketAPIs();
|
|
159
186
|
await runWrangler("tail test-worker --header X-CUSTOM-HEADER");
|
|
160
|
-
|
|
161
|
-
{
|
|
162
|
-
|
|
187
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
188
|
+
`{"filters":[{"header":{"key":"X-CUSTOM-HEADER"}}]}`
|
|
189
|
+
);
|
|
163
190
|
});
|
|
164
191
|
|
|
165
192
|
it("sends header filters with a query", async () => {
|
|
166
193
|
const api = mockWebsocketAPIs();
|
|
167
194
|
await runWrangler("tail test-worker --header X-CUSTOM-HEADER:some-value");
|
|
168
|
-
|
|
169
|
-
{
|
|
170
|
-
|
|
195
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
196
|
+
`{"filters":[{"header":{"key":"X-CUSTOM-HEADER","query":"some-value"}}]}`
|
|
197
|
+
);
|
|
171
198
|
});
|
|
172
199
|
|
|
173
200
|
it("sends single IP filters", async () => {
|
|
@@ -175,9 +202,9 @@ describe("tail", () => {
|
|
|
175
202
|
const fakeIp = "192.0.2.1";
|
|
176
203
|
|
|
177
204
|
await runWrangler(`tail test-worker --ip ${fakeIp}`);
|
|
178
|
-
|
|
179
|
-
{
|
|
180
|
-
|
|
205
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
206
|
+
`{"filters":[{"client_ip":["${fakeIp}"]}]}`
|
|
207
|
+
);
|
|
181
208
|
});
|
|
182
209
|
|
|
183
210
|
it("sends multiple IP filters", async () => {
|
|
@@ -185,9 +212,9 @@ describe("tail", () => {
|
|
|
185
212
|
const fakeIp = "192.0.2.1";
|
|
186
213
|
|
|
187
214
|
await runWrangler(`tail test-worker --ip ${fakeIp} --ip self`);
|
|
188
|
-
|
|
189
|
-
{
|
|
190
|
-
|
|
215
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
216
|
+
`{"filters":[{"client_ip":["${fakeIp}","self"]}]}`
|
|
217
|
+
);
|
|
191
218
|
});
|
|
192
219
|
|
|
193
220
|
it("sends search filters", async () => {
|
|
@@ -195,9 +222,9 @@ describe("tail", () => {
|
|
|
195
222
|
const search = "filterMe";
|
|
196
223
|
|
|
197
224
|
await runWrangler(`tail test-worker --search ${search}`);
|
|
198
|
-
|
|
199
|
-
{
|
|
200
|
-
|
|
225
|
+
expect(api.requests.creation[0].body).toEqual(
|
|
226
|
+
`{"filters":[{"query":"${search}"}]}`
|
|
227
|
+
);
|
|
201
228
|
});
|
|
202
229
|
|
|
203
230
|
it("sends everything but the kitchen sink", async () => {
|
|
@@ -218,30 +245,10 @@ describe("tail", () => {
|
|
|
218
245
|
`--search ${query} ` +
|
|
219
246
|
`--debug`;
|
|
220
247
|
|
|
221
|
-
const expectedWebsocketMessage = {
|
|
222
|
-
filters: [
|
|
223
|
-
{ sampling_rate },
|
|
224
|
-
{
|
|
225
|
-
outcome: [
|
|
226
|
-
"ok",
|
|
227
|
-
"exception",
|
|
228
|
-
"exceededCpu",
|
|
229
|
-
"exceededMemory",
|
|
230
|
-
"unknown",
|
|
231
|
-
],
|
|
232
|
-
},
|
|
233
|
-
{ method },
|
|
234
|
-
{ header: { key: "X-HELLO", query: "world" } },
|
|
235
|
-
{ client_ip },
|
|
236
|
-
{ query },
|
|
237
|
-
],
|
|
238
|
-
debug: true,
|
|
239
|
-
};
|
|
248
|
+
const expectedWebsocketMessage = `{"filters":[{"sampling_rate":0.69},{"outcome":["ok","exception","exceededCpu","exceededMemory","unknown"]},{"method":["GET","POST","PUT"]},{"header":{"key":"X-HELLO","query":"world"}},{"client_ip":["192.0.2.1","self"]},{"query":"onlyTheseMessagesPlease"}]}`;
|
|
240
249
|
|
|
241
250
|
await runWrangler(`tail test-worker ${cliFilters}`);
|
|
242
|
-
|
|
243
|
-
expectedWebsocketMessage
|
|
244
|
-
);
|
|
251
|
+
expect(api.requests.creation[0].body).toEqual(expectedWebsocketMessage);
|
|
245
252
|
});
|
|
246
253
|
});
|
|
247
254
|
|
|
@@ -555,7 +562,7 @@ function deserializeToJson(message: WebSocket.RawData): string {
|
|
|
555
562
|
*/
|
|
556
563
|
type MockAPI = {
|
|
557
564
|
requests: {
|
|
558
|
-
creation:
|
|
565
|
+
creation: RequestInit[];
|
|
559
566
|
deletion: RequestCounter;
|
|
560
567
|
};
|
|
561
568
|
ws: MockWebSocket;
|
|
@@ -581,15 +588,15 @@ function mockCreateTailRequest(
|
|
|
581
588
|
websocketURL: string,
|
|
582
589
|
env?: string,
|
|
583
590
|
legacyEnv = false
|
|
584
|
-
):
|
|
585
|
-
const requests =
|
|
591
|
+
): RequestInit[] {
|
|
592
|
+
const requests: RequestInit[] = [];
|
|
586
593
|
const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
|
|
587
594
|
const environment = env && !legacyEnv ? "/environments/:envName" : "";
|
|
588
595
|
setMockResponse(
|
|
589
596
|
`/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/tails`,
|
|
590
597
|
"POST",
|
|
591
|
-
([_url, accountId, scriptName, envName]) => {
|
|
592
|
-
requests.
|
|
598
|
+
([_url, accountId, scriptName, envName], req) => {
|
|
599
|
+
requests.push(req);
|
|
593
600
|
expect(accountId).toEqual("some-account-id");
|
|
594
601
|
expect(scriptName).toEqual(
|
|
595
602
|
legacyEnv && env ? `test-worker-${env}` : "test-worker"
|
|
@@ -676,7 +683,7 @@ function mockWebsocketAPIs(env?: string, legacyEnv = false): MockAPI {
|
|
|
676
683
|
const api: MockAPI = {
|
|
677
684
|
requests: {
|
|
678
685
|
deletion: { count: 0 },
|
|
679
|
-
creation:
|
|
686
|
+
creation: [],
|
|
680
687
|
},
|
|
681
688
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
682
689
|
ws: null!, // will be set in the `beforeEach()` below.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// this test has to be run with a version of node.js older than 16.
|
|
1
|
+
// this test has to be run with a version of node.js older than 16.13 to pass
|
|
2
2
|
|
|
3
3
|
const { spawn } = require("child_process");
|
|
4
4
|
const path = require("path");
|
|
@@ -11,7 +11,7 @@ const wranglerProcess = spawn(
|
|
|
11
11
|
{ stdio: "pipe" }
|
|
12
12
|
);
|
|
13
13
|
|
|
14
|
-
const messageToMatch = "Wrangler requires at least node.js v16.
|
|
14
|
+
const messageToMatch = "Wrangler requires at least node.js v16.13.0";
|
|
15
15
|
|
|
16
16
|
wranglerProcess.once("exit", (code) => {
|
|
17
17
|
try {
|
|
@@ -25,7 +25,7 @@ wranglerProcess.once("exit", (code) => {
|
|
|
25
25
|
} catch (err) {
|
|
26
26
|
console.error("Error:", err);
|
|
27
27
|
throw new Error(
|
|
28
|
-
"This test has to be run with a version of node.js under 16.
|
|
28
|
+
"This test has to be run with a version of node.js under 16.13 to pass"
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
});
|
|
@@ -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/api/dev.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fetch } from "undici";
|
|
2
|
+
import { startApiDev, startDev } from "../dev";
|
|
2
3
|
import { logger } from "../logger";
|
|
3
4
|
|
|
4
5
|
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
5
6
|
import type { RequestInit, Response } from "undici";
|
|
6
7
|
|
|
7
8
|
interface DevOptions {
|
|
9
|
+
config?: string;
|
|
8
10
|
env?: string;
|
|
9
11
|
ip?: string;
|
|
10
12
|
port?: number;
|
|
@@ -20,7 +22,7 @@ interface DevOptions {
|
|
|
20
22
|
experimentalEnableLocalPersistence?: boolean;
|
|
21
23
|
liveReload?: boolean;
|
|
22
24
|
watch?: boolean;
|
|
23
|
-
vars
|
|
25
|
+
vars?: {
|
|
24
26
|
[key: string]: unknown;
|
|
25
27
|
};
|
|
26
28
|
kv?: {
|
|
@@ -48,46 +50,109 @@ interface DevOptions {
|
|
|
48
50
|
_?: (string | number)[]; //yargs wants this
|
|
49
51
|
$0?: string; //yargs wants this
|
|
50
52
|
}
|
|
53
|
+
|
|
54
|
+
interface DevApiOptions {
|
|
55
|
+
testMode?: boolean;
|
|
56
|
+
disableExperimentalWarning?: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface UnstableDev {
|
|
60
|
+
stop: () => Promise<void>;
|
|
61
|
+
fetch: (init?: RequestInit) => Promise<Response | undefined>;
|
|
62
|
+
waitUntilExit: () => Promise<void>;
|
|
63
|
+
}
|
|
51
64
|
/**
|
|
52
65
|
* unstable_dev starts a wrangler dev server, and returns a promise that resolves with utility functions to interact with it.
|
|
53
66
|
* @param {string} script
|
|
54
67
|
* @param {DevOptions} options
|
|
68
|
+
* @param {DevApiOptions} apiOptions
|
|
69
|
+
* @returns {Promise<UnstableDev>}
|
|
55
70
|
*/
|
|
56
71
|
export async function unstable_dev(
|
|
57
72
|
script: string,
|
|
58
|
-
options
|
|
59
|
-
|
|
73
|
+
options?: DevOptions,
|
|
74
|
+
apiOptions?: DevApiOptions
|
|
60
75
|
) {
|
|
76
|
+
const { testMode = true, disableExperimentalWarning = false } =
|
|
77
|
+
apiOptions || {};
|
|
61
78
|
if (!disableExperimentalWarning) {
|
|
62
79
|
logger.warn(
|
|
63
80
|
`unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases`
|
|
64
81
|
);
|
|
65
82
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
let readyPort: number;
|
|
84
|
+
let readyAddress: string;
|
|
85
|
+
//due to Pages adoption of unstable_dev, we can't *just* disable rebuilds and watching. instead, we'll have two versions of startDev, which will converge.
|
|
86
|
+
if (testMode) {
|
|
87
|
+
//in testMode, we can run multiple wranglers in parallel, but rebuilds might not work out of the box
|
|
88
|
+
return new Promise<UnstableDev>((resolve) => {
|
|
89
|
+
//lmao
|
|
90
|
+
return new Promise<Awaited<ReturnType<typeof startApiDev>>>((ready) => {
|
|
91
|
+
// once the devServer is ready for requests, we resolve the inner promise
|
|
92
|
+
// (where we've named the resolve function "ready")
|
|
93
|
+
const devServer = startApiDev({
|
|
94
|
+
script: script,
|
|
95
|
+
inspect: false,
|
|
96
|
+
logLevel: "none",
|
|
97
|
+
showInteractiveDevSession: false,
|
|
98
|
+
_: [],
|
|
99
|
+
$0: "",
|
|
100
|
+
port: options?.port ?? 0,
|
|
101
|
+
...options,
|
|
102
|
+
local: true,
|
|
103
|
+
onReady: (address, port) => {
|
|
104
|
+
readyPort = port;
|
|
105
|
+
readyAddress = address;
|
|
106
|
+
ready(devServer);
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}).then((devServer) => {
|
|
110
|
+
// now that the inner promise has resolved, we can resolve the outer promise
|
|
111
|
+
// with an object that lets you fetch and stop the dev server
|
|
112
|
+
resolve({
|
|
113
|
+
stop: devServer.stop,
|
|
114
|
+
fetch: async (init?: RequestInit) => {
|
|
115
|
+
const urlToFetch = `http://${readyAddress}:${readyPort}/`;
|
|
116
|
+
return await fetch(urlToFetch, init);
|
|
117
|
+
},
|
|
118
|
+
//no-op, does nothing in tests
|
|
119
|
+
waitUntilExit: async () => {
|
|
120
|
+
return;
|
|
121
|
+
},
|
|
122
|
+
});
|
|
84
123
|
});
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
124
|
+
});
|
|
125
|
+
} else {
|
|
126
|
+
//outside of test mode, rebuilds work fine, but only one instance of wrangler will work at a time
|
|
127
|
+
|
|
128
|
+
return new Promise<UnstableDev>((resolve) => {
|
|
129
|
+
//lmao
|
|
130
|
+
return new Promise<Awaited<ReturnType<typeof startDev>>>((ready) => {
|
|
131
|
+
const devServer = startDev({
|
|
132
|
+
script: script,
|
|
133
|
+
inspect: false,
|
|
134
|
+
logLevel: "none",
|
|
135
|
+
showInteractiveDevSession: false,
|
|
136
|
+
_: [],
|
|
137
|
+
$0: "",
|
|
138
|
+
...options,
|
|
139
|
+
local: true,
|
|
140
|
+
onReady: (address, port) => {
|
|
141
|
+
readyPort = port;
|
|
142
|
+
readyAddress = address;
|
|
143
|
+
ready(devServer);
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}).then((devServer) => {
|
|
147
|
+
resolve({
|
|
148
|
+
stop: devServer.stop,
|
|
149
|
+
fetch: async (init?: RequestInit) => {
|
|
150
|
+
const urlToFetch = `http://${readyAddress}:${readyPort}/`;
|
|
151
|
+
return await fetch(urlToFetch, init);
|
|
152
|
+
},
|
|
153
|
+
waitUntilExit: devServer.devReactElement.waitUntilExit,
|
|
154
|
+
});
|
|
90
155
|
});
|
|
91
156
|
});
|
|
92
|
-
}
|
|
157
|
+
}
|
|
93
158
|
}
|