wrangler 2.0.6 → 2.0.9

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 (46) hide show
  1. package/README.md +1 -1
  2. package/bin/wrangler.js +16 -4
  3. package/package.json +6 -4
  4. package/pages/functions/buildPlugin.ts +13 -0
  5. package/pages/functions/buildWorker.ts +13 -0
  6. package/src/__tests__/configuration.test.ts +132 -60
  7. package/src/__tests__/dev.test.tsx +168 -67
  8. package/src/__tests__/helpers/mock-dialogs.ts +41 -1
  9. package/src/__tests__/index.test.ts +25 -10
  10. package/src/__tests__/init.test.ts +252 -131
  11. package/src/__tests__/kv.test.ts +16 -16
  12. package/src/__tests__/package-manager.test.ts +154 -7
  13. package/src/__tests__/pages.test.ts +442 -38
  14. package/src/__tests__/parse.test.ts +5 -1
  15. package/src/__tests__/publish.test.ts +377 -84
  16. package/src/__tests__/secret.test.ts +4 -4
  17. package/src/__tests__/whoami.test.tsx +34 -0
  18. package/src/abort.d.ts +3 -0
  19. package/src/cfetch/index.ts +21 -4
  20. package/src/cfetch/internal.ts +20 -18
  21. package/src/config/config.ts +1 -1
  22. package/src/config/index.ts +162 -0
  23. package/src/config/validation.ts +77 -29
  24. package/src/create-worker-preview.ts +32 -22
  25. package/src/dev/dev.tsx +6 -16
  26. package/src/dev/remote.tsx +40 -16
  27. package/src/dialogs.tsx +48 -0
  28. package/src/durable.ts +102 -0
  29. package/src/index.tsx +291 -207
  30. package/src/inspect.ts +39 -0
  31. package/src/kv.ts +74 -25
  32. package/src/open-in-browser.ts +5 -12
  33. package/src/package-manager.ts +50 -3
  34. package/src/pages.tsx +218 -61
  35. package/src/parse.ts +21 -4
  36. package/src/proxy.ts +38 -22
  37. package/src/publish.ts +166 -108
  38. package/src/sites.tsx +8 -8
  39. package/src/user.tsx +12 -1
  40. package/src/whoami.tsx +3 -2
  41. package/src/worker.ts +2 -1
  42. package/src/zones.ts +73 -0
  43. package/templates/new-worker-scheduled.js +17 -0
  44. package/templates/new-worker-scheduled.ts +32 -0
  45. package/templates/new-worker.ts +16 -1
  46. package/wrangler-dist/cli.js +33066 -20052
package/src/inspect.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import assert from "node:assert";
2
2
  import { createServer } from "node:http";
3
+ import os from "node:os";
3
4
  import { URL } from "node:url";
4
5
 
6
+ import open from "open";
5
7
  import { useEffect, useRef, useState } from "react";
6
8
  import WebSocket, { WebSocketServer } from "ws";
7
9
  import { version } from "../package.json";
@@ -621,3 +623,40 @@ function logConsoleMessage(evt: Protocol.Runtime.ConsoleAPICalledEvent): void {
621
623
  logger.warn("console event:", evt);
622
624
  }
623
625
  }
626
+
627
+ /**
628
+ * Opens the chrome debugger
629
+ */
630
+ export const openInspector = async (inspectorPort: number) => {
631
+ const url = `https://built-devtools.pages.dev/js_app?experiments=true&v8only=true&ws=localhost:${inspectorPort}/ws`;
632
+ const errorMessage =
633
+ "Failed to open inspector.\nInspector depends on having a Chromium-based browser installed, maybe you need to install one?";
634
+
635
+ // see: https://github.com/sindresorhus/open/issues/177#issue-610016699
636
+ let braveBrowser: string;
637
+ switch (os.platform()) {
638
+ case "darwin":
639
+ case "win32":
640
+ braveBrowser = "Brave";
641
+ break;
642
+ default:
643
+ braveBrowser = "brave";
644
+ }
645
+
646
+ const childProcess = await open(url, {
647
+ app: [
648
+ {
649
+ name: open.apps.chrome,
650
+ },
651
+ {
652
+ name: braveBrowser,
653
+ },
654
+ {
655
+ name: open.apps.edge,
656
+ },
657
+ ],
658
+ });
659
+ childProcess.on("error", () => {
660
+ logger.warn(errorMessage);
661
+ });
662
+ };
package/src/kv.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { URLSearchParams } from "node:url";
2
2
  import { fetchListResult, fetchResult, fetchKVGetValue } from "./cfetch";
