wrangler 2.0.23 → 2.0.24
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/README.md +20 -2
- package/bin/wrangler.js +1 -1
- package/miniflare-dist/index.mjs +96 -34
- package/package.json +9 -4
- package/src/__tests__/configuration.test.ts +88 -16
- package/src/__tests__/dev.test.tsx +3 -0
- package/src/__tests__/generate.test.ts +93 -0
- package/src/__tests__/helpers/mock-cfetch.ts +54 -2
- package/src/__tests__/index.test.ts +10 -27
- package/src/__tests__/jest.setup.ts +31 -1
- package/src/__tests__/kv.test.ts +2 -2
- package/src/__tests__/metrics.test.ts +5 -0
- package/src/__tests__/publish.test.ts +497 -254
- package/src/__tests__/r2.test.ts +155 -71
- package/src/__tests__/user.test.ts +1 -0
- package/src/__tests__/validate-dev-props.test.ts +56 -0
- package/src/__tests__/whoami.test.tsx +60 -1
- package/src/bundle.ts +278 -44
- package/src/cfetch/internal.ts +34 -2
- package/src/config/config.ts +7 -2
- package/src/config/environment.ts +40 -8
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +101 -7
- package/src/create-worker-upload-form.ts +25 -0
- package/src/dev/dev.tsx +107 -28
- package/src/dev/local.tsx +20 -10
- package/src/dev/remote.tsx +39 -8
- package/src/dev/use-esbuild.ts +25 -0
- package/src/dev/validate-dev-props.ts +31 -0
- package/src/dev-registry.tsx +157 -0
- package/src/dev.tsx +93 -75
- package/src/generate.ts +112 -14
- package/src/index.tsx +182 -4
- package/src/inspect.ts +93 -5
- package/src/metrics/index.ts +1 -0
- package/src/metrics/metrics-dispatcher.ts +1 -0
- package/src/metrics/metrics-usage-headers.ts +24 -0
- package/src/metrics/send-event.ts +2 -2
- package/src/module-collection.ts +3 -3
- package/src/pages/constants.ts +1 -0
- package/src/pages/deployments.tsx +1 -1
- package/src/pages/dev.tsx +6 -1
- package/src/pages/publish.tsx +1 -1
- package/src/pages/upload.tsx +32 -13
- package/src/publish.ts +126 -112
- package/src/r2.ts +68 -0
- package/src/user/user.tsx +20 -2
- package/src/whoami.tsx +79 -1
- package/src/worker.ts +12 -0
- package/templates/first-party-worker-module-facade.ts +18 -0
- package/templates/format-dev-errors.ts +32 -0
- package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
- package/templates/service-bindings-module-facade.js +51 -0
- package/templates/service-bindings-sw-facade.js +39 -0
- package/wrangler-dist/cli.js +40192 -15265
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { setup } from "create-cloudflare";
|
|
5
|
+
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
6
|
+
import { mockConfirm, clearConfirmMocks } from "./helpers/mock-dialogs";
|
|
7
|
+
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
8
|
+
import { runWrangler } from "./helpers/run-wrangler";
|
|
9
|
+
|
|
10
|
+
const createCloudflareMock = setup as jest.Mock;
|
|
11
|
+
|
|
12
|
+
describe("generate", () => {
|
|
13
|
+
runInTempDir();
|
|
14
|
+
const std = mockConsoleMethods();
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
clearConfirmMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("defers to `wrangler init` when no template is given", async () => {
|
|
21
|
+
mockConfirm(
|
|
22
|
+
{
|
|
23
|
+
text: "Would you like to use git to manage this Worker?",
|
|
24
|
+
result: false,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
text: "No package.json found. Would you like to create one?",
|
|
28
|
+
result: false,
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
await runWrangler("generate no-template");
|
|
32
|
+
expect(std.out).toMatchInlineSnapshot(
|
|
33
|
+
`"✨ Created no-template/wrangler.toml"`
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("runs `create-cloudflare` when a template is given", async () => {
|
|
38
|
+
await expect(
|
|
39
|
+
runWrangler("generate my-worker some-template")
|
|
40
|
+
).resolves.toBeUndefined();
|
|
41
|
+
|
|
42
|
+
expect(createCloudflareMock).toBeCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("complains when given the --type argument", async () => {
|
|
46
|
+
await expect(
|
|
47
|
+
runWrangler("generate worker-name worker-template --type rust")
|
|
48
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
49
|
+
`"The --type option is no longer supported."`
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("complains when given the --site argument", async () => {
|
|
54
|
+
await expect(runWrangler("generate worker-name worker-template --site"))
|
|
55
|
+
.rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
56
|
+
"The --site option is no longer supported.
|
|
57
|
+
If you wish to create a brand new Worker Sites project then clone the \`worker-sites-template\` starter repository:
|
|
58
|
+
|
|
59
|
+
\`\`\`
|
|
60
|
+
git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template worker-name
|
|
61
|
+
cd worker-name
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.
|
|
65
|
+
Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/."
|
|
66
|
+
`);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("auto-increments the worker directory name", async () => {
|
|
70
|
+
fs.mkdirSync("my-worker");
|
|
71
|
+
await expect(
|
|
72
|
+
runWrangler("generate my-worker some-template")
|
|
73
|
+
).resolves.toBeUndefined();
|
|
74
|
+
|
|
75
|
+
expect(createCloudflareMock).lastCalledWith(
|
|
76
|
+
path.resolve(process.cwd(), "my-worker-1"),
|
|
77
|
+
"some-template",
|
|
78
|
+
{ debug: false, force: false, init: true }
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
fs.mkdirSync("my-worker-1");
|
|
82
|
+
|
|
83
|
+
await expect(
|
|
84
|
+
runWrangler("generate my-worker some-template")
|
|
85
|
+
).resolves.toBeUndefined();
|
|
86
|
+
|
|
87
|
+
expect(createCloudflareMock).lastCalledWith(
|
|
88
|
+
path.resolve(process.cwd(), "my-worker-2"),
|
|
89
|
+
"some-template",
|
|
90
|
+
{ debug: false, force: false, init: true }
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
1
2
|
import { URL, URLSearchParams } from "node:url";
|
|
2
3
|
import { pathToRegexp } from "path-to-regexp";
|
|
4
|
+
import { Response } from "undici";
|
|
3
5
|
import { getCloudflareApiBaseUrl } from "../../cfetch";
|
|
4
6
|
import type { FetchResult, FetchError } from "../../cfetch";
|
|
5
|
-
import type { RequestInit } from "undici";
|
|
7
|
+
import type { RequestInit, BodyInit, HeadersInit } from "undici";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* The signature of the function that will handle a mock request.
|
|
@@ -180,6 +182,7 @@ export function unsetAllMocks() {
|
|
|
180
182
|
*/
|
|
181
183
|
|
|
182
184
|
const kvGetMocks = new Map<string, string | Buffer>();
|
|
185
|
+
const r2GetMocks = new Map<string, string | undefined>();
|
|
183
186
|
|
|
184
187
|
/**
|
|
185
188
|
* @mocked typeof fetchKVGetValue
|
|
@@ -206,6 +209,55 @@ export function setMockFetchKVGetValue(
|
|
|
206
209
|
kvGetMocks.set(`${accountId}/${namespaceId}/${key}`, value);
|
|
207
210
|
}
|
|
208
211
|
|
|
209
|
-
|
|
212
|
+
/**
|
|
213
|
+
* @mocked typeof fetchR2Objects
|
|
214
|
+
*/
|
|
215
|
+
export async function mockFetchR2Objects(
|
|
216
|
+
resource: string,
|
|
217
|
+
bodyInit: {
|
|
218
|
+
body: BodyInit | Readable;
|
|
219
|
+
headers: HeadersInit | undefined;
|
|
220
|
+
method: "PUT" | "GET";
|
|
221
|
+
}
|
|
222
|
+
): Promise<Response> {
|
|
223
|
+
/**
|
|
224
|
+
* Here we destroy & removeListeners to "drain" the stream, for testing purposes
|
|
225
|
+
* mimicking the fetch request taking in the stream and draining it.
|
|
226
|
+
*/
|
|
227
|
+
if (bodyInit.body instanceof Readable) {
|
|
228
|
+
bodyInit.body.destroy();
|
|
229
|
+
bodyInit.body.removeAllListeners();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (r2GetMocks.has(resource)) {
|
|
233
|
+
const value = r2GetMocks.get(resource);
|
|
234
|
+
|
|
235
|
+
return new Response(value);
|
|
236
|
+
}
|
|
237
|
+
throw new Error(`no expected mock found for \`r2 object get\` - ${resource}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Mock setter for usage within test blocks, companion helper to `mockFetchR2Objects`
|
|
242
|
+
*/
|
|
243
|
+
export function setMockFetchR2Objects({
|
|
244
|
+
accountId,
|
|
245
|
+
bucketName,
|
|
246
|
+
objectName,
|
|
247
|
+
mockResponse,
|
|
248
|
+
}: {
|
|
249
|
+
accountId: string;
|
|
250
|
+
bucketName: string;
|
|
251
|
+
objectName: string;
|
|
252
|
+
mockResponse?: string;
|
|
253
|
+
}) {
|
|
254
|
+
r2GetMocks.set(
|
|
255
|
+
`/accounts/${accountId}/r2/buckets/${bucketName}/objects/${objectName}`,
|
|
256
|
+
mockResponse
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function unsetSpecialMockFns() {
|
|
210
261
|
kvGetMocks.clear();
|
|
262
|
+
r2GetMocks.clear();
|
|
211
263
|
}
|
|
@@ -203,36 +203,19 @@ describe("wrangler", () => {
|
|
|
203
203
|
await runWrangler("r2");
|
|
204
204
|
await endEventLoop();
|
|
205
205
|
expect(std.out).toMatchInlineSnapshot(`
|
|
206
|
-
|
|
206
|
+
"wrangler r2
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
📦 Interact with an R2 store
|
|
209
209
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
Flags:
|
|
214
|
-
-c, --config Path to .toml configuration file [string]
|
|
215
|
-
-h, --help Show help [boolean]
|
|
216
|
-
-v, --version Show version number [boolean]"
|
|
217
|
-
`);
|
|
218
|
-
});
|
|
219
|
-
});
|
|
210
|
+
Commands:
|
|
211
|
+
wrangler r2 object Manage R2 objects
|
|
212
|
+
wrangler r2 bucket Manage R2 buckets
|
|
220
213
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
\`wrangler generate\` has been deprecated.
|
|
227
|
-
Try running \`wrangler init\` to generate a basic Worker, or cloning the template repository instead:
|
|
228
|
-
|
|
229
|
-
\`\`\`
|
|
230
|
-
git clone https://github.com/cloudflare/worker-template
|
|
231
|
-
\`\`\`
|
|
232
|
-
|
|
233
|
-
Please refer to https://developers.cloudflare.com/workers/wrangler/deprecations/#generate for more information."
|
|
234
|
-
`);
|
|
235
|
-
});
|
|
214
|
+
Flags:
|
|
215
|
+
-c, --config Path to .toml configuration file [string]
|
|
216
|
+
-h, --help Show help [boolean]
|
|
217
|
+
-v, --version Show version number [boolean]"
|
|
218
|
+
`);
|
|
236
219
|
});
|
|
237
220
|
});
|
|
238
221
|
|
|
@@ -2,10 +2,15 @@ import fetchMock from "jest-fetch-mock";
|
|
|
2
2
|
import {
|
|
3
3
|
fetchInternal,
|
|
4
4
|
fetchKVGetValue,
|
|
5
|
+
fetchR2Objects,
|
|
5
6
|
getCloudflareAPIBaseURL,
|
|
6
7
|
} from "../cfetch/internal";
|
|
7
8
|
import { confirm, prompt } from "../dialogs";
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
mockFetchInternal,
|
|
11
|
+
mockFetchKVGetValue,
|
|
12
|
+
mockFetchR2Objects,
|
|
13
|
+
} from "./helpers/mock-cfetch";
|
|
9
14
|
import { MockWebSocket } from "./helpers/mock-web-socket";
|
|
10
15
|
|
|
11
16
|
// Mock out getPort since we don't actually care about what ports are open in unit tests.
|
|
@@ -43,6 +48,7 @@ jest.mock("../cfetch/internal");
|
|
|
43
48
|
(getCloudflareAPIBaseURL as jest.Mock).mockReturnValue(
|
|
44
49
|
"https://api.cloudflare.com/client/v4"
|
|
45
50
|
);
|
|
51
|
+
(fetchR2Objects as jest.Mock).mockImplementation(mockFetchR2Objects);
|
|
46
52
|
|
|
47
53
|
jest.mock("../dialogs");
|
|
48
54
|
|
|
@@ -118,3 +124,27 @@ jest.mock("xdg-app-paths", () => {
|
|
|
118
124
|
}),
|
|
119
125
|
};
|
|
120
126
|
});
|
|
127
|
+
|
|
128
|
+
jest.mock("create-cloudflare");
|
|
129
|
+
|
|
130
|
+
jest.mock("../metrics/metrics-config", () => {
|
|
131
|
+
const realModule = jest.requireActual("../metrics/metrics-config");
|
|
132
|
+
const fakeModule = {
|
|
133
|
+
...realModule,
|
|
134
|
+
// Although we mock out the getMetricsConfig() function in most tests,
|
|
135
|
+
// we need a way to reinstate it for the metrics specific tests.
|
|
136
|
+
// This is what `useOriginal` is for.
|
|
137
|
+
useOriginal: false,
|
|
138
|
+
getMetricsConfig: (...args: unknown[]) =>
|
|
139
|
+
fakeModule.useOriginal
|
|
140
|
+
? realModule.getMetricsConfig(...args)
|
|
141
|
+
: async () => {
|
|
142
|
+
return {
|
|
143
|
+
enabled: false,
|
|
144
|
+
deviceId: "mock-device",
|
|
145
|
+
userId: undefined,
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
return fakeModule;
|
|
150
|
+
});
|
package/src/__tests__/kv.test.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
|
4
4
|
import {
|
|
5
5
|
setMockResponse,
|
|
6
6
|
unsetAllMocks,
|
|
7
|
-
|
|
7
|
+
unsetSpecialMockFns,
|
|
8
8
|
setMockFetchKVGetValue,
|
|
9
9
|
setMockRawResponse,
|
|
10
10
|
createFetchResult,
|
|
@@ -924,7 +924,7 @@ describe("wrangler", () => {
|
|
|
924
924
|
|
|
925
925
|
describe("get", () => {
|
|
926
926
|
afterEach(() => {
|
|
927
|
-
|
|
927
|
+
unsetSpecialMockFns();
|
|
928
928
|
});
|
|
929
929
|
|
|
930
930
|
it("should get a key in a given namespace specified by namespace-id", async () => {
|
|
@@ -26,6 +26,9 @@ describe("metrics", () => {
|
|
|
26
26
|
runInTempDir();
|
|
27
27
|
|
|
28
28
|
beforeEach(() => {
|
|
29
|
+
// Tell jest to use the original version of the `getMetricsConfig()` function in these tests.
|
|
30
|
+
const mockMetricsConfig = jest.requireMock("../metrics/metrics-config");
|
|
31
|
+
mockMetricsConfig.useOriginal = true;
|
|
29
32
|
global.SPARROW_SOURCE_KEY = "MOCK_KEY";
|
|
30
33
|
logger.loggerLevel = "debug";
|
|
31
34
|
// Create a node_modules directory to store config-cache files
|
|
@@ -65,6 +68,7 @@ describe("metrics", () => {
|
|
|
65
68
|
properties: {
|
|
66
69
|
category: "Workers",
|
|
67
70
|
wranglerVersion,
|
|
71
|
+
os: process.platform + ":" + process.arch,
|
|
68
72
|
a: 1,
|
|
69
73
|
b: 2,
|
|
70
74
|
},
|
|
@@ -139,6 +143,7 @@ describe("metrics", () => {
|
|
|
139
143
|
properties: {
|
|
140
144
|
category: "Workers",
|
|
141
145
|
wranglerVersion,
|
|
146
|
+
os: process.platform + ":" + process.arch,
|
|
142
147
|
a: 1,
|
|
143
148
|
b: 2,
|
|
144
149
|
},
|