wrangler 2.0.12 → 2.0.14

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.0.12",
3
+ "version": "2.0.14",
4
4
  "author": "wrangler@cloudflare.com",
5
5
  "description": "Command-line interface for all things Cloudflare Workers",
6
6
  "bin": {
@@ -99,7 +99,7 @@
99
99
  "timeago.js": "^4.0.2",
100
100
  "tmp-promise": "^3.0.3",
101
101
  "ts-dedent": "^2.2.0",
102
- "undici": "^5.3.0",
102
+ "undici": "^5.5.1",
103
103
  "update-check": "^1.5.4",
104
104
  "ws": "^8.5.0",
105
105
  "yargs": "^17.4.1"
@@ -75,3 +75,33 @@ jest.mock("../dev/dev", () => {
75
75
  // Make sure that we don't accidentally try to open a browser window when running tests.
76
76
  // We will actually provide a mock implementation for `openInBrowser()` within relevant tests.
77
77
  jest.mock("../open-in-browser");
78
+
79
+ // Mock the functions involved in getAuthURL so we don't take snapshots of the constantly changing URL.
80
+ jest.mock("../generate-auth-url", () => {
81
+ return {
82
+ generateRandomState: jest.fn().mockImplementation(() => "MOCK_STATE_PARAM"),
83
+ generateAuthUrl: jest
84
+ .fn()
85
+ .mockImplementation(({ authUrl, clientId, callbackUrl, scopes }) => {
86
+ return (
87
+ authUrl +
88
+ `?response_type=code&` +
89
+ `client_id=${encodeURIComponent(clientId)}&` +
90
+ `redirect_uri=${encodeURIComponent(callbackUrl)}&` +
91
+ // we add offline_access manually for every request
92
+ `scope=${encodeURIComponent(
93
+ [...scopes, "offline_access"].join(" ")
94
+ )}&` +
95
+ `state=MOCK_STATE_PARAM&` +
96
+ `code_challenge=${encodeURIComponent("MOCK_CODE_CHALLENGE")}&` +
97
+ `code_challenge_method=S256`
98
+ );
99
+ }),
100
+ };
101
+ });
102
+
103
+ jest.mock("../generate-random-state", () => {
104
+ return {
105
+ generateRandomState: jest.fn().mockImplementation(() => "MOCK_STATE_PARAM"),
106
+ };
107
+ });
@@ -448,11 +448,10 @@ describe("wrangler", () => {
448
448
  });
449
449
 
450
450
  it("should put a key with a value loaded from a given path", async () => {
451
- const buf = Buffer.from("file-contents", "utf-8");
452
- writeFileSync("foo.txt", buf);
451
+ writeFileSync("foo.txt", "file-contents", "utf-8");
453
452
  const requests = mockKeyPutRequest("some-namespace-id", {
454
453
  key: "my-key",
455
- value: buf,
454
+ value: "file-contents",
456
455
  });
457
456
  await runWrangler(
458
457
  "kv:key put my-key --namespace-id some-namespace-id --path foo.txt"
@@ -464,26 +463,6 @@ describe("wrangler", () => {
464
463
  expect(requests.count).toEqual(1);
465
464
  });
466
465
 
467
- it("should put a key with a binary value loaded from a given path", async () => {
468
- const buf = Buffer.from(
469
- "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
470
- "base64"
471
- );
472
- writeFileSync("test.png", buf);
473
- const requests = mockKeyPutRequest("another-namespace-id", {
474
- key: "my-key",
475
- value: buf,
476
- });
477
- await runWrangler(
478
- "kv:key put my-key --namespace-id another-namespace-id --path test.png"
479
- );
480
- expect(std.out).toMatchInlineSnapshot(
481
- `"Writing the contents of test.png to the key \\"my-key\\" on namespace another-namespace-id."`
482
- );
483
- expect(std.err).toMatchInlineSnapshot(`""`);
484
- expect(requests.count).toEqual(1);
485
- });
486
-
487
466
  it("should error if no key is provided", async () => {
488
467
  await expect(
489
468
  runWrangler("kv:key put")
@@ -66,7 +66,6 @@ describe("publish", () => {
66
66
  writeWorkerSource();
67
67
  mockSubDomainRequest();
68
68
  mockUploadWorkerRequest();
69
-
70
69
  mockOAuthServerCallback();
71
70
  const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
72
71
  mockGrantAuthorization({ respondWith: "success" });
@@ -79,6 +78,7 @@ describe("publish", () => {
79
78
 
80
79
  expect(std.out).toMatchInlineSnapshot(`
81
80
  "Attempting to login via OAuth...
81
+ Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
82
82
  Successfully logged in.
83
83
  Uploaded test-name (TIMINGS)
84
84
  Published test-name (TIMINGS)
@@ -108,6 +108,7 @@ describe("publish", () => {
108
108
 
109
109
  expect(std.out).toMatchInlineSnapshot(`
110
110
  "Attempting to login via OAuth...
111
+ Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
111
112
  Successfully logged in.
112
113
  Uploaded test-name (TIMINGS)
113
114
  Published test-name (TIMINGS)
@@ -46,6 +46,7 @@ describe("User", () => {
46
46
 
47
47
  expect(std.out).toMatchInlineSnapshot(`
48
48
  "Attempting to login via OAuth...
49
+ Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
49
50
  Successfully logged in."
50
51
  `);
51
52
 
@@ -0,0 +1,33 @@
1
+ interface GenerateAuthUrlProps {
2
+ authUrl: string;
3
+ clientId: string;
4
+ callbackUrl: string;
5
+ scopes: string[];
6
+ stateQueryParam: string;
7
+ codeChallenge: string;
8
+ }
9
+
10
+ /**
11
+ * generateAuthUrl was extracted from getAuthURL in user.tsx
12
+ * to make it possible to mock the generated URL
13
+ */
14
+ export const generateAuthUrl = ({
15
+ authUrl,
16
+ clientId,
17
+ callbackUrl,
18
+ scopes,
19
+ stateQueryParam,
20
+ codeChallenge,
21
+ }: GenerateAuthUrlProps) => {
22
+ return (
23
+ authUrl +
24
+ `?response_type=code&` +
25
+ `client_id=${encodeURIComponent(clientId)}&` +
26
+ `redirect_uri=${encodeURIComponent(callbackUrl)}&` +
27
+ // we add offline_access manually for every request
28
+ `scope=${encodeURIComponent([...scopes, "offline_access"].join(" "))}&` +
29
+ `state=${stateQueryParam}&` +
30
+ `code_challenge=${encodeURIComponent(codeChallenge)}&` +
31
+ `code_challenge_method=S256`
32
+ );
33
+ };
@@ -0,0 +1,16 @@
1
+ import { webcrypto as crypto } from "node:crypto";
2
+ import { PKCE_CHARSET } from "./user";
3
+
4
+ /**
5
+ * Generates random state to be passed for anti-csrf.
6
+ * extracted from user.tsx to make it possible to
7
+ * mock the generated URL
8
+ */
9
+ export function generateRandomState(lengthOfState: number): string {
10
+ const output = new Uint32Array(lengthOfState);
11
+ // @ts-expect-error crypto's types aren't there yet
12
+ crypto.getRandomValues(output);
13
+ return Array.from(output)
14
+ .map((num: number) => PKCE_CHARSET[num % PKCE_CHARSET.length])
15
+ .join("");
16
+ }
package/src/index.tsx CHANGED
@@ -48,7 +48,6 @@ import {
48
48
  parsePackageJSON,
49
49
  parseTOML,
50
50
  readFileSync,
51
- readFileSyncToBuffer,
52
51
  } from "./parse";
53
52
  import publish from "./publish";
54
53
  import { createR2Bucket, deleteR2Bucket, listR2Buckets } from "./r2";
@@ -2273,7 +2272,7 @@ function createCLIParser(argv: string[]) {
2273
2272
  const namespaceId = getKVNamespaceId(args, config);
2274
2273
  // One of `args.path` and `args.value` must be defined
2275
2274
  const value = args.path
2276
- ? readFileSyncToBuffer(args.path)
2275
+ ? readFileSync(args.path)
2277
2276
  : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2278
2277
  args.value!;
2279
2278
 
package/src/kv.ts CHANGED
@@ -111,7 +111,7 @@ export async function deleteKVNamespace(
111
111
  */
112
112
  export interface KeyValue {
113
113
  key: string;
114
- value: string | Buffer;
114
+ value: string;
115
115
  expiration?: number;
116
116
  expiration_ttl?: number;
117
117
  metadata?: object;
@@ -10,10 +10,8 @@ import { logger } from "./logger";
10
10
  * @param url the URL to point the browser at
11
11
  */
12
12
  export default async function openInBrowser(url: string): Promise<void> {
13
- const errorMessage = `Failed to open ${url} in a browser`;
14
-
15
13
  const childProcess = await open(url);
16
14
  childProcess.on("error", () => {
17
- logger.warn(errorMessage);
15
+ logger.warn("Failed to open");
18
16
  });
19
17
  }
package/src/parse.ts CHANGED
@@ -139,25 +139,6 @@ export function parseJSON<T>(input: string, file?: string): T {
139
139
  }
140
140
  }
141
141
 
142
- /**
143
- * Reads a file into a node Buffer.
144
- */
145
- export function readFileSyncToBuffer(file: string): Buffer {
146
- try {
147
- return fs.readFileSync(file);
148
- } catch (err) {
149
- const { message } = err as Error;
150
- throw new ParseError({
151
- text: `Could not read file: ${file}`,
152
- notes: [
153
- {
154
- text: message.replace(file, resolve(file)),
155
- },
156
- ],
157
- });
158
- }
159
- }
160
-
161
142
  /**
162
143
  * Reads a file and parses it based on its type.
163
144
  */
package/src/user.tsx CHANGED
@@ -223,6 +223,8 @@ import { fetch } from "undici";
223
223
  import { getCloudflareApiBaseUrl } from "./cfetch";
224
224
  import { purgeConfigCaches } from "./config-cache";
225
225
  import { getEnvironmentVariableFactory } from "./environment-variables";
226
+ import { generateAuthUrl } from "./generate-auth-url";
227
+ import { generateRandomState } from "./generate-random-state";
226
228
  import { logger } from "./logger";
227
229
  import openInBrowser from "./open-in-browser";
228
230
  import { parseTOML, readFileSync } from "./parse";
@@ -591,7 +593,7 @@ const RECOMMENDED_STATE_LENGTH = 32;
591
593
  /**
592
594
  * Character set to generate code verifier defined in rfc7636.
593
595
  */
594
- const PKCE_CHARSET =
596
+ export const PKCE_CHARSET =
595
597
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
596
598
 
597
599
  /**
@@ -641,17 +643,14 @@ export async function getAuthURL(scopes = ScopeKeys): Promise<string> {
641
643
  stateQueryParam,
642
644
  });
643
645
 
644
- return (
645
- AUTH_URL +
646
- `?response_type=code&` +
647
- `client_id=${encodeURIComponent(CLIENT_ID)}&` +
648
- `redirect_uri=${encodeURIComponent(CALLBACK_URL)}&` +
649
- // we add offline_access manually for every request
650
- `scope=${encodeURIComponent([...scopes, "offline_access"].join(" "))}&` +
651
- `state=${stateQueryParam}&` +
652
- `code_challenge=${encodeURIComponent(codeChallenge)}&` +
653
- `code_challenge_method=S256`
654
- );
646
+ return generateAuthUrl({
647
+ authUrl: AUTH_URL,
648
+ clientId: CLIENT_ID,
649
+ callbackUrl: CALLBACK_URL,
650
+ scopes,
651
+ stateQueryParam,
652
+ codeChallenge,
653
+ });
655
654
  }
656
655
 
657
656
  type TokenResponse =
@@ -863,18 +862,6 @@ async function generatePKCECodes(): Promise<PKCECodes> {
863
862
  return { codeChallenge, codeVerifier };
864
863
  }
865
864
 
866
- /**
867
- * Generates random state to be passed for anti-csrf.
868
- */
869
- function generateRandomState(lengthOfState: number): string {
870
- const output = new Uint32Array(lengthOfState);
871
- // @ts-expect-error crypto's types aren't there yet
872
- crypto.getRandomValues(output);
873
- return Array.from(output)
874
- .map((num: number) => PKCE_CHARSET[num % PKCE_CHARSET.length])
875
- .join("");
876
- }
877
-
878
865
  /**
879
866
  * Writes a a wrangler config file (auth credentials) to disk,
880
867
  * and updates the user auth state with the new credentials.
@@ -1013,6 +1000,7 @@ export async function login(props?: LoginProps): Promise<boolean> {
1013
1000
  server.listen(8976);
1014
1001
  });
1015
1002
 
1003
+ logger.log(`Opening a link in your default browser: ${urlToOpen}`);
1016
1004
  await openInBrowser(urlToOpen);
1017
1005
 
1018
1006
  return Promise.race([timerPromise, loginPromise]);
@@ -35,7 +35,7 @@ export default {
35
35
  } catch (e) {
36
36
  console.error(e);
37
37
  // if an error is thrown then serve from actual worker
38
- return worker.fetch(request);
38
+ return worker.fetch(request, env, ctx);
39
39
  // TODO: throw here if worker is not available
40
40
  // (which implies it may be a service-worker)
41
41
  }