wrangler 2.0.5 → 2.0.8

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 +335 -86
  7. package/src/__tests__/dev.test.tsx +166 -15
  8. package/src/__tests__/helpers/mock-dialogs.ts +41 -1
  9. package/src/__tests__/index.test.ts +30 -16
  10. package/src/__tests__/init.test.ts +249 -131
  11. package/src/__tests__/kv.test.ts +101 -101
  12. package/src/__tests__/package-manager.test.ts +154 -7
  13. package/src/__tests__/pages.test.ts +369 -39
  14. package/src/__tests__/parse.test.ts +5 -1
  15. package/src/__tests__/publish.test.ts +556 -84
  16. package/src/__tests__/r2.test.ts +47 -24
  17. package/src/__tests__/secret.test.ts +39 -4
  18. package/src/abort.d.ts +3 -0
  19. package/src/bundle.ts +32 -1
  20. package/src/cfetch/index.ts +21 -4
  21. package/src/cfetch/internal.ts +14 -9
  22. package/src/config/environment.ts +40 -14
  23. package/src/config/index.ts +162 -0
  24. package/src/config/validation.ts +179 -64
  25. package/src/create-worker-preview.ts +17 -7
  26. package/src/create-worker-upload-form.ts +22 -8
  27. package/src/dev/dev.tsx +2 -4
  28. package/src/dev/local.tsx +6 -0
  29. package/src/dev/remote.tsx +15 -1
  30. package/src/dialogs.tsx +48 -0
  31. package/src/durable.ts +102 -0
  32. package/src/index.tsx +314 -144
  33. package/src/inspect.ts +39 -0
  34. package/src/kv.ts +77 -13
  35. package/src/open-in-browser.ts +5 -12
  36. package/src/package-manager.ts +50 -3
  37. package/src/pages.tsx +210 -65
  38. package/src/parse.ts +21 -4
  39. package/src/proxy.ts +38 -22
  40. package/src/publish.ts +227 -113
  41. package/src/sites.tsx +11 -9
  42. package/src/worker.ts +8 -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 +35466 -22362
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,12 +127,52 @@ 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
- export function isKVKeyValue(keyValue: object): keyValue is KeyValue {
133
- const props = Object.keys(keyValue);
134
- if (!props.includes("key") || !props.includes("value")) {
165
+ export function isKVKeyValue(keyValue: unknown): keyValue is KeyValue {
166
+ if (
167
+ keyValue === null ||
168
+ typeof keyValue !== "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")
175
+ ) {
135
176
  return false;
136
177
  }
137
178
  return true;
@@ -190,15 +231,37 @@ export async function deleteKVKeyValue(
190
231
  );
191
232
  }
192
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
+
193
256
  export async function putKVBulkKeyValue(
194
257
  accountId: string,
195
258
  namespaceId: string,
196
259
  keyValues: KeyValue[],
197
- progressCallback: (index: number, total: number) => void
260
+ quiet = false
198
261
  ) {
199
262
  for (let index = 0; index < keyValues.length; index += BATCH_KEY_MAX) {
200
- if (progressCallback && keyValues.length > BATCH_KEY_MAX) {
201
- progressCallback(index, keyValues.length);
263
+ if (!quiet && keyValues.length > BATCH_KEY_MAX) {
264
+ logBulkProgress("put", index, keyValues.length);
202
265
  }
203
266
 
204
267
  await fetchResult(
@@ -210,8 +273,9 @@ export async function putKVBulkKeyValue(
210
273
  }
211
274
  );
212
275
  }
213
- if (progressCallback && keyValues.length > BATCH_KEY_MAX) {
214
- progressCallback(keyValues.length, keyValues.length);
276
+
277
+ if (!quiet && keyValues.length > BATCH_KEY_MAX) {
278
+ logBulkProgress("put", keyValues.length, keyValues.length);
215
279
  }
216
280
  }
217
281
 
@@ -219,11 +283,11 @@ export async function deleteKVBulkKeyValue(
219
283
  accountId: string,
220
284
  namespaceId: string,
221
285
  keys: string[],
222
- progressCallback: (index: number, total: number) => void
286
+ quiet = false
223
287
  ) {
224
288
  for (let index = 0; index < keys.length; index += BATCH_KEY_MAX) {
225
- if (progressCallback && keys.length > BATCH_KEY_MAX) {
226
- progressCallback(index, keys.length);
289
+ if (!quiet && keys.length > BATCH_KEY_MAX) {
290
+ logBulkProgress("delete", index, keys.length);
227
291
  }
228
292
 
229
293
  await fetchResult(
@@ -235,8 +299,8 @@ export async function deleteKVBulkKeyValue(
235
299
  }
236
300
  );
237
301
  }
238
- if (progressCallback && keys.length > BATCH_KEY_MAX) {
239
- progressCallback(keys.length, keys.length);
302
+ if (!quiet && keys.length > BATCH_KEY_MAX) {
303
+ logBulkProgress("delete", keys.length, keys.length);
240
304
  }
241
305
  }
242
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
+ }