wrangler 2.0.16 → 2.0.19

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.
Files changed (51) hide show
  1. package/bin/wrangler.js +42 -8
  2. package/miniflare-dist/index.mjs +1 -0
  3. package/package.json +65 -63
  4. package/src/__tests__/configuration.test.ts +11 -7
  5. package/src/__tests__/helpers/run-in-tmp.ts +22 -23
  6. package/src/__tests__/https-options.test.ts +51 -18
  7. package/src/__tests__/index.test.ts +13 -13
  8. package/src/__tests__/jest.setup.ts +13 -0
  9. package/src/__tests__/kv.test.ts +33 -2
  10. package/src/__tests__/metrics.test.ts +415 -0
  11. package/src/__tests__/pages.test.ts +15 -8
  12. package/src/__tests__/publish.test.ts +49 -23
  13. package/src/__tests__/secret.test.ts +84 -78
  14. package/src/__tests__/tail.test.ts +8 -0
  15. package/src/__tests__/test-old-node-version.js +31 -0
  16. package/src/__tests__/user.test.ts +7 -7
  17. package/src/__tests__/whoami.test.tsx +11 -1
  18. package/src/api/dev.ts +4 -1
  19. package/src/cli.ts +1 -1
  20. package/src/config/config.ts +8 -0
  21. package/src/config/validation.ts +9 -0
  22. package/src/config-cache.ts +2 -1
  23. package/src/dev/local.tsx +31 -25
  24. package/src/dev/remote.tsx +2 -2
  25. package/src/dev.tsx +6 -0
  26. package/src/entry.ts +1 -1
  27. package/src/{__tests__/helpers/faye-websocket.d.ts → faye-websocket.d.ts} +0 -0
  28. package/src/global-wrangler-config-path.ts +26 -0
  29. package/src/https-options.ts +8 -4
  30. package/src/index.tsx +120 -22
  31. package/src/kv.ts +23 -1
  32. package/src/metrics/index.ts +4 -0
  33. package/src/metrics/metrics-config.ts +222 -0
  34. package/src/metrics/metrics-dispatcher.ts +93 -0
  35. package/src/metrics/send-event.ts +80 -0
  36. package/src/miniflare-cli/index.ts +1 -0
  37. package/src/package-manager.ts +45 -0
  38. package/src/pages/build.tsx +2 -0
  39. package/src/pages/deployments.tsx +2 -0
  40. package/src/pages/dev.tsx +4 -0
  41. package/src/pages/projects.tsx +3 -0
  42. package/src/pages/publish.tsx +3 -0
  43. package/src/pages/upload.tsx +26 -14
  44. package/src/publish.ts +28 -15
  45. package/src/pubsub/pubsub-commands.tsx +43 -0
  46. package/src/user/user.tsx +29 -20
  47. package/src/worker-namespace.ts +16 -0
  48. package/templates/static-asset-facade.js +11 -5
  49. package/templates/tsconfig.json +2 -2
  50. package/wrangler-dist/cli.d.ts +298 -0
  51. package/wrangler-dist/cli.js +2589 -1659
