wrangler 0.0.0-e2f9bb2 → 0.0.0-e3278fa

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 (90) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +3 -1
  3. package/bin/wrangler.js +36 -4
  4. package/package.json +12 -7
  5. package/pages/functions/buildPlugin.ts +13 -0
  6. package/pages/functions/buildWorker.ts +14 -1
  7. package/pages/functions/template-plugin.ts +3 -2
  8. package/src/__tests__/configuration.test.ts +370 -87
  9. package/src/__tests__/dev.test.tsx +298 -77
  10. package/src/__tests__/helpers/mock-dialogs.ts +43 -2
  11. package/src/__tests__/index.test.ts +79 -72
  12. package/src/__tests__/init.test.ts +718 -123
  13. package/src/__tests__/jest.setup.ts +8 -0
  14. package/src/__tests__/kv.test.ts +173 -146
  15. package/src/__tests__/package-manager.test.ts +154 -7
  16. package/src/__tests__/pages.test.ts +478 -53
  17. package/src/__tests__/parse.test.ts +8 -0
  18. package/src/__tests__/publish.test.ts +1094 -215
  19. package/src/__tests__/r2.test.ts +55 -36
  20. package/src/__tests__/secret.test.ts +39 -4
  21. package/src/__tests__/whoami.test.tsx +34 -0
  22. package/src/abort.d.ts +3 -0
  23. package/src/bundle.ts +34 -6
  24. package/src/cfetch/index.ts +21 -4
  25. package/src/cfetch/internal.ts +23 -18
  26. package/src/config/config.ts +2 -2
  27. package/src/config/environment.ts +40 -14
  28. package/src/config/index.ts +162 -0
  29. package/src/config/validation-helpers.ts +10 -1
  30. package/src/config/validation.ts +180 -65
  31. package/src/create-worker-preview.ts +32 -22
  32. package/src/create-worker-upload-form.ts +22 -8
  33. package/src/dev/dev.tsx +12 -18
  34. package/src/dev/local.tsx +10 -0
  35. package/src/dev/remote.tsx +40 -16
  36. package/src/dialogs.tsx +48 -0
  37. package/src/durable.ts +102 -0
  38. package/src/entry.ts +64 -9
  39. package/src/index.tsx +548 -317
  40. package/src/inspect.ts +39 -0
  41. package/src/kv.ts +114 -25
  42. package/src/open-in-browser.ts +5 -12
  43. package/src/package-manager.ts +50 -3
  44. package/src/pages.tsx +434 -207
  45. package/src/parse.ts +23 -4
  46. package/src/proxy.ts +59 -35
  47. package/src/publish.ts +374 -127
  48. package/src/sites.tsx +61 -28
  49. package/src/user.tsx +23 -2
  50. package/src/whoami.tsx +3 -2
  51. package/src/worker.ts +10 -1
  52. package/src/zones.ts +73 -0
  53. package/templates/new-worker-scheduled.js +17 -0
  54. package/templates/new-worker-scheduled.ts +32 -0
  55. package/templates/new-worker.ts +16 -1
  56. package/templates/static-asset-facade.js +0 -4
  57. package/wrangler-dist/cli.js +96965 -83414
  58. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  59. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  60. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  61. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  62. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  63. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  64. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  65. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  66. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  67. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  68. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  69. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  70. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  71. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  72. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  73. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  74. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  75. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  76. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  77. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  78. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  79. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  80. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  81. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  82. package/vendor/wrangler-mime/LICENSE +0 -21
  83. package/vendor/wrangler-mime/Mime.js +0 -97
  84. package/vendor/wrangler-mime/README.md +0 -187
  85. package/vendor/wrangler-mime/cli.js +0 -46
  86. package/vendor/wrangler-mime/index.js +0 -4
  87. package/vendor/wrangler-mime/lite.js +0 -4
  88. package/vendor/wrangler-mime/package.json +0 -52
  89. package/vendor/wrangler-mime/types/other.js +0 -1
  90. package/vendor/wrangler-mime/types/standard.js +0 -1
package/src/parse.ts CHANGED
@@ -62,8 +62,6 @@ export class ParseError extends Error implements Message {
62
62
  }
