wrangler 2.1.0 → 2.1.3
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/miniflare-dist/index.mjs +1 -1
- package/package.json +2 -1
- package/src/__tests__/dev.test.tsx +2 -1
- package/src/__tests__/dialogs.test.tsx +40 -0
- package/src/__tests__/helpers/mock-cfetch.ts +35 -15
- package/src/__tests__/helpers/msw/handlers/index.ts +13 -0
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
- package/src/__tests__/helpers/msw/handlers/oauth.ts +36 -0
- package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
- package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
- package/src/__tests__/helpers/msw/index.ts +4 -0
- package/src/__tests__/index.test.ts +2 -0
- package/src/__tests__/jest.setup.ts +16 -0
- package/src/__tests__/publish.test.ts +52 -0
- package/src/__tests__/r2.test.ts +128 -93
- package/src/__tests__/secret.test.ts +78 -0
- package/src/__tests__/whoami.test.tsx +49 -64
- package/src/api/dev.ts +2 -1
- package/src/dev/dev.tsx +2 -2
- package/src/dev/local.tsx +2 -12
- package/src/dev/start-server.ts +2 -13
- package/src/dev.tsx +39 -6
- package/src/dialogs.tsx +8 -1
- package/src/index.tsx +90 -0
- package/src/miniflare-cli/assets.ts +1 -1
- package/src/pages/dev.tsx +28 -4
- package/src/publish.ts +21 -13
- package/wrangler-dist/cli.d.ts +2 -1
- package/wrangler-dist/cli.js +188 -44
package/src/__tests__/r2.test.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
+
import { rest } from "msw";
|
|
2
3
|
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
3
|
-
import {
|
|
4
|
-
setMockFetchR2Objects,
|
|
5
|
-
setMockResponse,
|
|
6
|
-
unsetAllMocks,
|
|
7
|
-
} from "./helpers/mock-cfetch";
|
|
8
4
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
5
|
+
import { msw } from "./helpers/msw";
|
|
9
6
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
10
7
|
import { runWrangler } from "./helpers/run-wrangler";
|
|
11
8
|
import type { R2BucketInfo } from "../r2";
|
|
@@ -16,10 +13,6 @@ describe("wrangler", () => {
|
|
|
16
13
|
runInTempDir();
|
|
17
14
|
const std = mockConsoleMethods();
|
|
18
15
|
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
unsetAllMocks();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
16
|
describe("r2", () => {
|
|
24
17
|
describe("bucket", () => {
|
|
25
18
|
it("should show the correct help when an invalid command is passed", async () => {
|
|
@@ -50,26 +43,41 @@ describe("wrangler", () => {
|
|
|
50
43
|
});
|
|
51
44
|
|
|
52
45
|
describe("list", () => {
|
|
53
|
-
|
|
54
|
-
const requests = { count: 0 };
|
|
55
|
-
setMockResponse(
|
|
56
|
-
"/accounts/:accountId/r2/buckets",
|
|
57
|
-
([_url, accountId], init) => {
|
|
58
|
-
requests.count++;
|
|
59
|
-
expect(accountId).toEqual("some-account-id");
|
|
60
|
-
expect(init).toEqual({});
|
|
61
|
-
return { buckets };
|
|
62
|
-
}
|
|
63
|
-
);
|
|
64
|
-
return requests;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
it("should list buckets", async () => {
|
|
46
|
+
it("should list buckets & check request inputs", async () => {
|
|
68
47
|
const expectedBuckets: R2BucketInfo[] = [
|
|
69
|
-
{ name: "bucket-1", creation_date: "01-01-2001" },
|
|
70
|
-
{ name: "bucket-2", creation_date: "01-01-2001" },
|
|
48
|
+
{ name: "bucket-1-local-once", creation_date: "01-01-2001" },
|
|
49
|
+
{ name: "bucket-2-local-once", creation_date: "01-01-2001" },
|
|
71
50
|
];
|
|
72
|
-
|
|
51
|
+
msw.use(
|
|
52
|
+
rest.get(
|
|
53
|
+
"*/accounts/:accountId/r2/buckets",
|
|
54
|
+
async (request, response, context) => {
|
|
55
|
+
const { accountId } = request.params;
|
|
56
|
+
expect(accountId).toEqual("some-account-id");
|
|
57
|
+
expect(await request.text()).toEqual("");
|
|
58
|
+
return response.once(
|
|
59
|
+
context.status(200),
|
|
60
|
+
context.json({
|
|
61
|
+
success: true,
|
|
62
|
+
errors: [],
|
|
63
|
+
messages: [],
|
|
64
|
+
result: {
|
|
65
|
+
buckets: [
|
|
66
|
+
{
|
|
67
|
+
name: "bucket-1-local-once",
|
|
68
|
+
creation_date: "01-01-2001",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "bucket-2-local-once",
|
|
72
|
+
creation_date: "01-01-2001",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
);
|
|
73
81
|
await runWrangler("r2 bucket list");
|
|
74
82
|
|
|
75
83
|
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
@@ -79,21 +87,6 @@ describe("wrangler", () => {
|
|
|
79
87
|
});
|
|
80
88
|
|
|
81
89
|
describe("create", () => {
|
|
82
|
-
function mockCreateRequest(expectedBucketName: string) {
|
|
83
|
-
const requests = { count: 0 };
|
|
84
|
-
setMockResponse(
|
|
85
|
-
"/accounts/:accountId/r2/buckets",
|
|
86
|
-
"POST",
|
|
87
|
-
([_url, accountId], { body }) => {
|
|
88
|
-
expect(accountId).toEqual("some-account-id");
|
|
89
|
-
const bucketName = JSON.parse(body as string).name;
|
|
90
|
-
expect(bucketName).toEqual(expectedBucketName);
|
|
91
|
-
requests.count += 1;
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
return requests;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
90
|
it("should error if no bucket name is given", async () => {
|
|
98
91
|
await expect(
|
|
99
92
|
runWrangler("r2 bucket create")
|
|
@@ -148,32 +141,35 @@ describe("wrangler", () => {
|
|
|
148
141
|
`);
|
|
149
142
|
});
|
|
150
143
|
|
|
151
|
-
it("should create a bucket", async () => {
|
|
152
|
-
|
|
144
|
+
it("should create a bucket & check request inputs", async () => {
|
|
145
|
+
msw.use(
|
|
146
|
+
rest.post(
|
|
147
|
+
"*/accounts/:accountId/r2/buckets",
|
|
148
|
+
async (request, response, context) => {
|
|
149
|
+
const { accountId } = request.params;
|
|
150
|
+
expect(accountId).toEqual("some-account-id");
|
|
151
|
+
expect(await request.json()).toEqual({ name: "testBucket" });
|
|
152
|
+
response.once(
|
|
153
|
+
context.status(200),
|
|
154
|
+
context.json({
|
|
155
|
+
success: true,
|
|
156
|
+
errors: [],
|
|
157
|
+
messages: [],
|
|
158
|
+
result: {},
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
);
|
|
153
164
|
await runWrangler("r2 bucket create testBucket");
|
|
154
165
|
expect(std.out).toMatchInlineSnapshot(`
|
|
155
166
|
"Creating bucket testBucket.
|
|
156
167
|
Created bucket testBucket."
|
|
157
168
|
`);
|
|
158
|
-
expect(requests.count).toEqual(1);
|
|
159
169
|
});
|
|
160
170
|
});
|
|
161
171
|
|
|
162
172
|
describe("delete", () => {
|
|
163
|
-
function mockDeleteRequest(expectedBucketName: string) {
|
|
164
|
-
const requests = { count: 0 };
|
|
165
|
-
setMockResponse(
|
|
166
|
-
"/accounts/:accountId/r2/buckets/:bucketName",
|
|
167
|
-
"DELETE",
|
|
168
|
-
([_url, accountId, bucketName]) => {
|
|
169
|
-
expect(accountId).toEqual("some-account-id");
|
|
170
|
-
expect(bucketName).toEqual(expectedBucketName);
|
|
171
|
-
requests.count += 1;
|
|
172
|
-
}
|
|
173
|
-
);
|
|
174
|
-
return requests;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
173
|
it("should error if no bucket name is given", async () => {
|
|
178
174
|
await expect(
|
|
179
175
|
runWrangler("r2 bucket delete")
|
|
@@ -228,23 +224,42 @@ describe("wrangler", () => {
|
|
|
228
224
|
`);
|
|
229
225
|
});
|
|
230
226
|
|
|
231
|
-
it("should delete a bucket specified by name", async () => {
|
|
232
|
-
|
|
227
|
+
it("should delete a bucket specified by name & check requests inputs", async () => {
|
|
228
|
+
msw.use(
|
|
229
|
+
rest.delete(
|
|
230
|
+
"*/accounts/:accountId/r2/buckets/:bucketName",
|
|
231
|
+
async (request, response, context) => {
|
|
232
|
+
const { accountId, bucketName } = request.params;
|
|
233
|
+
expect(accountId).toEqual("some-account-id");
|
|
234
|
+
expect(bucketName).toEqual("some-bucket");
|
|
235
|
+
expect(await request.text()).toEqual("");
|
|
236
|
+
expect(request.headers.get("authorization")).toEqual(
|
|
237
|
+
"Bearer some-api-token"
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
return response.once(
|
|
241
|
+
context.status(200),
|
|
242
|
+
context.json({
|
|
243
|
+
success: true,
|
|
244
|
+
errors: [],
|
|
245
|
+
messages: [],
|
|
246
|
+
result: null,
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
)
|
|
251
|
+
);
|
|
233
252
|
await runWrangler(`r2 bucket delete some-bucket`);
|
|
234
|
-
expect(
|
|
253
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
254
|
+
"Deleting bucket some-bucket.
|
|
255
|
+
Deleted bucket some-bucket."
|
|
256
|
+
`);
|
|
235
257
|
});
|
|
236
258
|
});
|
|
237
259
|
});
|
|
238
260
|
|
|
239
261
|
describe("r2 object", () => {
|
|
240
262
|
it("should download R2 object from bucket", async () => {
|
|
241
|
-
setMockFetchR2Objects({
|
|
242
|
-
accountId: "some-account-id",
|
|
243
|
-
bucketName: "bucketName-object-test",
|
|
244
|
-
objectName: "wormhole-img.png",
|
|
245
|
-
mockResponse: "R2-objects-test-data",
|
|
246
|
-
});
|
|
247
|
-
|
|
248
263
|
await runWrangler(
|
|
249
264
|
`r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png`
|
|
250
265
|
);
|
|
@@ -256,11 +271,6 @@ describe("wrangler", () => {
|
|
|
256
271
|
});
|
|
257
272
|
|
|
258
273
|
it("should upload R2 object from bucket", async () => {
|
|
259
|
-
setMockFetchR2Objects({
|
|
260
|
-
accountId: "some-account-id",
|
|
261
|
-
bucketName: "bucketName-object-test",
|
|
262
|
-
objectName: "wormhole-img.png",
|
|
263
|
-
});
|
|
264
274
|
fs.writeFileSync("wormhole-img.png", "passageway");
|
|
265
275
|
await runWrangler(
|
|
266
276
|
`r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png`
|
|
@@ -272,15 +282,52 @@ describe("wrangler", () => {
|
|
|
272
282
|
`);
|
|
273
283
|
});
|
|
274
284
|
|
|
275
|
-
it("should pass all fetch option flags into requestInit", async () => {
|
|
285
|
+
it("should pass all fetch option flags into requestInit & check request inputs", async () => {
|
|
286
|
+
msw.use(
|
|
287
|
+
rest.put(
|
|
288
|
+
"*/accounts/:accountId/r2/buckets/:bucketName/objects/:objectName",
|
|
289
|
+
(request, response, context) => {
|
|
290
|
+
const { accountId, bucketName, objectName } = request.params;
|
|
291
|
+
expect(accountId).toEqual("some-account-id");
|
|
292
|
+
expect(bucketName).toEqual("bucketName-object-test");
|
|
293
|
+
expect(objectName).toEqual("wormhole-img.png");
|
|
294
|
+
const headersObject = request.headers.all();
|
|
295
|
+
delete headersObject["user-agent"];
|
|
296
|
+
expect(headersObject).toMatchInlineSnapshot(`
|
|
297
|
+
Object {
|
|
298
|
+
"accept": "*/*",
|
|
299
|
+
"accept-encoding": "gzip,deflate",
|
|
300
|
+
"authorization": "Bearer some-api-token",
|
|
301
|
+
"cache-control": "cache-control-mock",
|
|
302
|
+
"connection": "close",
|
|
303
|
+
"content-disposition": "content-disposition-mock",
|
|
304
|
+
"content-encoding": "content-encoding-mock",
|
|
305
|
+
"content-language": "content-lang-mock",
|
|
306
|
+
"content-length": "10",
|
|
307
|
+
"content-type": "content-type-mock",
|
|
308
|
+
"expires": "expire-time-mock",
|
|
309
|
+
"host": "api.cloudflare.com",
|
|
310
|
+
}
|
|
311
|
+
`);
|
|
312
|
+
response.once(
|
|
313
|
+
context.status(200),
|
|
314
|
+
context.json({
|
|
315
|
+
success: true,
|
|
316
|
+
errors: [],
|
|
317
|
+
messages: [],
|
|
318
|
+
result: {
|
|
319
|
+
accountId: "some-account-id",
|
|
320
|
+
bucketName: "bucketName-object-test",
|
|
321
|
+
objectName: "wormhole-img.png",
|
|
322
|
+
},
|
|
323
|
+
})
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
)
|
|
327
|
+
);
|
|
276
328
|
fs.writeFileSync("wormhole-img.png", "passageway");
|
|
277
|
-
setMockFetchR2Objects({
|
|
278
|
-
accountId: "some-account-id",
|
|
279
|
-
bucketName: "bucketName-object-test",
|
|
280
|
-
objectName: "wormhole-img.png",
|
|
281
|
-
});
|
|
282
329
|
const flags =
|
|
283
|
-
"--ct content-type --cd content-disposition --ce content-encoding --cl content-lang --cc cache-control --e expire-time";
|
|
330
|
+
"--ct content-type-mock --cd content-disposition-mock --ce content-encoding-mock --cl content-lang-mock --cc cache-control-mock --e expire-time-mock";
|
|
284
331
|
|
|
285
332
|
await runWrangler(
|
|
286
333
|
`r2 object put bucketName-object-test/wormhole-img.png ${flags} --file wormhole-img.png`
|
|
@@ -293,12 +340,6 @@ describe("wrangler", () => {
|
|
|
293
340
|
});
|
|
294
341
|
|
|
295
342
|
it("should delete R2 object from bucket", async () => {
|
|
296
|
-
setMockFetchR2Objects({
|
|
297
|
-
accountId: "some-account-id",
|
|
298
|
-
bucketName: "bucketName-object-test",
|
|
299
|
-
objectName: "wormhole-img.png",
|
|
300
|
-
});
|
|
301
|
-
|
|
302
343
|
await runWrangler(
|
|
303
344
|
`r2 object delete bucketName-object-test/wormhole-img.png`
|
|
304
345
|
);
|
|
@@ -311,12 +352,6 @@ describe("wrangler", () => {
|
|
|
311
352
|
|
|
312
353
|
it("should not allow `--pipe` & `--file` to run together", async () => {
|
|
313
354
|
fs.writeFileSync("wormhole-img.png", "passageway");
|
|
314
|
-
setMockFetchR2Objects({
|
|
315
|
-
accountId: "some-account-id",
|
|
316
|
-
bucketName: "bucketName-object-test",
|
|
317
|
-
objectName: "wormhole-img.png",
|
|
318
|
-
});
|
|
319
|
-
|
|
320
355
|
await expect(
|
|
321
356
|
runWrangler(
|
|
322
357
|
`r2 object put bucketName-object-test/wormhole-img.png --pipe --file wormhole-img.png`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
2
3
|
import * as TOML from "@iarna/toml";
|
|
3
4
|
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
4
5
|
import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
|
|
@@ -95,6 +96,83 @@ describe("wrangler secret", () => {
|
|
|
95
96
|
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
96
97
|
});
|
|
97
98
|
|
|
99
|
+
it("should create secret:bulk", async () => {
|
|
100
|
+
writeFileSync(
|
|
101
|
+
"secret.json",
|
|
102
|
+
JSON.stringify({
|
|
103
|
+
"secret-name-1": "secret_text",
|
|
104
|
+
"secret-name-2": "secret_text",
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// User counter to pass different secrets to the request mock
|
|
109
|
+
let counter = 0;
|
|
110
|
+
setMockResponse(
|
|
111
|
+
`/accounts/:accountId/workers/scripts/:scriptName/secrets`,
|
|
112
|
+
"PUT",
|
|
113
|
+
([_url, accountId]) => {
|
|
114
|
+
expect(accountId).toEqual("some-account-id");
|
|
115
|
+
counter++;
|
|
116
|
+
|
|
117
|
+
return { name: `secret-name-${counter}`, type: "secret_text" };
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
await runWrangler("secret:bulk ./secret.json --name script-name");
|
|
122
|
+
|
|
123
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
124
|
+
"🌀 Creating the secrets for the Worker \\"script-name\\"
|
|
125
|
+
✨ Successfully created secret for key: secret-name-1
|
|
126
|
+
✨ Successfully created secret for key: secret-name-2
|
|
127
|
+
✨ Finished processing secrets JSON file"
|
|
128
|
+
`);
|
|
129
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should handle failed secret:bulk", async () => {
|
|
133
|
+
writeFileSync(
|
|
134
|
+
"secret.json",
|
|
135
|
+
JSON.stringify({
|
|
136
|
+
"secret-name-1": "secret_text",
|
|
137
|
+
"secret-name-2": "secret_text",
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// User counter to pass different secrets to the request mock
|
|
142
|
+
let counter = 0;
|
|
143
|
+
setMockResponse(
|
|
144
|
+
`/accounts/:accountId/workers/scripts/:scriptName/secrets`,
|
|
145
|
+
"PUT",
|
|
146
|
+
([_url, accountId]) => {
|
|
147
|
+
expect(accountId).toEqual("some-account-id");
|
|
148
|
+
counter++;
|
|
149
|
+
|
|
150
|
+
return Promise.reject(
|
|
151
|
+
new Error(`Failed to create secret ${counter}`)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
await runWrangler("secret:bulk ./secret.json --name script-name");
|
|
157
|
+
|
|
158
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
159
|
+
"🌀 Creating the secrets for the Worker \\"script-name\\"
|
|
160
|
+
✨ Finished processing secrets JSON file"
|
|
161
|
+
`);
|
|
162
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
163
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-1:[0m
|
|
164
|
+
|
|
165
|
+
Failed to create secret 1
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-2:[0m
|
|
169
|
+
|
|
170
|
+
Failed to create secret 2
|
|
171
|
+
|
|
172
|
+
"
|
|
173
|
+
`);
|
|
174
|
+
});
|
|
175
|
+
|
|
98
176
|
it("should create a secret: legacy envs", async () => {
|
|
99
177
|
mockPrompt({
|
|
100
178
|
text: "Enter a secret value:",
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { render } from "ink-testing-library";
|
|
2
|
+
import { rest } from "msw";
|
|
2
3
|
import React from "react";
|
|
3
4
|
import { writeAuthConfigFile } from "../user";
|
|
4
5
|
import { getUserInfo, WhoAmI } from "../whoami";
|
|
5
|
-
import {
|
|
6
|
-
createFetchResult,
|
|
7
|
-
setMockRawResponse,
|
|
8
|
-
setMockResponse,
|
|
9
|
-
unsetAllMocks,
|
|
10
|
-
} from "./helpers/mock-cfetch";
|
|
11
6
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
12
7
|
import { useMockIsTTY } from "./helpers/mock-istty";
|
|
8
|
+
import { msw } from "./helpers/msw";
|
|
13
9
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
14
10
|
import type { UserInfo } from "../whoami";
|
|
15
11
|
|
|
@@ -26,7 +22,6 @@ describe("getUserInfo()", () => {
|
|
|
26
22
|
|
|
27
23
|
afterEach(() => {
|
|
28
24
|
process.env = ENV_COPY;
|
|
29
|
-
unsetAllMocks();
|
|
30
25
|
});
|
|
31
26
|
|
|
32
27
|
it("should return undefined if there is no config file", async () => {
|
|
@@ -44,12 +39,47 @@ describe("getUserInfo()", () => {
|
|
|
44
39
|
process.env = {
|
|
45
40
|
CLOUDFLARE_API_TOKEN: "123456789",
|
|
46
41
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
msw.use(
|
|
43
|
+
rest.get("*/user", (_, res, ctx) => {
|
|
44
|
+
return res.once(
|
|
45
|
+
ctx.status(200),
|
|
46
|
+
ctx.json({
|
|
47
|
+
success: false,
|
|
48
|
+
errors: [
|
|
49
|
+
{
|
|
50
|
+
code: 9109,
|
|
51
|
+
message: "Uauthorized to access requested resource",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
messages: [],
|
|
55
|
+
result: {},
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}),
|
|
59
|
+
rest.get("*/accounts", (request, res, ctx) => {
|
|
60
|
+
const headersObject = request.headers.all();
|
|
61
|
+
delete headersObject["user-agent"];
|
|
62
|
+
|
|
63
|
+
expect(headersObject).toMatchInlineSnapshot(`
|
|
64
|
+
Object {
|
|
65
|
+
"accept": "*/*",
|
|
66
|
+
"accept-encoding": "gzip,deflate",
|
|
67
|
+
"authorization": "Bearer 123456789",
|
|
68
|
+
"connection": "close",
|
|
69
|
+
"host": "api.cloudflare.com",
|
|
70
|
+
}
|
|
71
|
+
`);
|
|
72
|
+
return res.once(
|
|
73
|
+
ctx.status(200),
|
|
74
|
+
ctx.json({
|
|
75
|
+
success: true,
|
|
76
|
+
errors: [],
|
|
77
|
+
messages: [],
|
|
78
|
+
result: [],
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
})
|
|
51
82
|
);
|
|
52
|
-
setMockResponse("/accounts", () => []);
|
|
53
83
|
const userInfo = await getUserInfo();
|
|
54
84
|
expect(userInfo?.email).toBeUndefined();
|
|
55
85
|
});
|
|
@@ -58,16 +88,6 @@ describe("getUserInfo()", () => {
|
|
|
58
88
|
process.env = {
|
|
59
89
|
CLOUDFLARE_API_TOKEN: "123456789",
|
|
60
90
|
};
|
|
61
|
-
setMockResponse("/user", () => {
|
|
62
|
-
return { email: "user@example.com" };
|
|
63
|
-
});
|
|
64
|
-
setMockResponse("/accounts", () => {
|
|
65
|
-
return [
|
|
66
|
-
{ name: "Account One", id: "account-1" },
|
|
67
|
-
{ name: "Account Two", id: "account-2" },
|
|
68
|
-
{ name: "Account Three", id: "account-3" },
|
|
69
|
-
];
|
|
70
|
-
});
|
|
71
91
|
|
|
72
92
|
const userInfo = await getUserInfo();
|
|
73
93
|
expect(userInfo).toEqual({
|
|
@@ -87,13 +107,6 @@ describe("getUserInfo()", () => {
|
|
|
87
107
|
CLOUDFLARE_API_KEY: "123456789",
|
|
88
108
|
CLOUDFLARE_EMAIL: "user@example.com",
|
|
89
109
|
};
|
|
90
|
-
setMockResponse("/accounts", () => {
|
|
91
|
-
return [
|
|
92
|
-
{ name: "Account One", id: "account-1" },
|
|
93
|
-
{ name: "Account Two", id: "account-2" },
|
|
94
|
-
{ name: "Account Three", id: "account-3" },
|
|
95
|
-
];
|
|
96
|
-
});
|
|
97
110
|
|
|
98
111
|
const userInfo = await getUserInfo();
|
|
99
112
|
expect(userInfo).toEqual({
|
|
@@ -114,13 +127,6 @@ describe("getUserInfo()", () => {
|
|
|
114
127
|
CLOUDFLARE_EMAIL: "user@example.com",
|
|
115
128
|
CLOUDFLARE_API_TOKEN: "123456789",
|
|
116
129
|
};
|
|
117
|
-
setMockResponse("/accounts", () => {
|
|
118
|
-
return [
|
|
119
|
-
{ name: "Account One", id: "account-1" },
|
|
120
|
-
{ name: "Account Two", id: "account-2" },
|
|
121
|
-
{ name: "Account Three", id: "account-3" },
|
|
122
|
-
];
|
|
123
|
-
});
|
|
124
130
|
|
|
125
131
|
const userInfo = await getUserInfo();
|
|
126
132
|
expect(userInfo).toEqual({
|
|
@@ -145,18 +151,6 @@ describe("getUserInfo()", () => {
|
|
|
145
151
|
|
|
146
152
|
it("should return the user's email and accounts if authenticated via config token", async () => {
|
|
147
153
|
writeAuthConfigFile({ oauth_token: "some-oauth-token" });
|
|
148
|
-
|
|
149
|
-
setMockResponse("/user", () => {
|
|
150
|
-
return { email: "user@example.com" };
|
|
151
|
-
});
|
|
152
|
-
setMockResponse("/accounts", () => {
|
|
153
|
-
return [
|
|
154
|
-
{ name: "Account One", id: "account-1" },
|
|
155
|
-
{ name: "Account Two", id: "account-2" },
|
|
156
|
-
{ name: "Account Three", id: "account-3" },
|
|
157
|
-
];
|
|
158
|
-
});
|
|
159
|
-
|
|
160
154
|
const userInfo = await getUserInfo();
|
|
161
155
|
|
|
162
156
|
expect(userInfo).toEqual({
|
|
@@ -173,26 +167,17 @@ describe("getUserInfo()", () => {
|
|
|
173
167
|
|
|
174
168
|
it("should display a warning message if the config file contains a legacy api_token field", async () => {
|
|
175
169
|
writeAuthConfigFile({ api_token: "API_TOKEN" });
|
|
176
|
-
setMockResponse("/user", () => {
|
|
177
|
-
return { email: "user@example.com" };
|
|
178
|
-
});
|
|
179
|
-
setMockResponse("/accounts", () => {
|
|
180
|
-
return [
|
|
181
|
-
{ name: "Account One", id: "account-1" },
|
|
182
|
-
{ name: "Account Two", id: "account-2" },
|
|
183
|
-
{ name: "Account Three", id: "account-3" },
|
|
184
|
-
];
|
|
185
|
-
});
|
|
186
170
|
await getUserInfo();
|
|
171
|
+
|
|
187
172
|
expect(std.warn).toMatchInlineSnapshot(`
|
|
188
|
-
|
|
173
|
+
"[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mIt looks like you have used Wrangler 1's \`config\` command to login with an API token.[0m
|
|
189
174
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
175
|
+
This is no longer supported in the current version of Wrangler.
|
|
176
|
+
If you wish to authenticate via an API token then please set the \`CLOUDFLARE_API_TOKEN\`
|
|
177
|
+
environment variable.
|
|
193
178
|
|
|
194
|
-
|
|
195
|
-
|
|
179
|
+
"
|
|
180
|
+
`);
|
|
196
181
|
});
|
|
197
182
|
});
|
|
198
183
|
|
package/src/api/dev.ts
CHANGED
|
@@ -19,7 +19,8 @@ interface DevOptions {
|
|
|
19
19
|
nodeCompat?: boolean;
|
|
20
20
|
compatibilityDate?: string;
|
|
21
21
|
compatibilityFlags?: string[];
|
|
22
|
-
|
|
22
|
+
persist?: boolean;
|
|
23
|
+
persistTo?: string;
|
|
23
24
|
liveReload?: boolean;
|
|
24
25
|
watch?: boolean;
|
|
25
26
|
vars?: {
|
package/src/dev/dev.tsx
CHANGED
|
@@ -136,7 +136,7 @@ export type DevProps = {
|
|
|
136
136
|
upstreamProtocol: "https" | "http";
|
|
137
137
|
localProtocol: "https" | "http";
|
|
138
138
|
localUpstream: string | undefined;
|
|
139
|
-
|
|
139
|
+
localPersistencePath: string | null;
|
|
140
140
|
liveReload: boolean;
|
|
141
141
|
bindings: CfWorkerInit["bindings"];
|
|
142
142
|
define: Config["define"];
|
|
@@ -276,7 +276,7 @@ function DevSession(props: DevSessionProps) {
|
|
|
276
276
|
ip={props.ip}
|
|
277
277
|
rules={props.rules}
|
|
278
278
|
inspectorPort={props.inspectorPort}
|
|
279
|
-
|
|
279
|
+
localPersistencePath={props.localPersistencePath}
|
|
280
280
|
liveReload={props.liveReload}
|
|
281
281
|
crons={props.crons}
|
|
282
282
|
localProtocol={props.localProtocol}
|
package/src/dev/local.tsx
CHANGED
|
@@ -42,7 +42,7 @@ export interface LocalProps {
|
|
|
42
42
|
ip: string;
|
|
43
43
|
rules: Config["rules"];
|
|
44
44
|
inspectorPort: number;
|
|
45
|
-
|
|
45
|
+
localPersistencePath: string | null;
|
|
46
46
|
liveReload: boolean;
|
|
47
47
|
crons: Config["triggers"]["crons"];
|
|
48
48
|
localProtocol: "http" | "https";
|
|
@@ -77,7 +77,7 @@ function useLocalWorker({
|
|
|
77
77
|
port,
|
|
78
78
|
inspectorPort,
|
|
79
79
|
rules,
|
|
80
|
-
|
|
80
|
+
localPersistencePath,
|
|
81
81
|
liveReload,
|
|
82
82
|
ip,
|
|
83
83
|
crons,
|
|
@@ -93,16 +93,6 @@ function useLocalWorker({
|
|
|
93
93
|
const local = useRef<ChildProcess>();
|
|
94
94
|
const removeSignalExitListener = useRef<() => void>();
|
|
95
95
|
const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
|
|
96
|
-
// if we're using local persistence for data, we should use the cwd
|
|
97
|
-
// as an explicit path, or else it'll use the temp dir
|
|
98
|
-
// which disappears when dev ends
|
|
99
|
-
const localPersistencePath = enableLocalPersistence
|
|
100
|
-
? // Maybe we could make the path configurable as well?
|
|
101
|
-
path.join(process.cwd(), "wrangler-local-state")
|
|
102
|
-
: // We otherwise choose null, but choose true later
|
|
103
|
-
// so that it's persisted in the temp dir across a dev session
|
|
104
|
-
// even when we change source and reload
|
|
105
|
-
null;
|
|
106
96
|
|
|
107
97
|
useEffect(() => {
|
|
108
98
|
if (bindings.services && bindings.services.length > 0) {
|
package/src/dev/start-server.ts
CHANGED
|
@@ -80,7 +80,7 @@ export async function startDevServer(
|
|
|
80
80
|
ip: props.ip,
|
|
81
81
|
rules: props.rules,
|
|
82
82
|
inspectorPort: props.inspectorPort,
|
|
83
|
-
|
|
83
|
+
localPersistencePath: props.localPersistencePath,
|
|
84
84
|
liveReload: props.liveReload,
|
|
85
85
|
crons: props.crons,
|
|
86
86
|
localProtocol: props.localProtocol,
|
|
@@ -203,7 +203,7 @@ export async function startLocalServer({
|
|
|
203
203
|
port,
|
|
204
204
|
inspectorPort,
|
|
205
205
|
rules,
|
|
206
|
-
|
|
206
|
+
localPersistencePath,
|
|
207
207
|
liveReload,
|
|
208
208
|
ip,
|
|
209
209
|
crons,
|
|
@@ -222,17 +222,6 @@ export async function startLocalServer({
|
|
|
222
222
|
inspectorUrl = url;
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
-
// if we're using local persistence for data, we should use the cwd
|
|
226
|
-
// as an explicit path, or else it'll use the temp dir
|
|
227
|
-
// which disappears when dev ends
|
|
228
|
-
const localPersistencePath = enableLocalPersistence
|
|
229
|
-
? // Maybe we could make the path configurable as well?
|
|
230
|
-
path.join(process.cwd(), "wrangler-local-state")
|
|
231
|
-
: // We otherwise choose null, but choose true later
|
|
232
|
-
// so that it's persisted in the temp dir across a dev session
|
|
233
|
-
// even when we change source and reload
|
|
234
|
-
null;
|
|
235
|
-
|
|
236
225
|
const abortController = new AbortController();
|
|
237
226
|
async function startLocalWorker() {
|
|
238
227
|
if (!bundle || !format) return;
|