3
+ import { logger } from "./logger";
3
4
  import type { Config } from "./config";
4
5
 
5
6
  /** The largest number of kv items we can pass to the API in a single request. */
@@ -126,26 +127,51 @@ const KeyValueKeys = new Set([
126
127
  "base64",
127
128
  ]);
128
129
 
130
+ /**
131
+ * The object has the specified property.
132
+ */
133
+ function hasProperty<T extends object>(
134
+ obj: object,
135
+ property: keyof T
136
+ ): obj is T {
137
+ return property in obj;
138
+ }
139
+
140
+ /**
141
+ * The object has a required property of the specified type.
142
+ */
143
+ function hasTypedProperty<T extends object>(
144
+ obj: object,
145
+ property: keyof T,
146
+ type: string
147
+ ): obj is T {
148
+ return hasProperty(obj, property) && typeof obj[property] === type;
149
+ }
150
+
151
+ /**
152
+ * The object an optional property, of the specified type.
153
+ */
154
+ function hasOptionalTypedProperty<T extends object>(
155
+ obj: object,
156
+ property: keyof T,
157
+ type: string
158
+ ): obj is Omit<T, typeof property> | T {
159
+ return !hasProperty(obj, property) || typeof obj[property] === type;
160
+ }
161
+
129
162
  /**
130
163
  * Is the given object a valid `KeyValue` type?
131
164
  */