63
63
  }
64
64
 
65
- /* eslint-disable @typescript-eslint/no-explicit-any */
66
-
67
65
  const TOML_ERROR_NAME = "TomlError";
68
66
  const TOML_ERROR_SUFFIX = " at row ";
69
67
 
@@ -77,7 +75,9 @@ type TomlError = Error & {
77
75
  */
78
76
  export function parseTOML(input: string, file?: string): TOML.JsonMap | never {
79
77
  try {
80
- return TOML.parse(input);
78
+ // Normalize CRLF to LF to avoid hitting https://github.com/iarna/iarna-toml/issues/33.
79
+ const normalizedInput = input.replace(/\r\n/g, "\n");
80
+ return TOML.parse(normalizedInput);
81
81
  } catch (err) {
82
82
  const { name, message, line, col } = err as TomlError;
83
83
  if (name !== TOML_ERROR_NAME) {
@@ -98,10 +98,29 @@ export function parseTOML(input: string, file?: string): TOML.JsonMap | never {
98
98
 
99
99
  const JSON_ERROR_SUFFIX = " in JSON at position ";
100
100
 
101
+ /**
102
+ * A minimal type describing a package.json file.
103
+ */
104
+ export type PackageJSON = {
105
+ devDependencies?: Record<string, unknown>;
106
+ dependencies?: Record<string, unknown>;
107
+ scripts?: Record<string, unknown>;
108
+ };
109
+
110
+ /**
111
+ * A typed version of `parseJSON()`.
112
+ */
113
+ export function parsePackageJSON<T extends PackageJSON = PackageJSON>(
114
+ input: string,
115
+ file?: string
116
+ ): T {
117
+ return parseJSON<T>(input, file);
118
+ }
119
+
101
120
  /**
102
121
  * A wrapper around `JSON.parse` that throws a `ParseError`.
103
122
  */
104
- export function parseJSON(input: string, file?: string): any {
123
+ export function parseJSON<T>(input: string, file?: string): T {
105
124
  try {
106
125
  return JSON.parse(input);
107
126
  } catch (err) {
package/src/proxy.ts CHANGED
@@ -2,11 +2,13 @@ import { createServer as createHttpServer } from "node:http";
2
2
  import { connect } from "node:http2";
3
3
  import { createServer as createHttpsServer } from "node:https";
4
4
  import WebSocket from "faye-websocket";
5
+ import { createHttpTerminator } from "http-terminator";
5
6
  import { useEffect, useRef, useState } from "react";
6
7
  import serveStatic from "serve-static";
7
8
  import { getHttpsOptions } from "./https-options";
8
9
  import { logger } from "./logger";
9
10
  import type { CfPreviewToken } from "./create-worker-preview";
11
+ import type { HttpTerminator } from "http-terminator";
10
12
  import type {
11
13
  IncomingHttpHeaders,
12
14
  RequestListener,
@@ -67,6 +69,11 @@ function rewriteRemoteHostToLocalHostInHeaders(
67
69
  }
68
70
  }
69
71
 
72
+ type PreviewProxy = {
73
+ server: HttpServer | HttpsServer;
74
+ terminator: HttpTerminator;
75
+ };
76
+
70
77
  export function usePreviewServer({
71
78
  previewToken,
72
79
  publicRoot,
@@ -81,21 +88,29 @@ export function usePreviewServer({
81
88
  ip: string;
82
89
  }) {
83
90
  /** Creates an HTTP/1 proxy that sends requests over HTTP/2. */
84
- const [proxyServer, setProxyServer] = useState<HttpServer | HttpsServer>();
91
+ const [proxy, setProxy] = useState<PreviewProxy>();
85
92
 
86
93
  /**
87
94
  * Create the instance of the local proxy server that will pass on
88
95
  * requests to the preview worker.
89
96
  */
90
97
  useEffect(() => {
91
- if (proxyServer === undefined) {
98
+ if (proxy === undefined) {
92
99
  createProxyServer(localProtocol)
93
- .then((proxy) => setProxyServer(proxy))
100
+ .then((server) => {
101
+ setProxy({
102
+ server,
103
+ terminator: createHttpTerminator({
104
+ server,
105
+ gracefulTerminationTimeout: 0,
106
+ }),
107
+ });
108
+ })
94
109
  .catch(async (err) => {
95
110
  logger.error("Failed to create proxy server:", err);
96
111
  });
97
112
  }
98
- }, [proxyServer, localProtocol]);
113
+ }, [proxy, localProtocol]);
99
114
 
100
115
  /**
101
116
  * When we're not connected / getting a fresh token on changes,
@@ -123,7 +138,7 @@ export function usePreviewServer({
123
138
  }
124
139
 
125
140
  useEffect(() => {
126
- if (proxyServer === undefined) {
141
+ if (proxy === undefined) {
127
142
  return;
128
143
  }
129
144
 
@@ -138,8 +153,8 @@ export function usePreviewServer({
138
153
  // store the stream in a buffer so we can replay it later
139
154
  streamBufferRef.current.push({ stream, headers });
140
155
  };
141
- proxyServer.on("stream", bufferStream);
142
- cleanupListeners.push(() => proxyServer.off("stream", bufferStream));
156
+ proxy.server.on("stream", bufferStream);
157
+ cleanupListeners.push(() => proxy.server.off("stream", bufferStream));
143
158
 
144
159
  const bufferRequestResponse = (
145
160
  request: IncomingMessage,
@@ -149,9 +164,9 @@ export function usePreviewServer({
149
164
  requestResponseBufferRef.current.push({ request, response });
150
165
  };
151
166
 
152
- proxyServer.on("request", bufferRequestResponse);
167
+ proxy.server.on("request", bufferRequestResponse);
153
168
  cleanupListeners.push(() =>
154
- proxyServer.off("request", bufferRequestResponse)
169
+ proxy.server.off("request", bufferRequestResponse)
155
170
  );
156
171
  return () => {
157
172
  cleanupListeners.forEach((cleanup) => cleanup());
@@ -179,8 +194,8 @@ export function usePreviewServer({
179
194
  port,
180
195
  localProtocol
181
196
  );
182
- proxyServer.on("stream", handleStream);
183
- cleanupListeners.push(() => proxyServer.off("stream", handleStream));
197
+ proxy.server.on("stream", handleStream);
198
+ cleanupListeners.push(() => proxy.server.off("stream", handleStream));
184
199
 
185
200
  // flush and replay buffered streams
186
201
  streamBufferRef.current.forEach((buffer) =>
@@ -210,6 +225,10 @@ export function usePreviewServer({
210
225
  const request = message.pipe(remote.request(headers));
211
226
  request.on("response", (responseHeaders) => {
212
227
  const status = responseHeaders[":status"] ?? 500;
228
+
229
+ // log all requests to terminal
230
+ logger.log(new Date().toLocaleTimeString(), method, url, status);
231
+
213
232
  rewriteRemoteHostToLocalHostInHeaders(
214
233
  responseHeaders,
215
234
  previewToken.host,
@@ -232,9 +251,9 @@ export function usePreviewServer({
232
251
  ? createHandleAssetsRequest(assetPath, handleRequest)
233
252
  : handleRequest;
234
253
 
235
- proxyServer.on("request", actualHandleRequest);
254
+ proxy.server.on("request", actualHandleRequest);
236
255
  cleanupListeners.push(() =>
237
- proxyServer.off("request", actualHandleRequest)
256
+ proxy.server.off("request", actualHandleRequest)
238
257
  );
239
258
 
240
259
  // flush and replay buffered requests
@@ -266,8 +285,8 @@ export function usePreviewServer({
266
285
  remoteWebsocketClient.close();
267
286
  });
268
287
  };
269
- proxyServer.on("upgrade", handleUpgrade);
270
- cleanupListeners.push(() => proxyServer.off("upgrade", handleUpgrade));
288
+ proxy.server.on("upgrade", handleUpgrade);
289
+ cleanupListeners.push(() => proxy.server.off("upgrade", handleUpgrade));
271
290
 
272
291
  return () => {
273
292
  cleanupListeners.forEach((cleanup) => cleanup());
@@ -277,7 +296,7 @@ export function usePreviewServer({
277
296
  publicRoot,
278
297
  port,
279
298
  localProtocol,
280
- proxyServer,
299
+ proxy,
281
300
  // We use a state value as a sigil to trigger reconnecting the server.
282
301
  // It's not used inside the effect, so react-hooks/exhaustive-deps
283
302
  // doesn't complain if it's not included in the dependency array.
@@ -289,7 +308,7 @@ export function usePreviewServer({
289
308
  // containing component is mounted/unmounted.
290
309
  useEffect(() => {
291
310
  const abortController = new AbortController();
292
- if (proxyServer === undefined) {
311
+ if (proxy === undefined) {
293
312
  return;
294
313
  }
295
314
 
@@ -299,8 +318,10 @@ export function usePreviewServer({
299
318
  abortSignal: abortController.signal,
300
319
  })
301
320
  .then(() => {
302
- proxyServer.listen(port, ip);
303
- logger.log(`⬣ Listening at ${localProtocol}://${ip}:${port}`);
321
+ proxy.server.on("listening", () => {
322
+ logger.log(`⬣ Listening at ${localProtocol}://${ip}:${port}`);
323
+ });
324
+ proxy.server.listen(port, ip);
304
325
  })
305
326
  .catch((err) => {
306
327
  if ((err as { code: string }).code !== "ABORT_ERR") {
@@ -309,10 +330,14 @@ export function usePreviewServer({
309
330
  });
310
331
 
311
332
  return () => {
312
- proxyServer.close();
313
333
  abortController.abort();
334
+ // Running `proxy.server.close()` does not close open connections, preventing the process from exiting.
335
+ // So we use this `terminator` to close all the connections and force the server to shutdown.
336
+ proxy.terminator
337
+ .terminate()
338
+ .catch(() => logger.error("Failed to terminate the proxy server."));
314
339
  };
315
- }, [port, ip, proxyServer, localProtocol]);
340
+ }, [port, ip, proxy, localProtocol]);
316
341
  }
317
342
 
318
343
  function createHandleAssetsRequest(
@@ -349,15 +374,6 @@ async function createProxyServer(
349
374
  : createHttpServer();
350
375
 
351
376
  return server
352
- .on("request", function (req, res) {
353
- // log all requests
354
- logger.log(
355
- new Date().toLocaleTimeString(),
356
- req.method,
357
- req.url,
358
- res.statusCode
359
- );
360
- })
361
377
  .on("upgrade", (req) => {
362
378
  // log all websocket connections
363
379
  logger.log(
@@ -409,7 +425,7 @@ export async function waitForPortToBeAvailable(
409
425
  ): Promise<void> {
410
426
  return new Promise((resolve, reject) => {
411
427
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
412
- (options.abortSignal as any).addEventListener("abort", () => {
428
+ options.abortSignal.addEventListener("abort", () => {
413
429
  const abortError = new Error("waitForPortToBeAvailable() aborted");
414
430
  (abortError as Error & { code: string }).code = "ABORT_ERR";
415
431
  doReject(abortError);
@@ -439,16 +455,24 @@ export async function waitForPortToBeAvailable(
439
455
  // trying to make a server listen on that port, and retrying
440
456
  // until it succeeds.
441
457
  const server = createHttpServer();
458
+ const terminator = createHttpTerminator({
459
+ server,
460
+ gracefulTerminationTimeout: 0, // default 1000
461
+ });
462
+
442
463
  server.on("error", (err) => {
443
464
  // @ts-expect-error non standard property on Error
444
465
  if (err.code !== "EADDRINUSE") {
445
466
  doReject(err);
446
467
  }
447
468
  });
448
- server.listen(port, () => {
449
- server.close();
450
- doResolve();
451
- });
469
+ server.listen(port, () =>
470
+ terminator
471
+ .terminate()
472
+ .then(doResolve, () =>
473
+ logger.error("Failed to terminate the port checker.")
474
+ )
475
+ );
452
476
  }
453
477
  });
454
478
  }