wrangler 0.0.0-e2a26a0 → 0.0.0-e3cab74

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 (68) hide show
  1. package/package.json +16 -7
  2. package/pages/functions/filepath-routing.test.ts +112 -36
  3. package/pages/functions/filepath-routing.ts +66 -119
  4. package/pages/functions/routes.ts +8 -17
  5. package/pages/functions/template-worker.ts +3 -9
  6. package/src/__tests__/configuration.test.ts +2185 -0
  7. package/src/__tests__/dev.test.tsx +48 -6
  8. package/src/__tests__/guess-worker-format.test.ts +66 -0
  9. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  10. package/src/__tests__/helpers/mock-account-id.ts +6 -6
  11. package/src/__tests__/helpers/mock-bin.ts +4 -1
  12. package/src/__tests__/helpers/mock-cfetch.ts +2 -2
  13. package/src/__tests__/helpers/mock-console.ts +11 -5
  14. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  15. package/src/__tests__/helpers/run-wrangler.ts +5 -3
  16. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  17. package/src/__tests__/index.test.ts +343 -20
  18. package/src/__tests__/jest.setup.ts +21 -1
  19. package/src/__tests__/kv.test.ts +82 -80
  20. package/src/__tests__/package-manager.test.ts +2 -2
  21. package/src/__tests__/parse.test.ts +322 -0
  22. package/src/__tests__/publish.test.ts +1428 -244
  23. package/src/__tests__/r2.test.ts +198 -0
  24. package/src/__tests__/secret.test.ts +176 -60
  25. package/src/__tests__/sentry.test.ts +146 -0
  26. package/src/__tests__/tail.test.ts +564 -0
  27. package/src/api/form_data.ts +106 -23
  28. package/src/api/preview.ts +32 -13
  29. package/src/api/worker.ts +49 -18
  30. package/src/bundle.ts +133 -0
  31. package/src/cfetch/index.ts +8 -6
  32. package/src/cfetch/internal.ts +49 -17
  33. package/src/cli.ts +10 -0
  34. package/src/config/README.md +107 -0
  35. package/src/config/config.ts +265 -0
  36. package/src/config/diagnostics.ts +80 -0
  37. package/src/config/environment.ts +305 -0
  38. package/src/config/index.ts +52 -0
  39. package/src/config/validation-helpers.ts +370 -0
  40. package/src/config/validation.ts +1017 -0
  41. package/src/dev.tsx +338 -211
  42. package/src/entry.ts +57 -0
  43. package/src/environment-variables.ts +33 -0
  44. package/src/guess-worker-format.ts +68 -0
  45. package/src/index.tsx +860 -634
  46. package/src/inspect.ts +16 -3
  47. package/src/kv.tsx +20 -29
  48. package/src/module-collection.ts +141 -34
  49. package/src/open-in-browser.ts +13 -0
  50. package/src/package-manager.ts +21 -15
  51. package/src/pages.tsx +9 -10
  52. package/src/parse.ts +183 -0
  53. package/src/proxy.ts +11 -5
  54. package/src/publish.ts +272 -314
  55. package/src/r2.ts +50 -0
  56. package/src/reporting.ts +115 -0
  57. package/src/sites.tsx +16 -15
  58. package/src/tail/filters.ts +279 -0
  59. package/src/tail/index.ts +299 -0
  60. package/src/tail/printing.ts +62 -0
  61. package/src/user.tsx +74 -44
  62. package/templates/new-worker.js +1 -1
  63. package/templates/new-worker.ts +1 -1
  64. package/templates/tsconfig.json +105 -0
  65. package/wrangler-dist/cli.js +51308 -36440
  66. package/wrangler-dist/cli.js.map +3 -3
  67. package/src/config.ts +0 -641
  68. package/src/tail.tsx +0 -73
@@ -2,14 +2,20 @@ import { render } from "ink-testing-library";
2
2
  import patchConsole from "patch-console";
3
3
  import React from "react";
4
4
  import Dev from "../dev";
5
+ import { mockConsoleMethods } from "./helpers/mock-console";
6
+ import { runWrangler } from "./helpers/run-wrangler";
7
+ import writeWranglerToml from "./helpers/write-wrangler-toml";
5
8
  import type { DevProps } from "../dev";
6
9
 