@@ -0,0 +1,415 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import fetchMock from "jest-fetch-mock";
3
+ import { version as wranglerVersion } from "../../package.json";
4
+ import { purgeConfigCaches, saveToConfigCache } from "../config-cache";
5
+ import { logger } from "../logger";
6
+ import { getMetricsDispatcher, getMetricsConfig } from "../metrics";
7
+ import {
8
+ CURRENT_METRICS_DATE,
9
+ readMetricsConfig,
10
+ USER_ID_CACHE_PATH,
11
+ writeMetricsConfig,
12
+ } from "../metrics/metrics-config";
13
+ import { writeAuthConfigFile } from "../user";
14
+ import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
15
+ import { mockConsoleMethods } from "./helpers/mock-console";
16
+ import { mockConfirm } from "./helpers/mock-dialogs";
17
+ import { useMockIsTTY } from "./helpers/mock-istty";
18
+ import { runInTempDir } from "./helpers/run-in-tmp";
19
+
20
+ declare const global: { SPARROW_SOURCE_KEY: string | undefined };
21
+
22
+ describe("metrics", () => {
23
+ const ORIGINAL_SPARROW_SOURCE_KEY = global.SPARROW_SOURCE_KEY;
24
+ const std = mockConsoleMethods();
25
+ runInTempDir();
26
+
27
+ beforeEach(() => {
28
+ global.SPARROW_SOURCE_KEY = "MOCK_KEY";
29
+ logger.loggerLevel = "debug";
30
+ // Create a node_modules directory to store config-cache files
31
+ mkdirSync("node_modules");
32
+ });
33
+ afterEach(() => {
34
+ global.SPARROW_SOURCE_KEY = ORIGINAL_SPARROW_SOURCE_KEY;
35
+ fetchMock.resetMocks();
36
+ unsetAllMocks();
37
+ purgeConfigCaches();
38
+ });
39
+
40
+ describe("getMetricsDispatcher()", () => {
41
+ const MOCK_DISPATCHER_OPTIONS = {
42
+ // By setting this to true we avoid the `getMetricsConfig()` logic in these tests.
43
+ sendMetrics: true,
44
+ offline: false,
45
+ };
46
+
47
+ // These tests should never hit the `/user` API endpoint.
48
+ const userRequests = mockUserRequest();
49
+ afterEach(() => {
50
+ expect(userRequests.count).toBe(0);
51
+ });
52
+
53
+ describe("identify()", () => {
54
+ it("should send a request to the default URL", async () => {
55
+ const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
56
+ fetchMock.mockResponse("");
57
+ await dispatcher.identify({ a: 1, b: 2 });
58
+ expect(fetchMock).toHaveBeenCalledTimes(1);
59
+ const [url, { body, headers }] = fetchMock.mock.calls[0];
60
+ expect(url).toEqual("https://sparrow.cloudflare.com/api/v1/identify");
61
+ expect(JSON.parse(body)).toEqual(
62
+ expect.objectContaining({
63
+ event: "identify",
64
+ properties: {
65
+ category: "Workers",
66
+ wranglerVersion,
67
+ a: 1,
68
+ b: 2,
69
+ },
70
+ })
71
+ );
72
+ expect(headers).toEqual(
73
+ expect.objectContaining({
74
+ "Sparrow-Source-Key": "MOCK_KEY",
75
+ })
76
+ );
77
+ expect(std.debug).toMatchInlineSnapshot(
78
+ `"Metrics dispatcher: Posting data {\\"type\\":\\"identify\\",\\"name\\":\\"identify\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}"`
79
+ );
80
+ expect(std.out).toMatchInlineSnapshot(`""`);
81
+ expect(std.warn).toMatchInlineSnapshot(`""`);
82
+ expect(std.err).toMatchInlineSnapshot(`""`);
83
+ });
84
+
85
+ it("should write a debug log if the dispatcher is disabled", async () => {
86
+ const dispatcher = await getMetricsDispatcher({
87
+ ...MOCK_DISPATCHER_OPTIONS,
88
+ sendMetrics: false,
89
+ });
90
+ await dispatcher.identify({ a: 1, b: 2 });
91
+ expect(fetchMock).toHaveBeenCalledTimes(0);
92
+ expect(std.debug).toMatchInlineSnapshot(
93
+ `"Metrics dispatcher: Dispatching disabled - would have sent {\\"type\\":\\"identify\\",\\"name\\":\\"identify\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}."`
94
+ );
95
+ expect(std.out).toMatchInlineSnapshot(`""`);
96
+ expect(std.warn).toMatchInlineSnapshot(`""`);
97
+ expect(std.err).toMatchInlineSnapshot(`""`);
98
+ });
99
+
100
+ it("should write a debug log if the request fails", async () => {
101
+ const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
102
+ fetchMock.mockReject(new Error("BAD REQUEST"));
103
+ await dispatcher.identify({ a: 1, b: 2 });
104
+ expect(std.debug).toMatchInlineSnapshot(`
105
+ "Metrics dispatcher: Posting data {\\"type\\":\\"identify\\",\\"name\\":\\"identify\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}
106
+ Metrics dispatcher: Failed to send request: BAD REQUEST"
107
+ `);
108
+ expect(std.out).toMatchInlineSnapshot(`""`);
109
+ expect(std.warn).toMatchInlineSnapshot(`""`);
110
+ expect(std.err).toMatchInlineSnapshot(`""`);
111
+ });
112
+
113
+ it("should write a warning log if no source key has been provided", async () => {
114
+ global.SPARROW_SOURCE_KEY = undefined;
115
+ const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
116
+ await dispatcher.identify({ a: 1, b: 2 });
117
+ expect(fetchMock).toHaveBeenCalledTimes(0);
118
+ expect(std.debug).toMatchInlineSnapshot(
119
+ `"Metrics dispatcher: Source Key not provided. Be sure to initialize before sending events. { type: 'identify', name: 'identify', properties: { a: 1, b: 2 } }"`
120
+ );
121
+ expect(std.out).toMatchInlineSnapshot(`""`);
122
+ expect(std.warn).toMatchInlineSnapshot(`""`);
123
+ expect(std.err).toMatchInlineSnapshot(`""`);
124
+ });
125
+ });
126
+
127
+ describe("sendEvent()", () => {
128
+ it("should send a request to the default URL", async () => {
129
+ const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
130
+ fetchMock.mockResponse("");
131
+ await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
132
+ expect(fetchMock).toHaveBeenCalledTimes(1);
133
+ const [url, { body, headers }] = fetchMock.mock.calls[0];
134
+ expect(url).toEqual("https://sparrow.cloudflare.com/api/v1/event");
135
+ expect(JSON.parse(body)).toEqual(
136
+ expect.objectContaining({
137
+ event: "some-event",
138
+ properties: {
139
+ category: "Workers",
140
+ wranglerVersion,
141
+ a: 1,
142
+ b: 2,
143
+ },
144
+ })
145
+ );
146
+ expect(headers).toEqual(
147
+ expect.objectContaining({
148
+ "Sparrow-Source-Key": "MOCK_KEY",
149
+ })
150
+ );
151
+ expect(std.debug).toMatchInlineSnapshot(
152
+ `"Metrics dispatcher: Posting data {\\"type\\":\\"event\\",\\"name\\":\\"some-event\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}"`
153
+ );
154
+ expect(std.out).toMatchInlineSnapshot(`""`);
155
+ expect(std.warn).toMatchInlineSnapshot(`""`);
156
+ expect(std.err).toMatchInlineSnapshot(`""`);
157
+ });
158
+
159
+ it("should write a debug log if the dispatcher is disabled", async () => {
160
+ const dispatcher = await getMetricsDispatcher({
161
+ ...MOCK_DISPATCHER_OPTIONS,
162
+ sendMetrics: false,
163
+ });
164
+ await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
165
+ expect(fetchMock).toHaveBeenCalledTimes(0);
166
+ expect(std.debug).toMatchInlineSnapshot(
167
+ `"Metrics dispatcher: Dispatching disabled - would have sent {\\"type\\":\\"event\\",\\"name\\":\\"some-event\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}."`
168
+ );
169
+ expect(std.out).toMatchInlineSnapshot(`""`);
170
+ expect(std.warn).toMatchInlineSnapshot(`""`);
171
+ expect(std.err).toMatchInlineSnapshot(`""`);
172
+ });
173
+
174
+ it("should write a debug log if the request fails", async () => {
175
+ const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
176
+ fetchMock.mockReject(new Error("BAD REQUEST"));
177
+ await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
178
+ expect(std.debug).toMatchInlineSnapshot(`
179
+ "Metrics dispatcher: Posting data {\\"type\\":\\"event\\",\\"name\\":\\"some-event\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}
180
+ Metrics dispatcher: Failed to send request: BAD REQUEST"
181
+ `);
182
+ expect(std.out).toMatchInlineSnapshot(`""`);
183
+ expect(std.warn).toMatchInlineSnapshot(`""`);
184
+ expect(std.err).toMatchInlineSnapshot(`""`);
185
+ });
186
+
187
+ it("should write a warning log if no source key has been provided", async () => {
188
+ global.SPARROW_SOURCE_KEY = undefined;
189
+ const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
190
+ await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
191
+ expect(fetchMock).toHaveBeenCalledTimes(0);
192
+ expect(std.debug).toMatchInlineSnapshot(
193
+ `"Metrics dispatcher: Source Key not provided. Be sure to initialize before sending events. { type: 'event', name: 'some-event', properties: { a: 1, b: 2 } }"`
194
+ );
195
+ expect(std.out).toMatchInlineSnapshot(`""`);
196
+ expect(std.warn).toMatchInlineSnapshot(`""`);
197
+ expect(std.err).toMatchInlineSnapshot(`""`);
198
+ });
199
+ });
200
+ });
201
+
202
+ describe("getMetricsConfig()", () => {
203
+ const { setIsTTY } = useMockIsTTY();
204
+ beforeEach(() => {
205
+ // Default the mock TTY to interactive for all these tests.
206
+ setIsTTY(true);
207
+ });
208
+
209
+ describe("enabled", () => {
210
+ it("should return the sendMetrics argument for enabled if it is defined", async () => {
211
+ expect(
212
+ await getMetricsConfig({ sendMetrics: false, offline: false })
213
+ ).toMatchObject({
214
+ enabled: false,
215
+ });
216
+ expect(
217
+ await getMetricsConfig({ sendMetrics: true, offline: false })
218
+ ).toMatchObject({
219
+ enabled: true,
220
+ });
221
+ });
222
+
223
+ it("should return enabled false if the process is not interactive", async () => {
224
+ setIsTTY(false);
225
+ expect(
226
+ await getMetricsConfig({
227
+ sendMetrics: undefined,
228
+ offline: false,
229
+ })
230
+ ).toMatchObject({
231
+ enabled: false,
232
+ });
233
+ });
234
+
235
+ it("should return enabled true if the user on this device previously agreed to send metrics", async () => {
236
+ await writeMetricsConfig({
237
+ permission: {
238
+ enabled: true,
239
+ date: new Date(2022, 6, 4),
240
+ },
241
+ });
242
+ expect(
243
+ await getMetricsConfig({
244
+ sendMetrics: undefined,
245
+ offline: false,
246
+ })
247
+ ).toMatchObject({
248
+ enabled: true,
249
+ });
250
+ });
251
+
252
+ it("should return enabled false if the user on this device previously refused to send metrics", async () => {
253
+ await writeMetricsConfig({
254
+ permission: {
255
+ enabled: false,
256
+ date: new Date(2022, 6, 4),
257
+ },
258
+ });
259
+ expect(
260
+ await getMetricsConfig({
261
+ sendMetrics: undefined,
262
+ offline: false,
263
+ })
264
+ ).toMatchObject({
265
+ enabled: false,
266
+ });
267
+ });
268
+
269
+ it("should accept and store permission granting to send metrics if the user agrees", async () => {
270
+ const checkConfirmations = mockConfirm({
271
+ text: "Would you like to help improve Wrangler by sending usage metrics to Cloudflare?",
272
+ result: true,
273
+ });
274
+ expect(
275
+ await getMetricsConfig({
276
+ sendMetrics: undefined,
277
+ offline: false,
278
+ })
279
+ ).toMatchObject({
280
+ enabled: true,
281
+ });
282
+ checkConfirmations();
283
+ expect((await readMetricsConfig()).permission).toMatchObject({
284
+ enabled: true,
285
+ });
286
+ });
287
+
288
+ it("should accept and store permission declining to send metrics if the user declines", async () => {
289
+ const checkConfirmations = mockConfirm({
290
+ text: "Would you like to help improve Wrangler by sending usage metrics to Cloudflare?",
291
+ result: false,
292
+ });
293
+ expect(
294
+ await getMetricsConfig({
295
+ sendMetrics: undefined,
296
+ offline: false,
297
+ })
298
+ ).toMatchObject({
299
+ enabled: false,
300
+ });
301
+ checkConfirmations();
302
+ expect((await readMetricsConfig()).permission).toMatchObject({
303
+ enabled: false,
304
+ });
305
+ });
306
+
307
+ it("should ignore the config if the permission date is older than the current metrics date", async () => {
308
+ const checkConfirmations = mockConfirm({
309
+ text: "Would you like to help improve Wrangler by sending usage metrics to Cloudflare?",
310
+ result: false,
311
+ });
312
+ const OLD_DATE = new Date(2000);
313
+ await writeMetricsConfig({
314
+ permission: { enabled: true, date: OLD_DATE },
315
+ });
316
+ expect(
317
+ await getMetricsConfig({
318
+ sendMetrics: undefined,
319
+ offline: false,
320
+ })
321
+ ).toMatchObject({
322
+ enabled: false,
323
+ });
324
+ checkConfirmations();
325
+ const { permission } = await readMetricsConfig();
326
+ expect(permission?.enabled).toBe(false);
327
+ // The date should be updated to today's date
328
+ expect(permission?.date).toEqual(CURRENT_METRICS_DATE);
329
+
330
+ expect(std.out).toMatchInlineSnapshot(`
331
+ "Usage metrics tracking has changed since you last granted permission.
332
+ Your choice has been saved in the following file: home/.wrangler/config/metrics.json.
333
+
334
+ You can override the user level setting for a project in \`wrangler.toml\`:
335
+
336
+ - to disable sending metrics for a project: \`send_metrics = false\`
337
+ - to enable sending metrics for a project: \`send_metrics = true\`"
338
+ `);
339
+ });
340
+ });
341
+
342
+ describe("deviceId", () => {
343
+ it("should return a deviceId found in the config file", async () => {
344
+ await writeMetricsConfig({ deviceId: "XXXX-YYYY-ZZZZ" });
345
+ const { deviceId } = await getMetricsConfig({
346
+ sendMetrics: true,
347
+ offline: false,
348
+ });
349
+ expect(deviceId).toEqual("XXXX-YYYY-ZZZZ");
350
+ expect((await readMetricsConfig()).deviceId).toEqual(deviceId);
351
+ });
352
+
353
+ it("should create and store a new deviceId if none is found in the config file", async () => {
354
+ await writeMetricsConfig({});
355
+ const { deviceId } = await getMetricsConfig({
356
+ sendMetrics: true,
357
+ offline: false,
358
+ });
359
+ expect(deviceId).toMatch(
360
+ /[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}/
361
+ );
362
+ expect((await readMetricsConfig()).deviceId).toEqual(deviceId);
363
+ });
364
+ });
365
+
366
+ describe("userId", () => {
367
+ const userRequests = mockUserRequest();
368
+ it("should return a userId found in a cache file", async () => {
369
+ await saveToConfigCache(USER_ID_CACHE_PATH, {
370
+ userId: "CACHED_USER_ID",
371
+ });
372
+ const { userId } = await getMetricsConfig({
373
+ sendMetrics: true,
374
+ offline: false,
375
+ });
376
+ expect(userId).toEqual("CACHED_USER_ID");
377
+ expect(userRequests.count).toBe(0);
378
+ });
379
+
380
+ it("should fetch the userId from Cloudflare and store it in a cache file", async () => {
381
+ writeAuthConfigFile({ oauth_token: "DUMMY_TOKEN" });
382
+ const { userId } = await getMetricsConfig({
383
+ sendMetrics: true,
384
+ offline: false,
385
+ });
386
+ expect(userId).toEqual("MOCK_USER_ID");
387
+ expect(userRequests.count).toBe(1);
388
+ });
389
+
390
+ it("should not fetch the userId from Cloudflare if running in `offline` mode", async () => {
391
+ writeAuthConfigFile({ oauth_token: "DUMMY_TOKEN" });
392
+ const { userId } = await getMetricsConfig({
393
+ sendMetrics: true,
394
+ offline: true,
395
+ });
396
+ expect(userId).toBe(undefined);
397
+ expect(userRequests.count).toBe(0);
398
+ });
399
+ });
400
+ });
401
+ });
402
+
403
+ function mockUserRequest() {
404
+ const requests = { count: 0 };
405
+ beforeEach(() => {
406
+ setMockResponse("/user", () => {
407
+ requests.count++;
408
+ return { id: "MOCK_USER_ID" };
409
+ });
410
+ });
411
+ afterEach(() => {
412
+ requests.count = 0;
413
+ });
414
+ return requests;
415
+ }
@@ -45,6 +45,13 @@ describe("pages", () => {
45
45
  outOfBandTests.forEach((fn) => fn());
46
46
  });
