wrangler 2.0.21 → 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 +527 -5
- package/package.json +18 -5
- package/src/__tests__/configuration.test.ts +88 -16
- package/src/__tests__/dev.test.tsx +95 -4
- 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 +82 -61
- package/src/__tests__/metrics.test.ts +35 -0
- package/src/__tests__/publish.test.ts +573 -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__/version.test.ts +35 -0
- package/src/__tests__/whoami.test.tsx +60 -1
- package/src/api/dev.ts +43 -9
- package/src/bundle.ts +297 -37
- package/src/cfetch/internal.ts +34 -2
- package/src/config/config.ts +14 -2
- package/src/config/environment.ts +40 -8
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +110 -8
- package/src/create-worker-preview.ts +3 -1
- package/src/create-worker-upload-form.ts +25 -0
- package/src/dev/dev.tsx +135 -31
- package/src/dev/local.tsx +48 -20
- package/src/dev/remote.tsx +39 -12
- 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 +137 -65
- package/src/generate.ts +112 -14
- package/src/index.tsx +222 -7
- package/src/inspect.ts +93 -5
- package/src/metrics/index.ts +1 -0
- package/src/metrics/is-ci.ts +14 -0
- package/src/metrics/metrics-config.ts +19 -2
- 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/miniflare-cli/assets.ts +543 -0
- package/src/miniflare-cli/index.ts +36 -4
- 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 +85 -639
- package/src/pages/publish.tsx +1 -1
- package/src/pages/upload.tsx +32 -13
- package/src/publish.ts +139 -112
- package/src/r2.ts +68 -0
- package/src/user/choose-account.tsx +20 -11
- 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/pages-shim.ts +9 -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.d.ts +32 -3
- package/wrangler-dist/cli.js +45257 -25209
package/src/__tests__/r2.test.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
1
2
|
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
2
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
setMockFetchR2Objects,
|
|
5
|
+
setMockResponse,
|
|
6
|
+
unsetAllMocks,
|
|
7
|
+
} from "./helpers/mock-cfetch";
|
|
3
8
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
4
9
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
5
10
|
import { runWrangler } from "./helpers/run-wrangler";
|
|
@@ -22,26 +27,26 @@ describe("wrangler", () => {
|
|
|
22
27
|
runWrangler("r2 bucket foo")
|
|
23
28
|
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unknown argument: foo"`);
|
|
24
29
|
expect(std.err).toMatchInlineSnapshot(`
|
|
25
|
-
|
|
30
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
"
|
|
33
|
+
`);
|
|
29
34
|
expect(std.out).toMatchInlineSnapshot(`
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
"
|
|
36
|
+
wrangler r2 bucket
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
Manage R2 buckets
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
Commands:
|
|
41
|
+
wrangler r2 bucket create <name> Create a new R2 bucket
|
|
42
|
+
wrangler r2 bucket list List R2 buckets
|
|
43
|
+
wrangler r2 bucket delete <name> Delete an R2 bucket
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
Flags:
|
|
46
|
+
-c, --config Path to .toml configuration file [string]
|
|
47
|
+
-h, --help Show help [boolean]
|
|
48
|
+
-v, --version Show version number [boolean]"
|
|
49
|
+
`);
|
|
45
50
|
});
|
|
46
51
|
|
|
47
52
|
describe("list", () => {
|
|
@@ -95,24 +100,24 @@ describe("wrangler", () => {
|
|
|
95
100
|
`"Not enough non-option arguments: got 0, need at least 1"`
|
|
96
101
|
);
|
|
97
102
|
expect(std.out).toMatchInlineSnapshot(`
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
"
|
|
104
|
+
wrangler r2 bucket create <name>
|
|
100
105
|
|
|
101
|
-
|
|
106
|
+
Create a new R2 bucket
|
|
102
107
|
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
Positionals:
|
|
109
|
+
name The name of the new bucket [string] [required]
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
+
Flags:
|
|
112
|
+
-c, --config Path to .toml configuration file [string]
|
|
113
|
+
-h, --help Show help [boolean]
|
|
114
|
+
-v, --version Show version number [boolean]"
|
|
115
|
+
`);
|
|
111
116
|
expect(std.err).toMatchInlineSnapshot(`
|
|
112
|
-
|
|
117
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
"
|
|
120
|
+
`);
|
|
116
121
|
});
|
|
117
122
|
|
|
118
123
|
it("should error if the bucket to create contains spaces", async () => {
|
|
@@ -122,33 +127,33 @@ describe("wrangler", () => {
|
|
|
122
127
|
`"Unknown arguments: def, ghi"`
|
|
123
128
|
);
|
|
124
129
|
expect(std.out).toMatchInlineSnapshot(`
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
"
|
|
131
|
+
wrangler r2 bucket create <name>
|
|
127
132
|
|
|
128
|
-
|
|
133
|
+
Create a new R2 bucket
|
|
129
134
|
|
|
130
|
-
|
|
131
|
-
|
|
135
|
+
Positionals:
|
|
136
|
+
name The name of the new bucket [string] [required]
|
|
132
137
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
Flags:
|
|
139
|
+
-c, --config Path to .toml configuration file [string]
|
|
140
|
+
-h, --help Show help [boolean]
|
|
141
|
+
-v, --version Show version number [boolean]"
|
|
142
|
+
`);
|
|
138
143
|
expect(std.err).toMatchInlineSnapshot(`
|
|
139
|
-
|
|
144
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
|
|
140
145
|
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
"
|
|
147
|
+
`);
|
|
143
148
|
});
|
|
144
149
|
|
|
145
150
|
it("should create a bucket", async () => {
|
|
146
151
|
const requests = mockCreateRequest("testBucket");
|
|
147
152
|
await runWrangler("r2 bucket create testBucket");
|
|
148
153
|
expect(std.out).toMatchInlineSnapshot(`
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
154
|
+
"Creating bucket testBucket.
|
|
155
|
+
Created bucket testBucket."
|
|
156
|
+
`);
|
|
152
157
|
expect(requests.count).toEqual(1);
|
|
153
158
|
});
|
|
154
159
|
});
|
|
@@ -175,24 +180,24 @@ describe("wrangler", () => {
|
|
|
175
180
|
`"Not enough non-option arguments: got 0, need at least 1"`
|
|
176
181
|
);
|
|
177
182
|
expect(std.out).toMatchInlineSnapshot(`
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
"
|
|
184
|
+
wrangler r2 bucket delete <name>
|
|
180
185
|
|
|
181
|
-
|
|
186
|
+
Delete an R2 bucket
|
|
182
187
|
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
Positionals:
|
|
189
|
+
name The name of the bucket to delete [string] [required]
|
|
185
190
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
Flags:
|
|
192
|
+
-c, --config Path to .toml configuration file [string]
|
|
193
|
+
-h, --help Show help [boolean]
|
|
194
|
+
-v, --version Show version number [boolean]"
|
|
195
|
+
`);
|
|
191
196
|
expect(std.err).toMatchInlineSnapshot(`
|
|
192
|
-
|
|
197
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
|
|
193
198
|
|
|
194
|
-
|
|
195
|
-
|
|
199
|
+
"
|
|
200
|
+
`);
|
|
196
201
|
});
|
|
197
202
|
|
|
198
203
|
it("should error if the bucket name to delete contains spaces", async () => {
|
|
@@ -202,24 +207,24 @@ describe("wrangler", () => {
|
|
|
202
207
|
`"Unknown arguments: def, ghi"`
|
|
203
208
|
);
|
|
204
209
|
expect(std.out).toMatchInlineSnapshot(`
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
"
|
|
211
|
+
wrangler r2 bucket delete <name>
|
|
207
212
|
|
|
208
|
-
|
|
213
|
+
Delete an R2 bucket
|
|
209
214
|
|
|
210
|
-
|
|
211
|
-
|
|
215
|
+
Positionals:
|
|
216
|
+
name The name of the bucket to delete [string] [required]
|
|
212
217
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
Flags:
|
|
219
|
+
-c, --config Path to .toml configuration file [string]
|
|
220
|
+
-h, --help Show help [boolean]
|
|
221
|
+
-v, --version Show version number [boolean]"
|
|
222
|
+
`);
|
|
218
223
|
expect(std.err).toMatchInlineSnapshot(`
|
|
219
|
-
|
|
224
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
|
|
220
225
|
|
|
221
|
-
|
|
222
|
-
|
|
226
|
+
"
|
|
227
|
+
`);
|
|
223
228
|
});
|
|
224
229
|
|
|
225
230
|
it("should delete a bucket specified by name", async () => {
|
|
@@ -229,5 +234,84 @@ describe("wrangler", () => {
|
|
|
229
234
|
});
|
|
230
235
|
});
|
|
231
236
|
});
|
|
237
|
+
|
|
238
|
+
describe("r2 object", () => {
|
|
239
|
+
it("should download R2 object from bucket", async () => {
|
|
240
|
+
setMockFetchR2Objects({
|
|
241
|
+
accountId: "some-account-id",
|
|
242
|
+
bucketName: "bucketName-object-test",
|
|
243
|
+
objectName: "wormhole-img.png",
|
|
244
|
+
mockResponse: "R2-objects-test-data",
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
await runWrangler(
|
|
248
|
+
`r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png`
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
252
|
+
"Downloading \\"wormhole-img.png\\" from \\"bucketName-object-test\\".
|
|
253
|
+
Download complete."
|
|
254
|
+
`);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("should upload R2 object from bucket", async () => {
|
|
258
|
+
setMockFetchR2Objects({
|
|
259
|
+
accountId: "some-account-id",
|
|
260
|
+
bucketName: "bucketName-object-test",
|
|
261
|
+
objectName: "wormhole-img.png",
|
|
262
|
+
});
|
|
263
|
+
fs.writeFileSync("wormhole-img.png", "passageway");
|
|
264
|
+
await runWrangler(
|
|
265
|
+
`r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png`
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
269
|
+
"Creating object \\"wormhole-img.png\\" in bucket \\"bucketName-object-test\\".
|
|
270
|
+
Upload complete."
|
|
271
|
+
`);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("should pass all fetch option flags into requestInit", async () => {
|
|
275
|
+
fs.writeFileSync("wormhole-img.png", "passageway");
|
|
276
|
+
setMockFetchR2Objects({
|
|
277
|
+
accountId: "some-account-id",
|
|
278
|
+
bucketName: "bucketName-object-test",
|
|
279
|
+
objectName: "wormhole-img.png",
|
|
280
|
+
});
|
|
281
|
+
const flags =
|
|
282
|
+
"--ct content-type --cd content-disposition --ce content-encoding --cl content-lang --cc cache-control --e expire-time";
|
|
283
|
+
|
|
284
|
+
await runWrangler(
|
|
285
|
+
`r2 object put bucketName-object-test/wormhole-img.png ${flags} --file wormhole-img.png`
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
289
|
+
"Creating object \\"wormhole-img.png\\" in bucket \\"bucketName-object-test\\".
|
|
290
|
+
Upload complete."
|
|
291
|
+
`);
|
|
292
|
+
});
|
|
293
|
+
it("should not allow `--pipe` & `--file` to run together", async () => {
|
|
294
|
+
fs.writeFileSync("wormhole-img.png", "passageway");
|
|
295
|
+
setMockFetchR2Objects({
|
|
296
|
+
accountId: "some-account-id",
|
|
297
|
+
bucketName: "bucketName-object-test",
|
|
298
|
+
objectName: "wormhole-img.png",
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
await expect(
|
|
302
|
+
runWrangler(
|
|
303
|
+
`r2 object put bucketName-object-test/wormhole-img.png --pipe --file wormhole-img.png`
|
|
304
|
+
)
|
|
305
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
306
|
+
`"Arguments pipe and file are mutually exclusive"`
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
310
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mArguments pipe and file are mutually exclusive[0m
|
|
311
|
+
|
|
312
|
+
"
|
|
313
|
+
`);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
232
316
|
});
|
|
233
317
|
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { validateDevProps } from "../dev/validate-dev-props";
|
|
2
|
+
import type { DevProps } from "../dev/dev";
|
|
3
|
+
|
|
4
|
+
describe("validateDevProps", () => {
|
|
5
|
+
it("should throw if the user tries to use the service-worker format with an `assets` directory", () => {
|
|
6
|
+
const props = {
|
|
7
|
+
isWorkersSite: false,
|
|
8
|
+
assetPaths: ["assets"],
|
|
9
|
+
entry: { format: "service-worker" },
|
|
10
|
+
bindings: {},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
expect(() => validateDevProps(props as unknown as DevProps)).toThrowError(
|
|
14
|
+
"You cannot use the service-worker format with an `assets` directory yet. For information on how to migrate to the module-worker format, see: https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/"
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should throw if the user tries to configure [wasm_modules] with an ES module worker", () => {
|
|
19
|
+
const props = {
|
|
20
|
+
isWorkersSite: false,
|
|
21
|
+
assetPaths: [],
|
|
22
|
+
entry: { format: "modules" },
|
|
23
|
+
bindings: { wasm_modules: true },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
expect(() => validateDevProps(props as unknown as DevProps)).toThrowError(
|
|
27
|
+
"You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should throw if the user tries to configure [text_blobs] with an ES module worker", () => {
|
|
32
|
+
const props = {
|
|
33
|
+
isWorkersSite: false,
|
|
34
|
+
assetPaths: [],
|
|
35
|
+
entry: { format: "modules" },
|
|
36
|
+
bindings: { text_blobs: true },
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
expect(() => validateDevProps(props as unknown as DevProps)).toThrowError(
|
|
40
|
+
"You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should throw if the user tries to configure [data_blobs] with an ES module worker", () => {
|
|
45
|
+
const props = {
|
|
46
|
+
isWorkersSite: false,
|
|
47
|
+
assetPaths: [],
|
|
48
|
+
entry: { format: "modules" },
|
|
49
|
+
bindings: { data_blobs: true },
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
expect(() => validateDevProps(props as unknown as DevProps)).toThrowError(
|
|
53
|
+
"You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { version } from "./../../package.json";
|
|
2
|
+
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
3
|
+
import { useMockIsTTY } from "./helpers/mock-istty";
|
|
4
|
+
import { runWrangler } from "./helpers/run-wrangler";
|
|
5
|
+
|
|
6
|
+
describe("version", () => {
|
|
7
|
+
const std = mockConsoleMethods();
|
|
8
|
+
const { setIsTTY } = useMockIsTTY();
|
|
9
|
+
|
|
10
|
+
// We cannot test output of version banner,
|
|
11
|
+
// as it is disabled in jest environments
|
|
12
|
+
|
|
13
|
+
// it("should output version banner", async () => {
|
|
14
|
+
// await runWrangler("-v");
|
|
15
|
+
// expect(std.out).toMatchInlineSnapshot(`
|
|
16
|
+
// " ⛅️ wrangler 2.0.22
|
|
17
|
+
// [38;5;214m--------------------[39m"
|
|
18
|
+
// `);
|
|
19
|
+
// });
|
|
20
|
+
|
|
21
|
+
it("should output current version if !isTTY calling -v", async () => {
|
|
22
|
+
setIsTTY(false);
|
|
23
|
+
|
|
24
|
+
await runWrangler("-v");
|
|
25
|
+
expect(std.out).toMatch(version);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// This run separately as command handling is different
|
|
29
|
+
it("should output current version if !isTTY calling --version", async () => {
|
|
30
|
+
setIsTTY(false);
|
|
31
|
+
|
|
32
|
+
await runWrangler("--version");
|
|
33
|
+
expect(std.out).toMatch(version);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -205,11 +205,12 @@ describe("WhoAmI component", () => {
|
|
|
205
205
|
);
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
it("should display the user's email and
|
|
208
|
+
it("should display the user's email, accounts and OAuth scopes", async () => {
|
|
209
209
|
const user: UserInfo = {
|
|
210
210
|
authType: "OAuth Token",
|
|
211
211
|
apiToken: "some-oauth-token",
|
|
212
212
|
email: "user@example.com",
|
|
213
|
+
tokenPermissions: ["scope1:read", "scope2:write", "scope3"],
|
|
213
214
|
accounts: [
|
|
214
215
|
{ name: "Account One", id: "account-1" },
|
|
215
216
|
{ name: "Account Two", id: "account-2" },
|
|
@@ -226,5 +227,63 @@ describe("WhoAmI component", () => {
|
|
|
226
227
|
expect(lastFrame()).toMatch(/Account One .+ account-1/);
|
|
227
228
|
expect(lastFrame()).toMatch(/Account Two .+ account-2/);
|
|
228
229
|
expect(lastFrame()).toMatch(/Account Three .+ account-3/);
|
|
230
|
+
expect(lastFrame()).toContain(
|
|
231
|
+
"Token Permissions: If scopes are missing, you may need to logout and re-login."
|
|
232
|
+
);
|
|
233
|
+
expect(lastFrame()).toContain("- scope1 (read)");
|
|
234
|
+
expect(lastFrame()).toContain("- scope2 (write)");
|
|
235
|
+
expect(lastFrame()).toContain("- scope3");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// For the case where the cache hasn't updated to include the scopes array
|
|
239
|
+
it("should display the user's email and accounts, but no OAuth scopes if none provided", async () => {
|
|
240
|
+
const user: UserInfo = {
|
|
241
|
+
authType: "OAuth Token",
|
|
242
|
+
apiToken: "some-oauth-token",
|
|
243
|
+
email: "user@example.com",
|
|
244
|
+
tokenPermissions: undefined,
|
|
245
|
+
accounts: [
|
|
246
|
+
{ name: "Account One", id: "account-1" },
|
|
247
|
+
{ name: "Account Two", id: "account-2" },
|
|
248
|
+
{ name: "Account Three", id: "account-3" },
|
|
249
|
+
],
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
|
|
253
|
+
|
|
254
|
+
expect(lastFrame()).toContain(
|
|
255
|
+
"You are logged in with an OAuth Token, associated with the email 'user@example.com'!"
|
|
256
|
+
);
|
|
257
|
+
expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
|
|
258
|
+
expect(lastFrame()).toMatch(/Account One .+ account-1/);
|
|
259
|
+
expect(lastFrame()).toMatch(/Account Two .+ account-2/);
|
|
260
|
+
expect(lastFrame()).toMatch(/Account Three .+ account-3/);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("should display the user's email, accounts and link to view token permissions for non-OAuth tokens", async () => {
|
|
264
|
+
const user: UserInfo = {
|
|
265
|
+
authType: "API Token",
|
|
266
|
+
apiToken: "some-api-token",
|
|
267
|
+
email: "user@example.com",
|
|
268
|
+
tokenPermissions: undefined,
|
|
269
|
+
accounts: [
|
|
270
|
+
{ name: "Account One", id: "account-1" },
|
|
271
|
+
{ name: "Account Two", id: "account-2" },
|
|
272
|
+
{ name: "Account Three", id: "account-3" },
|
|
273
|
+
],
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
|
|
277
|
+
|
|
278
|
+
expect(lastFrame()).toContain(
|
|
279
|
+
"You are logged in with an API Token, associated with the email 'user@example.com'!"
|
|
280
|
+
);
|
|
281
|
+
expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
|
|
282
|
+
expect(lastFrame()).toMatch(/Account One .+ account-1/);
|
|
283
|
+
expect(lastFrame()).toMatch(/Account Two .+ account-2/);
|
|
284
|
+
expect(lastFrame()).toMatch(/Account Three .+ account-3/);
|
|
285
|
+
expect(lastFrame()).toContain(
|
|
286
|
+
"To see token permissions visit https://dash.cloudflare.com/profile/api-tokens"
|
|
287
|
+
);
|
|
229
288
|
});
|
|
230
289
|
});
|
package/src/api/dev.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { startDev } from "../dev";
|
|
2
2
|
import { logger } from "../logger";
|
|
3
3
|
|
|
4
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
4
5
|
import type { RequestInit, Response } from "undici";
|
|
5
6
|
|
|
6
7
|
interface DevOptions {
|
|
@@ -13,39 +14,72 @@ interface DevOptions {
|
|
|
13
14
|
siteInclude?: string[];
|
|
14
15
|
siteExclude?: string[];
|
|
15
16
|
nodeCompat?: boolean;
|
|
17
|
+
compatibilityDate?: string;
|
|
16
18
|
experimentalEnableLocalPersistence?: boolean;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
liveReload?: boolean;
|
|
20
|
+
watch?: boolean;
|
|
21
|
+
vars: {
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
kv?: {
|
|
25
|
+
binding: string;
|
|
26
|
+
id: string;
|
|
27
|
+
preview_id?: string;
|
|
28
|
+
}[];
|
|
29
|
+
durableObjects?: {
|
|
30
|
+
name: string;
|
|
31
|
+
class_name: string;
|
|
32
|
+
script_name?: string | undefined;
|
|
33
|
+
environment?: string | undefined;
|
|
34
|
+
}[];
|
|
35
|
+
showInteractiveDevSession?: boolean;
|
|
36
|
+
logLevel?: "none" | "error" | "log" | "warn" | "debug";
|
|
37
|
+
logPrefix?: string;
|
|
38
|
+
inspect?: boolean;
|
|
39
|
+
forceLocal?: boolean;
|
|
40
|
+
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
41
|
+
_?: (string | number)[]; //yargs wants this
|
|
42
|
+
$0?: string; //yargs wants this
|
|
19
43
|
}
|
|
20
44
|
/**
|
|
21
45
|
* unstable_dev starts a wrangler dev server, and returns a promise that resolves with utility functions to interact with it.
|
|
22
46
|
* @param {string} script
|
|
23
47
|
* @param {DevOptions} options
|
|
24
48
|
*/
|
|
25
|
-
export async function unstable_dev(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
49
|
+
export async function unstable_dev(
|
|
50
|
+
script: string,
|
|
51
|
+
options: DevOptions,
|
|
52
|
+
disableExperimentalWarning?: boolean
|
|
53
|
+
) {
|
|
54
|
+
if (!disableExperimentalWarning) {
|
|
55
|
+
logger.warn(
|
|
56
|
+
`unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
29
59
|
|
|
30
60
|
return new Promise<{
|
|
31
61
|
stop: () => void;
|
|
32
62
|
fetch: (init?: RequestInit) => Promise<Response | undefined>;
|
|
63
|
+
waitUntilExit: () => Promise<void>;
|
|
33
64
|
}>((resolve) => {
|
|
34
65
|
//lmao
|
|
35
66
|
return new Promise<Awaited<ReturnType<typeof startDev>>>((ready) => {
|
|
36
67
|
const devServer = startDev({
|
|
37
68
|
script: script,
|
|
38
|
-
...options,
|
|
39
|
-
local: true,
|
|
40
|
-
onReady: () => ready(devServer),
|
|
41
69
|
inspect: false,
|
|
42
70
|
logLevel: "none",
|
|
43
71
|
showInteractiveDevSession: false,
|
|
72
|
+
_: [],
|
|
73
|
+
$0: "",
|
|
74
|
+
...options,
|
|
75
|
+
local: true,
|
|
76
|
+
onReady: () => ready(devServer),
|
|
44
77
|
});
|
|
45
78
|
}).then((devServer) => {
|
|
46
79
|
resolve({
|
|
47
80
|
stop: devServer.stop,
|
|
48
81
|
fetch: devServer.fetch,
|
|
82
|
+
waitUntilExit: devServer.devReactElement.waitUntilExit,
|
|
49
83
|
});
|
|
50
84
|
});
|
|
51
85
|
});
|