7
10
  describe("Dev component", () => {
8
- let restoreConsole;
11
+ let restoreConsole: ReturnType<typeof patchConsole>;
9
12
  beforeEach(() => (restoreConsole = patchConsole(() => {})));
10
13
  afterEach(() => restoreConsole());
14
+ const std = mockConsoleMethods();
11
15
 
12
- it("should throw if format is service-worker and there is a public directory", () => {
16
+ // This test needs to be rewritten because the error now throws asynchronously
17
+ // and the Ink framework does not yet have async testing support.
18
+ it.skip("should throw if format is service-worker and there is a public directory", () => {
13
19
  const { lastFrame } = renderDev({
14
20
  format: "service-worker",
15
21
  accountId: "some-account-id",
@@ -21,6 +27,26 @@ describe("Dev component", () => {
21
27
  Error: You cannot use the service worker format with a \`public\` directory."
22
28
  `);
23
29
  });
30
+
31
+ describe("entry-points", () => {
32
+ it("should error if there is no entry-point specified", async () => {
33
+ writeWranglerToml();
34
+
35
+ await expect(
36
+ runWrangler("dev")
37
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
38
+ `"Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler dev path/to/script\`) or the \`main\` config field."`
39
+ );
40
+
41
+ expect(std.out).toMatchInlineSnapshot(`""`);
42
+ expect(std.err).toMatchInlineSnapshot(`
43
+ "Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler dev path/to/script\`) or the \`main\` config field.
44
+
45
+ %s
46
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
47
+ `);
48
+ });
49
+ });
24
50
  });
25
51
 
26
52
  /**
@@ -30,14 +56,25 @@ describe("Dev component", () => {
30
56
  */
31
57
  function renderDev({
32
58
  name,
33
- entry = "some/entry.ts",
59
+ entry = { file: "some/entry.ts", directory: process.cwd() },
34
60
  port,
61
+ inspectorPort = 9229,
35
62
  format,
36
63
  accountId,
37
- initialMode = "remote",
64
+ legacyEnv = true,
65
+ initialMode = "local",
38
66
  jsxFactory,
39
67
  jsxFragment,
40
- bindings = {},
68
+ rules = [],
69
+ bindings = {
70
+ kv_namespaces: [],
71
+ vars: {},
72
+ durable_objects: { bindings: [] },
73
+ r2_buckets: [],
74
+ wasm_modules: {},
75
+ text_blobs: {},
76
+ unsafe: [],
77
+ },
41
78
  public: publicDir,
42
79
  assetPaths,
43
80
  compatibilityDate,
@@ -45,14 +82,18 @@ function renderDev({
45
82
  usageModel,
46
83
  buildCommand = {},
47
84
  enableLocalPersistence = false,
48
- env = undefined,
85
+ env,
86
+ zone,
49
87
  }: Partial<DevProps>) {
50
88
  return render(
51
89
  <Dev
52
90
  name={name}
53
91
  entry={entry}
54
92
  env={env}
93
+ rules={rules}
55
94
  port={port}
95
+ inspectorPort={inspectorPort}
96
+ legacyEnv={legacyEnv}
56
97
  buildCommand={buildCommand}
57
98
  format={format}
58
99
  initialMode={initialMode}
@@ -66,6 +107,7 @@ function renderDev({
66
107
  usageModel={usageModel}
67
108
  bindings={bindings}
68
109
  enableLocalPersistence={enableLocalPersistence}
110
+ zone={zone}
69
111
  />
70
112
  );
71
113
  }
@@ -0,0 +1,66 @@
1
+ import { writeFile } from "fs/promises";
2
+ import path from "path";
3
+ import guessWorkerFormat from "../guess-worker-format";
4
+ import { runInTempDir } from "./helpers/run-in-tmp";
5
+
6
+ describe("guess worker format", () => {
7
+ runInTempDir();
8
+ it('should detect a "modules" worker', async () => {
9
+ await writeFile("./index.ts", "export default {};");
10
+ // Note that this isn't actually a valid worker, because it's missing
11
+ // a fetch handler. Regardless, our heuristic is simply to check for exports.
12
+ const guess = await guessWorkerFormat(
13
+ {
14
+ file: path.join(process.cwd(), "./index.ts"),
15
+ directory: process.cwd(),
16
+ },
17
+ undefined
18
+ );
19
+ expect(guess).toBe("modules");
20
+ });
21
+
22
+ it('should detect a "service-worker" worker', async () => {
23
+ await writeFile("./index.ts", "");
24
+ // Note that this isn't actually a valid worker, because it's missing
25
+ // a fetch listener. Regardless, our heuristic is simply to check for
26
+ // the lack of exports.
27
+ const guess = await guessWorkerFormat(
28
+ {
29
+ file: path.join(process.cwd(), "./index.ts"),
30
+ directory: process.cwd(),
31
+ },
32
+ undefined
33
+ );
34
+ expect(guess).toBe("service-worker");
35
+ });
36
+
37
+ it("should throw an error when the hint doesn't match the guess (modules - service-worker)", async () => {
38
+ await writeFile("./index.ts", "export default {};");
39
+ await expect(
40
+ guessWorkerFormat(
41
+ {
42
+ file: path.join(process.cwd(), "./index.ts"),
43
+ directory: process.cwd(),
44
+ },
45
+ "service-worker"
46
+ )
47
+ ).rejects.toThrow(
48
+ "You configured this worker to be a 'service-worker', but the file you are trying to build appears to have ES module exports. Please pass `--format modules`, or simply remove the configuration."
49
+ );
50
+ });
51
+
52
+ it("should throw an error when the hint doesn't match the guess (service-worker - modules)", async () => {
53
+ await writeFile("./index.ts", "");
54
+ await expect(
55
+ guessWorkerFormat(
56
+ {
57
+ file: path.join(process.cwd(), "./index.ts"),
58
+ directory: process.cwd(),
59
+ },
60
+ "modules"
61
+ )
62
+ ).rejects.toThrow(
63
+ "You configured this worker to be 'modules', but the file you are trying to build doesn't export a handler. Please pass `--format service-worker`, or simply remove the configuration."
64
+ );
65
+ });
66
+ });
@@ -0,0 +1,6 @@
1
+ module "faye-websocket" {
2
+ /**
3
+ * Standards-compliant WebSocket client and server.
4
+ */
5
+ export default WebSocket;
6
+ }
@@ -1,5 +1,5 @@
1
- const ORIGINAL_CF_API_TOKEN = process.env.CF_API_TOKEN;
2
- const ORIGINAL_CF_ACCOUNT_ID = process.env.CF_ACCOUNT_ID;
1
+ const ORIGINAL_CLOUDFLARE_API_TOKEN = process.env.CLOUDFLARE_API_TOKEN;
2
+ const ORIGINAL_CLOUDFLARE_ACCOUNT_ID = process.env.CLOUDFLARE_ACCOUNT_ID;
3
3
 
4
4
  /**
5
5
  * Mock the API token so that we don't need to read it from user configuration files.
@@ -8,10 +8,10 @@ export function mockApiToken({
8
8
  apiToken = "some-api-token",
9
9
  }: { apiToken?: string } = {}) {
10
10
  beforeEach(() => {
11
- process.env.CF_API_TOKEN = apiToken;
11
+ process.env.CLOUDFLARE_API_TOKEN = apiToken;
12
12
  });
13
13
  afterEach(() => {
14
- process.env.CF_API_TOKEN = ORIGINAL_CF_API_TOKEN;
14
+ process.env.CLOUDFLARE_API_TOKEN = ORIGINAL_CLOUDFLARE_API_TOKEN;
15
15
  });
16
16
  }
17
17
 
@@ -22,9 +22,9 @@ export function mockAccountId({
22
22
  accountId = "some-account-id",
23
23
  }: { accountId?: string } = {}) {
24
24
  beforeEach(() => {
25
- process.env.CF_ACCOUNT_ID = accountId;
25
+ process.env.CLOUDFLARE_ACCOUNT_ID = accountId;
26
26
  });
27
27
  afterEach(() => {
28
- process.env.CF_ACCOUNT_ID = ORIGINAL_CF_ACCOUNT_ID;
28
+ process.env.CLOUDFLARE_ACCOUNT_ID = ORIGINAL_CLOUDFLARE_ACCOUNT_ID;
29
29
  });
30
30
  }
@@ -7,7 +7,10 @@ const nodeShebang = "#!/usr/bin/env node";
7
7
  /**
8
8
  * Create a binary file in a temp directory and make it available on the PATH.
9
9
  */
10
- export async function mockBinary(binaryName: string, code: string) {
10
+ export async function mockBinary(
11
+ binaryName: string,
12
+ code: string
13
+ ): Promise<() => void> {
11
14
  // Ensure there is a directory to put the mock binary in.
12
15
  const tmpDir = resolve(mkdtempSync(".mock-binary-"));
13
16
 
@@ -1,6 +1,6 @@
1
1
  import { URL, URLSearchParams } from "node:url";
2
2
  import { pathToRegexp } from "path-to-regexp";
3
- import { CF_API_BASE_URL } from "../../cfetch";
3
+ import { getCloudflareApiBaseUrl } from "../../cfetch";
4
4
  import type { FetchResult } from "../../cfetch";
5
5
  import type { RequestInit } from "undici";
6
6
 
@@ -35,7 +35,7 @@ export async function mockFetchInternal(
35
35
  queryParams: URLSearchParams = new URLSearchParams()
36
36
  ) {
37
37
  for (const { regexp, method, handler } of mocks) {
38
- const resourcePath = new URL(resource, CF_API_BASE_URL).pathname;
38
+ const resourcePath = new URL(resource, getCloudflareApiBaseUrl()).pathname;
39
39
  const uri = regexp.exec(resourcePath);
40
40
  // Do the resource path and (if specified) the HTTP method match?
41
41
  if (uri !== null && (!method || method === (init.method ?? "GET"))) {
@@ -9,16 +9,18 @@ let logSpy: jest.SpyInstance,
9
9
 
10
10
  const std = {
11
11
  get out() {
12
- return normalizeSlashes(stripTimings(logSpy.mock.calls.flat(2).join("\n")));
12
+ return stripTrailingWhitespace(
13
+ normalizeSlashes(stripTimings(logSpy.mock.calls.flat(2).join("\n")))
14
+ );
13
15
  },
14
16
  get err() {
15
- return normalizeSlashes(
16
- stripTimings(errorSpy.mock.calls.flat(2).join("\n"))
17
+ return stripTrailingWhitespace(
18
+ normalizeSlashes(stripTimings(errorSpy.mock.calls.flat(2).join("\n")))
17
19
  );
18
20
  },
19
21
  get warn() {
20
- return normalizeSlashes(
21
- stripTimings(warnSpy.mock.calls.flat(2).join("\n"))
22
+ return stripTrailingWhitespace(
23
+ normalizeSlashes(stripTimings(warnSpy.mock.calls.flat(2).join("\n")))
22
24
  );
23
25
  },
24
26
  };
@@ -54,3 +56,7 @@ export function normalizeSlashes(str: string): string {
54
56
  export function stripTimings(stdout: string): string {
55
57
  return stdout.replace(/\(\d+\.\d+ sec\)/g, "(TIMINGS)");
56
58
  }
59
+
60
+ export function stripTrailingWhitespace(str: string): string {
61
+ return str.replace(/[^\S\n]+\n/g, "\n");
62
+ }
@@ -0,0 +1,29 @@
1
+ import { WebSocket } from "mock-socket";
2
+
3
+ /**
4
+ * A version of the mock WebSocket that supports the methods that we use.
5
+ */
6
+ export class MockWebSocket extends WebSocket {
7
+ on(event: string | symbol, listener: (...args: unknown[]) => void): this {
8
+ switch (event) {
9
+ case "message":
10
+ this.onmessage = ({ data }) => {
11
+ listener(data);
12
+ };
13
+ break;
14
+ case "open":
15
+ this.onopen = listener;
16
+ break;
17
+ case "close":
18
+ this.onclose = listener;
19
+ break;
20
+ default:
21
+ throw new Error("Unknown event type: " + event.toString());
22
+ }
23
+ return this;
24
+ }
25
+
26
+ terminate() {
27
+ this.close();
28
+ }
29
+ }
@@ -7,8 +7,10 @@ import { normalizeSlashes, stripTimings } from "./mock-console";
7
7
  export async function runWrangler(cmd?: string) {
8
8
  try {
9
9
  await main(cmd?.split(" ") ?? []);
10
- } catch (e) {
11
- e.message = normalizeSlashes(stripTimings(e.message));
12
- throw e;
10
+ } catch (err) {
11
+ if (err instanceof Error) {
12
+ err.message = normalizeSlashes(stripTimings(err.message));
13
+ }
14
+ throw err;
13
15
  }
14
16
  }
@@ -0,0 +1,17 @@
1
+ import * as fs from "fs";
2
+ import TOML from "@iarna/toml";
3
+ import type { RawConfig } from "../../config";
4
+
5
+ /** Write a mock wrangler.toml file to disk. */
6
+ export default function writeWranglerToml(config: RawConfig = {}) {
7
+ fs.writeFileSync(
8
+ "./wrangler.toml",
9
+ TOML.stringify({
10
+ compatibility_date: "2022-01-12",
11
+ name: "test-name",
12
+ ...(config as TOML.JsonMap),
13
+ }),
14
+
15
+ "utf-8"
16
+ );
17
+ }