47
47
 
48
+ beforeEach(() => {
49
+ // @ts-expect-error we're using a very simple setTimeout mock here
50
+ jest.spyOn(global, "setTimeout").mockImplementation((fn, _period) => {
51
+ setImmediate(fn);
52
+ });
53
+ });
54
+
48
55
  it("should should display a list of available subcommands, for pages with no subcommand", async () => {
49
56
  await runWrangler("pages");
50
57
  await endEventLoop();
@@ -645,8 +652,8 @@ describe("pages", () => {
645
652
  });
646
653
  bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
647
654
  }
648
- // First bucket should end up with 2 files
649
- expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
655
+ // One bucket should end up with 2 files
656
+ expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
650
657
  // But we don't know the order, so flatten and test without ordering
651
658
  expect(bodies.flatMap((b) => b)).toEqual(
652
659
  expect.arrayContaining([
@@ -759,8 +766,8 @@ describe("pages", () => {
759
766
  });
760
767
  bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
761
768
  }
762
- // First bucket should end up with 2 files
763
- expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
769
+ // One bucket should end up with 2 files
770
+ expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
764
771
  // But we don't know the order, so flatten and test without ordering
765
772
  expect(bodies.flatMap((b) => b)).toEqual(
766
773
  expect.arrayContaining([
@@ -874,8 +881,8 @@ describe("pages", () => {
874
881
  });
875
882
  bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
876
883
  }
877
- // First bucket should end up with 2 files
878
- expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
884
+ // One bucket should end up with 2 files
885
+ expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
879
886
  // But we don't know the order, so flatten and test without ordering
880
887
  expect(bodies.flatMap((b) => b)).toEqual(
881
888
  expect.arrayContaining([
@@ -1163,8 +1170,8 @@ describe("pages", () => {
1163
1170
  });
1164
1171
  bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
1165
1172
  }
1166
- // First bucket should end up with 2 files
1167
- expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
1173
+ // One bucket should end up with 2 files
1174
+ expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
1168
1175
  // But we don't know the order, so flatten and test without ordering
1169
1176
  expect(bodies.flatMap((b) => b)).toEqual(
1170
1177
  expect.arrayContaining([
@@ -29,7 +29,7 @@ import type { FormData, File } from "undici";
29
29
  describe("publish", () => {
30
30
  mockAccountId();
31
31
  mockApiToken();
32
- runInTempDir({ homedir: "./home" });
32
+ runInTempDir();
33
33
  const { setIsTTY } = useMockIsTTY();
34
34
  const std = mockConsoleMethods();
35
35
  const {
@@ -51,6 +51,31 @@ describe("publish", () => {
51
51
  unsetMockFetchKVGetValues();
52
52
  });
53
53
 
54
+ describe("output additional script information", () => {
55
+ mockApiToken();
56
+
57
+ it("should print worker information at log level", async () => {
58
+ setIsTTY(false);
59
+ writeWranglerToml();
60
+ writeWorkerSource();
61
+ mockSubDomainRequest();
62
+ mockUploadWorkerRequest({ expectedType: "esm", sendScriptIds: true });
63
+ mockOAuthServerCallback();
64
+
65
+ await runWrangler("publish ./index");
66
+
67
+ expect(std.out).toMatchInlineSnapshot(`
68
+ "Total Upload: 0xx KiB / gzip: 0xx KiB
69
+ Worker ID: abc12345
70
+ Worker ETag: etag98765
71
+ Worker PipelineHash: hash9999
72
+ Uploaded test-name (TIMINGS)
73
+ Published test-name (TIMINGS)
74
+ test-name.test-sub-domain.workers.dev"
75
+ `);
76
+ });
77
+ });
78
+
54
79
  describe("authentication", () => {
55
80
  mockApiToken({ apiToken: null });
56
81
  beforeEach(() => {
@@ -97,33 +122,23 @@ describe("publish", () => {
97
122
  api_token: "some-api-token",
98
123
  });
99
124
 
100
- const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
101
- mockGrantAuthorization({ respondWith: "success" });
102
-
103
125
  await expect(runWrangler("publish index.js")).resolves.toBeUndefined();
104
126
 
105
- expect(accessTokenRequest.actual.url).toEqual(
106
- accessTokenRequest.expected.url
107
- );
108
-
109
127
  expect(std.out).toMatchInlineSnapshot(`
110
- "Attempting to login via OAuth...
111
- Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
112
- Successfully logged in.
113
- Total Upload: 0xx KiB / gzip: 0xx KiB
114
- Uploaded test-name (TIMINGS)
115
- Published test-name (TIMINGS)
116
- test-name.test-sub-domain.workers.dev"
117
- `);
128
+ "Total Upload: 0xx KiB / gzip: 0xx KiB
129
+ Uploaded test-name (TIMINGS)
130
+ Published test-name (TIMINGS)
131
+ test-name.test-sub-domain.workers.dev"
132
+ `);
118
133
  expect(std.warn).toMatchInlineSnapshot(`
119
- "▲ [WARNING] It looks like you have used Wrangler 1's \`config\` command to login with an API token.
134
+ "▲ [WARNING] It looks like you have used Wrangler 1's \`config\` command to login with an API token.
120
135
 
121
- This is no longer supported in the current version of Wrangler.
122
- If you wish to authenticate via an API token then please set the \`CLOUDFLARE_API_TOKEN\`
123
- environment variable.
136
+ This is no longer supported in the current version of Wrangler.
137
+ If you wish to authenticate via an API token then please set the \`CLOUDFLARE_API_TOKEN\`
138
+ environment variable.
124
139
 
125
- "
126
- `);
140
+ "
141
+ `);
127
142
  expect(std.err).toMatchInlineSnapshot(`""`);
128
143
  });
129
144
 
@@ -6123,6 +6138,7 @@ function mockUploadWorkerRequest(
6123
6138
  expectedMigrations?: CfWorkerInit["migrations"];
6124
6139
  env?: string;
6125
6140
  legacyEnv?: boolean;
6141
+ sendScriptIds?: boolean;
6126
6142
  } = {}
6127
6143
  ) {
6128
6144
  const {
@@ -6137,6 +6153,7 @@ function mockUploadWorkerRequest(
6137
6153
  env = undefined,
6138
6154
  legacyEnv = false,
6139
6155
  expectedMigrations,
6156
+ sendScriptIds,
6140
6157
  } = options;
6141
6158
  setMockResponse(
6142
6159
  env && !legacyEnv
@@ -6185,7 +6202,16 @@ function mockUploadWorkerRequest(
6185
6202
  expect(await (formBody.get(name) as File).text()).toEqual(content);
6186
6203
  }
6187
6204
 
6188
- return { available_on_subdomain };
6205
+ return {
6206
+ available_on_subdomain,
6207
+ ...(sendScriptIds
6208
+ ? {
6209
+ id: "abc12345",
6210
+ etag: "etag98765",
6211
+ pipeline_hash: "hash9999",
6212
+ }
6213
+ : {}),
6214
+ };
6189
6215
  }
6190
6216
  );
6191
6217
  }