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.
- package/package.json +16 -7
- package/pages/functions/filepath-routing.test.ts +112 -36
- package/pages/functions/filepath-routing.ts +66 -119
- package/pages/functions/routes.ts +8 -17
- package/pages/functions/template-worker.ts +3 -9
- package/src/__tests__/configuration.test.ts +2185 -0
- package/src/__tests__/dev.test.tsx +48 -6
- package/src/__tests__/guess-worker-format.test.ts +66 -0
- package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
- package/src/__tests__/helpers/mock-account-id.ts +6 -6
- package/src/__tests__/helpers/mock-bin.ts +4 -1
- package/src/__tests__/helpers/mock-cfetch.ts +2 -2
- package/src/__tests__/helpers/mock-console.ts +11 -5
- package/src/__tests__/helpers/mock-web-socket.ts +29 -0
- package/src/__tests__/helpers/run-wrangler.ts +5 -3
- package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
- package/src/__tests__/index.test.ts +343 -20
- package/src/__tests__/jest.setup.ts +21 -1
- package/src/__tests__/kv.test.ts +82 -80
- package/src/__tests__/package-manager.test.ts +2 -2
- package/src/__tests__/parse.test.ts +322 -0
- package/src/__tests__/publish.test.ts +1428 -244
- package/src/__tests__/r2.test.ts +198 -0
- package/src/__tests__/secret.test.ts +176 -60
- package/src/__tests__/sentry.test.ts +146 -0
- package/src/__tests__/tail.test.ts +564 -0
- package/src/api/form_data.ts +106 -23
- package/src/api/preview.ts +32 -13
- package/src/api/worker.ts +49 -18
- package/src/bundle.ts +133 -0
- package/src/cfetch/index.ts +8 -6
- package/src/cfetch/internal.ts +49 -17
- package/src/cli.ts +10 -0
- package/src/config/README.md +107 -0
- package/src/config/config.ts +265 -0
- package/src/config/diagnostics.ts +80 -0
- package/src/config/environment.ts +305 -0
- package/src/config/index.ts +52 -0
- package/src/config/validation-helpers.ts +370 -0
- package/src/config/validation.ts +1017 -0
- package/src/dev.tsx +338 -211
- package/src/entry.ts +57 -0
- package/src/environment-variables.ts +33 -0
- package/src/guess-worker-format.ts +68 -0
- package/src/index.tsx +860 -634
- package/src/inspect.ts +16 -3
- package/src/kv.tsx +20 -29
- package/src/module-collection.ts +141 -34
- package/src/open-in-browser.ts +13 -0
- package/src/package-manager.ts +21 -15
- package/src/pages.tsx +9 -10
- package/src/parse.ts +183 -0
- package/src/proxy.ts +11 -5
- package/src/publish.ts +272 -314
- package/src/r2.ts +50 -0
- package/src/reporting.ts +115 -0
- package/src/sites.tsx +16 -15
- package/src/tail/filters.ts +279 -0
- package/src/tail/index.ts +299 -0
- package/src/tail/printing.ts +62 -0
- package/src/user.tsx +74 -44
- package/templates/new-worker.js +1 -1
- package/templates/new-worker.ts +1 -1
- package/templates/tsconfig.json +105 -0
- package/wrangler-dist/cli.js +51308 -36440
- package/wrangler-dist/cli.js.map +3 -3
- package/src/config.ts +0 -641
- 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
|
-
|
|
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
|
+
[32m%s[0m
|
|
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
|
-
|
|
64
|
+
legacyEnv = true,
|
|
65
|
+
initialMode = "local",
|
|
38
66
|
jsxFactory,
|
|
39
67
|
jsxFragment,
|
|
40
|
-
|
|
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
|
|
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
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
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.
|
|
11
|
+
process.env.CLOUDFLARE_API_TOKEN = apiToken;
|
|
12
12
|
});
|
|
13
13
|
afterEach(() => {
|
|
14
|
-
process.env.
|
|
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.
|
|
25
|
+
process.env.CLOUDFLARE_ACCOUNT_ID = accountId;
|
|
26
26
|
});
|
|
27
27
|
afterEach(() => {
|
|
28
|
-
process.env.
|
|
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(
|
|
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 {
|
|
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,
|
|
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
|
|
12
|
+
return stripTrailingWhitespace(
|
|
13
|
+
normalizeSlashes(stripTimings(logSpy.mock.calls.flat(2).join("\n")))
|
|
14
|
+
);
|
|
13
15
|
},
|
|
14
16
|
get err() {
|
|
15
|
-
return
|
|
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
|
|
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 (
|
|
11
|
-
|
|
12
|
-
|
|
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
|
+
}
|