132
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
- export function isKVKeyValue(keyValue: any): keyValue is KeyValue {
134
- // (keyValue could indeed be any-thing)
165
+ export function isKVKeyValue(keyValue: unknown): keyValue is KeyValue {
135
166
  if (
167
+ keyValue === null ||
136
168
  typeof keyValue !== "object" ||
137
- typeof keyValue.key !== "string" ||
138
- typeof keyValue.value !== "string" ||
139
- !(
140
- keyValue.expiration === undefined ||
141
- typeof keyValue.expiration === "number"
142
- ) ||
143
- !(
144
- keyValue.expiration_ttl === undefined ||
145
- typeof keyValue.expiration_ttl === "number"
146
- ) ||
147
- !(keyValue.base64 === undefined || typeof keyValue.base64 === "boolean") ||
148
- !(keyValue.metadata === undefined || typeof keyValue.metadata === "object")
169
+ !hasTypedProperty(keyValue, "key", "string") ||
170
+ !hasTypedProperty(keyValue, "value", "string") ||
171
+ !hasOptionalTypedProperty(keyValue, "expiration", "number") ||
172
+ !hasOptionalTypedProperty(keyValue, "expiration_ttl", "number") ||
173
+ !hasOptionalTypedProperty(keyValue, "base64", "boolean") ||
174
+ !hasOptionalTypedProperty(keyValue, "metadata", "object")
149
175
  ) {
150
176
  return false;
151
177
  }
@@ -205,15 +231,37 @@ export async function deleteKVKeyValue(
205
231
  );
206
232
  }
207
233
 
234
+ /**
235
+ * Formatter for converting e.g. 5328 --> 5,328
236
+ */
237
+ const formatNumber = new Intl.NumberFormat("en-US", {
238
+ notation: "standard",
239
+ }).format;
240
+
241
+ /**
242
+ * Helper function for bulk requests, logs ongoing output to console.
243
+ */
244
+ function logBulkProgress(
245
+ operation: "put" | "delete",
246
+ index: number,
247
+ total: number
248
+ ) {
249
+ logger.log(
250
+ `${operation === "put" ? "Uploaded" : "Deleted"} ${Math.floor(
251
+ (100 * index) / total
252
+ )}% (${formatNumber(index)} out of ${formatNumber(total)})`
253
+ );
254
+ }
255
+
208
256
  export async function putKVBulkKeyValue(
209
257
  accountId: string,
210
258
  namespaceId: string,
211
259
  keyValues: KeyValue[],
212
- progressCallback: (index: number, total: number) => void
260
+ quiet = false
213
261
  ) {
214
262
  for (let index = 0; index < keyValues.length; index += BATCH_KEY_MAX) {
215
- if (progressCallback && keyValues.length > BATCH_KEY_MAX) {
216
- progressCallback(index, keyValues.length);
263
+ if (!quiet && keyValues.length > BATCH_KEY_MAX) {
264
+ logBulkProgress("put", index, keyValues.length);
217
265
  }
218
266
 
219
267
  await fetchResult(
@@ -225,8 +273,9 @@ export async function putKVBulkKeyValue(
225
273
  }
226
274
  );
227
275
  }
228
- if (progressCallback && keyValues.length > BATCH_KEY_MAX) {
229
- progressCallback(keyValues.length, keyValues.length);
276
+
277
+ if (!quiet && keyValues.length > BATCH_KEY_MAX) {
278
+ logBulkProgress("put", keyValues.length, keyValues.length);
230
279
  }
231
280
  }
232
281
 
@@ -234,11 +283,11 @@ export async function deleteKVBulkKeyValue(
234
283
  accountId: string,
235
284
  namespaceId: string,
236
285
  keys: string[],
237
- progressCallback: (index: number, total: number) => void
286
+ quiet = false
238
287
  ) {
239
288
  for (let index = 0; index < keys.length; index += BATCH_KEY_MAX) {
240
- if (progressCallback && keys.length > BATCH_KEY_MAX) {
241
- progressCallback(index, keys.length);
289
+ if (!quiet && keys.length > BATCH_KEY_MAX) {
290
+ logBulkProgress("delete", index, keys.length);
242
291
  }
243
292
 
244
293
  await fetchResult(
@@ -250,8 +299,8 @@ export async function deleteKVBulkKeyValue(
250
299
  }
251
300
  );
252
301
  }
253
- if (progressCallback && keys.length > BATCH_KEY_MAX) {
254
- progressCallback(keys.length, keys.length);
302
+ if (!quiet && keys.length > BATCH_KEY_MAX) {
303
+ logBulkProgress("delete", keys.length, keys.length);
255
304
  }
256
305
  }
257
306
 
@@ -8,19 +8,12 @@ import { logger } from "./logger";
8
8
  * StackBlitz, remote servers), it doesn't just crash the process.
9
9
  *
10
10
  * @param url the URL to point the browser at
11
- * @param options open a Chromium-based browser instead of the default
12
11
  */
13
- export default async function openInBrowser(
14
- url: string,
15
- { forceChromium }: { forceChromium: boolean } = { forceChromium: false }
16
- ): Promise<void> {
17
- const options: open.Options | undefined = forceChromium
18
- ? {
19
- app: [{ name: open.apps.chrome }, { name: open.apps.edge }],
20
- }
21
- : undefined;
22
- const childProcess = await open(url, options);
12
+ export default async function openInBrowser(url: string): Promise<void> {
13
+ const errorMessage = `Failed to open ${url} in a browser`;
14
+
15
+ const childProcess = await open(url);
23
16
  childProcess.on("error", () => {
24
- logger.warn(`Failed to open ${url} in a browser.`);
17
+ logger.warn(errorMessage);
25
18
  });
26
19
  }
@@ -5,15 +5,20 @@ import { logger } from "./logger";
5
5
 
6
6
  export interface PackageManager {
7
7
  cwd: string;
8
- type: "npm" | "yarn";
8
+ type: "npm" | "yarn" | "pnpm";
9
9
  addDevDeps(...packages: string[]): Promise<void>;
10
10
  install(): Promise<void>;
11
11
  }
12
12
 
13
13
  export async function getPackageManager(cwd: string): Promise<PackageManager> {
14
- const [hasYarn, hasNpm] = await Promise.all([supportsYarn(), supportsNpm()]);
14
+ const [hasYarn, hasNpm, hasPnpm] = await Promise.all([
15
+ supportsYarn(),
16
+ supportsNpm(),
17
+ supportsPnpm(),
18
+ ]);
15
19
  const hasYarnLock = existsSync(join(cwd, "yarn.lock"));
16
20
  const hasNpmLock = existsSync(join(cwd, "package-lock.json"));
21
+ const hasPnpmLock = existsSync(join(cwd, "pnpm-lock.yaml"));
17
22
 
18
23
  if (hasNpmLock) {
19
24
  if (hasNpm) {
@@ -28,6 +33,18 @@ export async function getPackageManager(cwd: string): Promise<PackageManager> {
28
33
  );
29
34
  return { ...YarnPackageManager, cwd };
30
35
  }
36
+ } else if (hasPnpmLock) {
37
+ if (hasPnpm) {
38
+ logger.log(
39
+ "Using pnpm as package manager, as there is already a pnpm-lock.yaml file."
40
+ );
41
+ return { ...PnpmPackageManager, cwd };
42
+ } else {
43
+ logger.warn(
44
+ "There is already a pnpm-lock.yaml file but could not find pnpm on the PATH."
45
+ );
46
+ // will simply fallback to the first found of [npm, yaml, pnpm] in the next if round.
47
+ }
31
48
  } else if (hasYarnLock) {
32
49
  if (hasYarn) {
33
50
  logger.log(
@@ -49,9 +66,12 @@ export async function getPackageManager(cwd: string): Promise<PackageManager> {
49
66
  } else if (hasYarn) {
50
67
  logger.log("Using yarn as package manager.");
51
68
  return { ...YarnPackageManager, cwd };
69
+ } else if (hasPnpm) {
70
+ logger.log("Using pnpm as package manager.");
71
+ return { ...PnpmPackageManager, cwd };
52
72
  } else {
53
73
  throw new Error(
54
- "Unable to find a package manager. Supported managers are: npm and yarn."
74
+ "Unable to find a package manager. Supported managers are: npm, yarn, and pnpm."
55
75
  );
56
76
  }
57
77
  }
@@ -86,6 +106,29 @@ const NpmPackageManager: PackageManager = {
86
106
  },
87
107
  };
88
108
 
109
+ /**
110
+ * Manage packages using pnpm
111
+ */
112
+ const PnpmPackageManager: PackageManager = {
113
+ cwd: process.cwd(),
114
+ type: "pnpm",
115
+ /** Add and install a new devDependency into the local package.json. */
116
+ async addDevDeps(...packages: string[]): Promise<void> {
117
+ await execa("pnpm", ["install", ...packages, "--save-dev"], {
118
+ stdio: "inherit",
119
+ cwd: this.cwd,
120
+ });
121
+ },
122
+
123
+ /** Install all the dependencies in the local package.json. */
124
+ async install(): Promise<void> {
125
+ await execa("pnpm", ["install"], {
126
+ stdio: "inherit",
127
+ cwd: this.cwd,
128
+ });
129
+ },
130
+ };
131
+
89
132
  /**
90
133
  * Manage packages using yarn
91
134
  */
@@ -125,3 +168,7 @@ function supportsYarn(): Promise<boolean> {
125
168
  function supportsNpm(): Promise<boolean> {
126
169
  return supports("npm");
127
170
  }
171
+
172
+ function supportsPnpm(): Promise<boolean> {
173
+ return supports("pnpm");
174
+ }