wrangler 0.0.0-e978986 → 0.0.0-e9e9872

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.
Files changed (186) hide show
  1. package/README.md +7 -1
  2. package/bin/wrangler.js +114 -57
  3. package/kv-asset-handler.js +1 -0
  4. package/miniflare-dist/index.mjs +10 -2
  5. package/package.json +159 -152
  6. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  7. package/src/__tests__/config-cache.test.ts +30 -24
  8. package/src/__tests__/configuration.test.ts +3935 -3363
  9. package/src/__tests__/dev.test.tsx +1128 -949
  10. package/src/__tests__/guess-worker-format.test.ts +68 -68
  11. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  12. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  13. package/src/__tests__/helpers/mock-bin.ts +20 -20
  14. package/src/__tests__/helpers/mock-cfetch.ts +92 -92
  15. package/src/__tests__/helpers/mock-console.ts +49 -39
  16. package/src/__tests__/helpers/mock-dialogs.ts +94 -71
  17. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  18. package/src/__tests__/helpers/mock-istty.ts +65 -18
  19. package/src/__tests__/helpers/mock-kv.ts +26 -26
  20. package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
  21. package/src/__tests__/helpers/mock-process.ts +39 -0
  22. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  23. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  24. package/src/__tests__/helpers/run-in-tmp.ts +27 -28
  25. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  26. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  27. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  28. package/src/__tests__/https-options.test.ts +142 -109
  29. package/src/__tests__/index.test.ts +239 -233
  30. package/src/__tests__/init.test.ts +1605 -1180
  31. package/src/__tests__/jest.setup.ts +76 -33
  32. package/src/__tests__/kv.test.ts +1160 -991
  33. package/src/__tests__/logger.test.ts +100 -74
  34. package/src/__tests__/package-manager.test.ts +303 -303
  35. package/src/__tests__/pages.test.ts +1160 -563
  36. package/src/__tests__/parse.test.ts +252 -252
  37. package/src/__tests__/publish.test.ts +6426 -5299
  38. package/src/__tests__/pubsub.test.ts +367 -0
  39. package/src/__tests__/r2.test.ts +133 -133
  40. package/src/__tests__/route.test.ts +18 -18
  41. package/src/__tests__/secret.test.ts +470 -459
  42. package/src/__tests__/tail.test.ts +538 -530
  43. package/src/__tests__/user.test.ts +124 -112
  44. package/src/__tests__/whoami.test.tsx +208 -83
  45. package/src/__tests__/worker-namespace.test.ts +327 -0
  46. package/src/abort.d.ts +1 -1
  47. package/src/api/dev.ts +52 -0
  48. package/src/api/index.ts +1 -0
  49. package/src/bundle-reporter.tsx +29 -0
  50. package/src/bundle.ts +158 -146
  51. package/src/cfetch/index.ts +80 -80
  52. package/src/cfetch/internal.ts +92 -88
  53. package/src/cli.ts +21 -7
  54. package/src/config/config.ts +204 -195
  55. package/src/config/diagnostics.ts +61 -61
  56. package/src/config/environment.ts +390 -357
  57. package/src/config/index.ts +206 -193
  58. package/src/config/validation-helpers.ts +366 -357
  59. package/src/config/validation.ts +1573 -1367
  60. package/src/config-cache.ts +79 -41
  61. package/src/create-worker-preview.ts +206 -136
  62. package/src/create-worker-upload-form.ts +247 -238
  63. package/src/dev/dev-vars.ts +13 -13
  64. package/src/dev/dev.tsx +334 -336
  65. package/src/dev/local.tsx +310 -274
  66. package/src/dev/remote.tsx +366 -211
  67. package/src/dev/use-esbuild.ts +126 -94
  68. package/src/dev.tsx +538 -0
  69. package/src/dialogs.tsx +97 -97
  70. package/src/durable.ts +87 -87
  71. package/src/entry.ts +234 -228
  72. package/src/environment-variables.ts +23 -23
  73. package/src/errors.ts +6 -6
  74. package/src/faye-websocket.d.ts +6 -0
  75. package/src/generate.ts +33 -0
  76. package/src/git-client.ts +42 -0
  77. package/src/global-wrangler-config-path.ts +26 -0
  78. package/src/https-options.ts +84 -80
  79. package/src/index.tsx +1800 -2752
  80. package/src/init.ts +549 -0
  81. package/src/inspect.ts +593 -593
  82. package/src/intl-polyfill.d.ts +123 -123
  83. package/src/is-interactive.ts +12 -0
  84. package/src/kv.ts +299 -277
  85. package/src/logger.ts +46 -39
  86. package/src/miniflare-cli/enum-keys.ts +8 -8
  87. package/src/miniflare-cli/index.ts +43 -31
  88. package/src/miniflare-cli/request-context.ts +18 -18
  89. package/src/module-collection.ts +212 -212
  90. package/src/open-in-browser.ts +4 -6
  91. package/src/package-manager.ts +173 -128
  92. package/src/pages/build.tsx +202 -0
  93. package/src/pages/constants.ts +7 -0
  94. package/src/pages/deployments.tsx +101 -0
  95. package/src/pages/dev.tsx +964 -0
  96. package/src/pages/functions/buildPlugin.ts +105 -0
  97. package/src/pages/functions/buildWorker.ts +151 -0
  98. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  99. package/src/pages/functions/filepath-routing.ts +189 -0
  100. package/src/pages/functions/identifiers.ts +78 -0
  101. package/src/pages/functions/routes.ts +151 -0
  102. package/src/pages/index.tsx +84 -0
  103. package/src/pages/projects.tsx +157 -0
  104. package/src/pages/publish.tsx +335 -0
  105. package/src/pages/types.ts +40 -0
  106. package/src/pages/upload.tsx +396 -0
  107. package/src/pages/utils.ts +12 -0
  108. package/src/parse.ts +209 -125
  109. package/src/paths.ts +6 -6
  110. package/src/preview.ts +31 -0
  111. package/src/proxy.ts +400 -389
  112. package/src/publish.ts +702 -505
  113. package/src/pubsub/index.ts +286 -0
  114. package/src/pubsub/pubsub-commands.tsx +577 -0
  115. package/src/r2.ts +19 -19
  116. package/src/selfsigned.d.ts +23 -23
  117. package/src/sites.tsx +278 -201
  118. package/src/tail/filters.ts +108 -108
  119. package/src/tail/index.ts +217 -217
  120. package/src/tail/printing.ts +45 -45
  121. package/src/update-check.ts +11 -11
  122. package/src/user/choose-account.tsx +60 -0
  123. package/src/user/env-vars.ts +46 -0
  124. package/src/user/generate-auth-url.ts +33 -0
  125. package/src/user/generate-random-state.ts +16 -0
  126. package/src/user/index.ts +3 -0
  127. package/src/user/user.tsx +1170 -0
  128. package/src/whoami.tsx +61 -41
  129. package/src/worker-namespace.ts +190 -0
  130. package/src/worker.ts +110 -99
  131. package/src/zones.ts +76 -0
  132. package/templates/checked-fetch.js +17 -0
  133. package/templates/new-worker-scheduled.js +4 -4
  134. package/templates/new-worker-scheduled.ts +16 -16
  135. package/templates/new-worker.js +3 -3
  136. package/templates/new-worker.ts +15 -15
  137. package/templates/no-op-worker.js +10 -0
  138. package/templates/pages-template-plugin.ts +155 -0
  139. package/templates/pages-template-worker.ts +161 -0
  140. package/templates/static-asset-facade.js +38 -36
  141. package/templates/tsconfig.json +95 -95
  142. package/wrangler-dist/cli.d.ts +298 -0
  143. package/wrangler-dist/cli.js +33496 -31370
  144. package/pages/functions/buildPlugin.ts +0 -105
  145. package/pages/functions/buildWorker.ts +0 -151
  146. package/pages/functions/filepath-routing.ts +0 -189
  147. package/pages/functions/identifiers.ts +0 -78
  148. package/pages/functions/routes.ts +0 -156
  149. package/pages/functions/template-plugin.ts +0 -147
  150. package/pages/functions/template-worker.ts +0 -143
  151. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  152. package/src/pages.tsx +0 -2027
  153. package/src/user.tsx +0 -1203
  154. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  155. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  156. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  157. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  158. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  159. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  160. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  161. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  162. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  163. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  164. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  165. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  166. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  167. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  168. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  169. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  170. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  171. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  172. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  173. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  174. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  175. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  176. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  177. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  178. package/vendor/wrangler-mime/LICENSE +0 -21
  179. package/vendor/wrangler-mime/Mime.js +0 -97
  180. package/vendor/wrangler-mime/README.md +0 -187
  181. package/vendor/wrangler-mime/cli.js +0 -46
  182. package/vendor/wrangler-mime/index.js +0 -4
  183. package/vendor/wrangler-mime/lite.js +0 -4
  184. package/vendor/wrangler-mime/package.json +0 -52
  185. package/vendor/wrangler-mime/types/other.js +0 -1
  186. package/vendor/wrangler-mime/types/standard.js +0 -1
@@ -1,9 +1,27 @@
1
1
  import fetchMock from "jest-fetch-mock";
2
2
  import { Request } from "undici";
3
- import { getCloudflareApiBaseUrl } from "../../cfetch";
4
3
  import openInBrowser from "../../open-in-browser";
4
+ import {
5
+ createFetchResult,
6
+ setMockRawResponse,
7
+ setMockResponse,
8
+ } from "./mock-cfetch";
5
9
  import { mockHttpServer } from "./mock-http-server";
6
10
 
11
+ export function mockGetMemberships(
12
+ accounts: { id: string; account: { id: string; name: string } }[]
13
+ ) {
14
+ setMockResponse("/memberships", "GET", () => {
15
+ return accounts;
16
+ });
17
+ }
18
+
19
+ export function mockGetMembershipsFail() {
20
+ setMockRawResponse("/memberships", () => {
21
+ return createFetchResult([], false);
22
+ });
23
+ }
24
+
7
25
  // the response to send when wrangler wants an oauth grant
8
26
  let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
9
27
 
@@ -11,245 +29,222 @@ let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
11
29
  * Functions to help with mocking various parts of the OAuth Flow
12
30
  */
13
31
  export const mockOAuthFlow = () => {
14
- const fetchHttp = mockHttpServer();
15
-
16
- afterEach(() => {
17
- fetchMock.resetMocks();
18
- });
19
-
20
- /**
21
- * Mock out the callback from a browser to our HttpServer.
22
- *
23
- * This function will override `openInBrowser()` so that instead of opening a browser window
24
- * at the OAuth URL, it will automatically trigger the callback URL on the mock HttpServer that
25
- * we have created as part of the call to `mockOAuthFlow()`.
26
- */
27
- const mockOAuthServerCallback = () => {
28
- (
29
- openInBrowser as jest.MockedFunction<typeof openInBrowser>
30
- ).mockImplementation(async (url: string) => {
31
- // We don't support the grant response timing out.
32
- if (oauthGrantResponse === "timeout") {
33
- throw "unimplemented";
34
- }
35
-
36
- // Create a fake callback request that would be created by the OAuth server
37
- const { searchParams } = new URL(url);
38
- const queryParams = toQueryParams(oauthGrantResponse, searchParams);
39
- const request = new Request(
40
- `${searchParams.get("redirect_uri")}?${queryParams}`
41
- );
42
-
43
- // Trigger the mock HttpServer to handle this fake request to continue the OAuth flow.
44
- fetchHttp(request).catch((e) => {
45
- throw new Error(
46
- "Failed to send OAuth Grant to wrangler, maybe the server was closed?",
47
- e as Error
48
- );
49
- });
50
- });
51
- };
52
-
53
- const mockGrantAuthorization = ({
54
- respondWith,
55
- }: {
56
- respondWith: "timeout" | "success" | "failure" | GrantResponseOptions;
57
- }) => {
58
- if (respondWith === "failure") {
59
- oauthGrantResponse = {
60
- error: "access_denied",
61
- };
62
- } else if (respondWith === "success") {
63
- oauthGrantResponse = {
64
- code: "test-oauth-code",
65
- };
66
- } else if (respondWith === "timeout") {
67
- oauthGrantResponse = "timeout";
68
- } else {
69
- oauthGrantResponse = respondWith;
70
- }
71
- };
72
-
73
- const mockRevokeAuthorization = () => {
74
- const outcome = {
75
- actual: new Request("https://example.org"),
76
- expected: new Request("https://dash.cloudflare.com/oauth2/revoke", {
77
- method: "POST",
78
- }),
79
- };
80
-
81
- fetchMock.mockIf(outcome.expected.url, async (req) => {
82
- outcome.actual = req;
83
- return "";
84
- });
85
-
86
- return outcome;
87
- };
88
-
89
- const mockGetMemberships = (args: {
90
- success: boolean;
91
- result: { id: string; account: { id: string; name: string } }[];
92
- }) => {
93
- const outcome = {
94
- actual: new Request("https://example.org"),
95
- expected: new Request(`${getCloudflareApiBaseUrl()}/memberships`, {
96
- method: "GET",
97
- }),
98
- };
99
-
100
- fetchMock.mockIf(outcome.expected.url, async (req) => {
101
- outcome.actual = req;
102
- return {
103
- status: 200,
104
- body: JSON.stringify(args),
105
- };
106
- });
107
-
108
- return outcome;
109
- };
110
-
111
- const mockGrantAccessToken = ({
112
- respondWith,
113
- }: {
114
- respondWith: MockTokenResponse;
115
- }) => {
116
- const outcome = {
117
- actual: new Request("https://example.org"),
118
- expected: new Request("https://dash.cloudflare.com/oauth2/token", {
119
- method: "POST",
120
- }),
121
- };
122
-
123
- fetchMock.mockOnceIf(outcome.expected.url, async (req) => {
124
- outcome.actual = req;
125
- return makeTokenResponse(respondWith);
126
- });
127
-
128
- return outcome;
129
- };
130
-
131
- const mockExchangeRefreshTokenForAccessToken = ({
132
- respondWith,
133
- }: {
134
- respondWith: "refreshSuccess" | "refreshError" | "badResponse";
135
- }) => {
136
- fetchMock.mockOnceIf(
137
- "https://dash.cloudflare.com/oauth2/token",
138
- async () => {
139
- switch (respondWith) {
140
- case "refreshSuccess":
141
- return {
142
- status: 200,
143
- body: JSON.stringify({
144
- access_token: "access_token_success_mock",
145
- expires_in: 1701,
146
- refresh_token: "refresh_token_sucess_mock",
147
- scope: "scope_success_mock",
148
- token_type: "bearer",
149
- }),
150
- };
151
- case "refreshError":
152
- return {
153
- status: 400,
154
- body: JSON.stringify({
155
- error: "invalid_request",
156
- error_description: "error_description_mock",
157
- error_hint: "error_hint_mock",
158
- error_verbose: "error_verbose_mock",
159
- status_code: 400,
160
- }),
161
- };
162
- case "badResponse":
163
- return {
164
- status: 400,
165
- body: `<html> <body> This shouldn't be sent, but should be handled </body> </html>`,
166
- };
167
-
168
- default:
169
- return "Not a respondWith option for `mockExchangeRefreshTokenForAccessToken`";
170
- }
171
- }
172
- );
173
- };
174
-
175
- return {
176
- mockGetMemberships,
177
- mockGrantAccessToken,
178
- mockGrantAuthorization,
179
- mockOAuthServerCallback,
180
- mockRevokeAuthorization,
181
- mockExchangeRefreshTokenForAccessToken,
182
- };
32
+ const fetchHttp = mockHttpServer();
33
+
34
+ afterEach(() => {
35
+ fetchMock.resetMocks();
36
+ });
37
+
38
+ /**
39
+ * Mock out the callback from a browser to our HttpServer.
40
+ *
41
+ * This function will override `openInBrowser()` so that instead of opening a browser window
42
+ * at the OAuth URL, it will automatically trigger the callback URL on the mock HttpServer that
43
+ * we have created as part of the call to `mockOAuthFlow()`.
44
+ */
45
+ const mockOAuthServerCallback = () => {
46
+ (
47
+ openInBrowser as jest.MockedFunction<typeof openInBrowser>
48
+ ).mockImplementation(async (url: string) => {
49
+ // We don't support the grant response timing out.
50
+ if (oauthGrantResponse === "timeout") {
51
+ throw "unimplemented";
52
+ }
53
+
54
+ // Create a fake callback request that would be created by the OAuth server
55
+ const { searchParams } = new URL(url);
56
+ const queryParams = toQueryParams(oauthGrantResponse, searchParams);
57
+ const request = new Request(
58
+ `${searchParams.get("redirect_uri")}?${queryParams}`
59
+ );
60
+
61
+ // Trigger the mock HttpServer to handle this fake request to continue the OAuth flow.
62
+ fetchHttp(request).catch((e) => {
63
+ throw new Error(
64
+ "Failed to send OAuth Grant to wrangler, maybe the server was closed?",
65
+ e as Error
66
+ );
67
+ });
68
+ });
69
+ };
70
+
71
+ const mockGrantAuthorization = ({
72
+ respondWith,
73
+ }: {
74
+ respondWith: "timeout" | "success" | "failure" | GrantResponseOptions;
75
+ }) => {
76
+ if (respondWith === "failure") {
77
+ oauthGrantResponse = {
78
+ error: "access_denied",
79
+ };
80
+ } else if (respondWith === "success") {
81
+ oauthGrantResponse = {
82
+ code: "test-oauth-code",
83
+ };
84
+ } else if (respondWith === "timeout") {
85
+ oauthGrantResponse = "timeout";
86
+ } else {
87
+ oauthGrantResponse = respondWith;
88
+ }
89
+ };
90
+
91
+ const mockRevokeAuthorization = () => {
92
+ const outcome = {
93
+ actual: new Request("https://example.org"),
94
+ expected: new Request("https://dash.cloudflare.com/oauth2/revoke", {
95
+ method: "POST",
96
+ }),
97
+ };
98
+
99
+ fetchMock.mockIf(outcome.expected.url, async (req) => {
100
+ outcome.actual = req;
101
+ return "";
102
+ });
103
+
104
+ return outcome;
105
+ };
106
+
107
+ const mockGrantAccessToken = ({
108
+ respondWith,
109
+ }: {
110
+ respondWith: MockTokenResponse;
111
+ }) => {
112
+ const outcome = {
113
+ actual: new Request("https://example.org"),
114
+ expected: new Request("https://dash.cloudflare.com/oauth2/token", {
115
+ method: "POST",
116
+ }),
117
+ };
118
+
119
+ fetchMock.mockOnceIf(outcome.expected.url, async (req) => {
120
+ outcome.actual = req;
121
+ return makeTokenResponse(respondWith);
122
+ });
123
+
124
+ return outcome;
125
+ };
126
+
127
+ const mockExchangeRefreshTokenForAccessToken = ({
128
+ respondWith,
129
+ }: {
130
+ respondWith: "refreshSuccess" | "refreshError" | "badResponse";
131
+ }) => {
132
+ fetchMock.mockOnceIf(
133
+ "https://dash.cloudflare.com/oauth2/token",
134
+ async () => {
135
+ switch (respondWith) {
136
+ case "refreshSuccess":
137
+ return {
138
+ status: 200,
139
+ body: JSON.stringify({
140
+ access_token: "access_token_success_mock",
141
+ expires_in: 1701,
142
+ refresh_token: "refresh_token_sucess_mock",
143
+ scope: "scope_success_mock",
144
+ token_type: "bearer",
145
+ }),
146
+ };
147
+ case "refreshError":
148
+ return {
149
+ status: 400,
150
+ body: JSON.stringify({
151
+ error: "invalid_request",
152
+ error_description: "error_description_mock",
153
+ error_hint: "error_hint_mock",
154
+ error_verbose: "error_verbose_mock",
155
+ status_code: 400,
156
+ }),
157
+ };
158
+ case "badResponse":
159
+ return {
160
+ status: 400,
161
+ body: `<html> <body> This shouldn't be sent, but should be handled </body> </html>`,
162
+ };
163
+
164
+ default:
165
+ return "Not a respondWith option for `mockExchangeRefreshTokenForAccessToken`";
166
+ }
167
+ }
168
+ );
169
+ };
170
+
171
+ return {
172
+ mockGrantAccessToken,
173
+ mockGrantAuthorization,
174
+ mockOAuthServerCallback,
175
+ mockRevokeAuthorization,
176
+ mockExchangeRefreshTokenForAccessToken,
177
+ };
183
178
  };
184
179
 
185
180
  type GrantResponseOptions = {
186
- code?: string;
187
- error?: ErrorType | ErrorType[];
181
+ code?: string;
182
+ error?: ErrorType | ErrorType[];
188
183
  };
189
184
 
190
185
  const toQueryParams = (
191
- { code, error }: GrantResponseOptions,
192
- wranglerRequestParams: URLSearchParams
186
+ { code, error }: GrantResponseOptions,
187
+ wranglerRequestParams: URLSearchParams
193
188
  ): string => {
194
- const queryParams = [];
195
- if (code) {
196
- queryParams.push(`code=${code}`);
197
- }
198
- if (error) {
199
- const stringifiedErr = Array.isArray(error) ? error.join(",") : error;
200
- queryParams.push(`error=${stringifiedErr}`);
201
- }
202
-
203
- queryParams.push(`state=${wranglerRequestParams.get("state")}`);
204
-
205
- return queryParams.join("&");
189
+ const queryParams = [];
190
+ if (code) {
191
+ queryParams.push(`code=${code}`);
192
+ }
193
+ if (error) {
194
+ const stringifiedErr = Array.isArray(error) ? error.join(",") : error;
195
+ queryParams.push(`error=${stringifiedErr}`);
196
+ }
197
+
198
+ queryParams.push(`state=${wranglerRequestParams.get("state")}`);
199
+
200
+ return queryParams.join("&");
206
201
  };
207
202
 
208
203
  type ErrorType =
209
- | "invalid_request"
210
- | "invalid_grant"
211
- | "unauthorized_client"
212
- | "access_denied"
213
- | "unsupported_response_type"
214
- | "invalid_scope"
215
- | "server_error"
216
- | "temporarily_unavailable"
217
- | "invalid_client"
218
- | "unsupported_grant_type"
219
- | "invalid_json"
220
- | "invalid_token"
221
- | "test-token-grant-error";
204
+ | "invalid_request"
205
+ | "invalid_grant"
206
+ | "unauthorized_client"
207
+ | "access_denied"
208
+ | "unsupported_response_type"
209
+ | "invalid_scope"
210
+ | "server_error"
211
+ | "temporarily_unavailable"
212
+ | "invalid_client"
213
+ | "unsupported_grant_type"
214
+ | "invalid_json"
215
+ | "invalid_token"
216
+ | "test-token-grant-error";
222
217
 
223
218
  type MockTokenResponse =
224
- | "ok"
225
- | "error"
226
- | {
227
- access_token: string;
228
- expires_in: number;
229
- refresh_token: string;
230
- scope: string;
231
- }
232
- | {
233
- error: ErrorType;
234
- };
219
+ | "ok"
220
+ | "error"
221
+ | {
222
+ access_token: string;
223
+ expires_in: number;
224
+ refresh_token: string;
225
+ scope: string;
226
+ }
227
+ | {
228
+ error: ErrorType;
229
+ };
235
230
 
236
231
  const makeTokenResponse = (partialResponse: MockTokenResponse): string => {
237
- let fullResponse: MockTokenResponse;
238
-
239
- if (partialResponse === "ok") {
240
- fullResponse = {
241
- access_token: "test-access-token",
242
- expires_in: 100000,
243
- refresh_token: "test-refresh-token",
244
- scope: "account:read",
245
- };
246
- } else if (partialResponse === "error") {
247
- fullResponse = {
248
- error: "test-token-grant-error",
249
- };
250
- } else {
251
- fullResponse = partialResponse;
252
- }
253
-
254
- return JSON.stringify(fullResponse);
232
+ let fullResponse: MockTokenResponse;
233
+
234
+ if (partialResponse === "ok") {
235
+ fullResponse = {
236
+ access_token: "test-access-token",
237
+ expires_in: 100000,
238
+ refresh_token: "test-refresh-token",
239
+ scope: "account:read",
240
+ };
241
+ } else if (partialResponse === "error") {
242
+ fullResponse = {
243
+ error: "test-token-grant-error",
244
+ };
245
+ } else {
246
+ fullResponse = partialResponse;
247
+ }
248
+
249
+ return JSON.stringify(fullResponse);
255
250
  };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * We use this module to mock process methods (write only for now),
3
+ * and optionally assert on the values they're called with in our tests.
4
+ */
5
+
6
+ let writeSpy: jest.SpyInstance;
7
+
8
+ function captureLastWriteCall(spy: jest.SpyInstance): Buffer {
9
+ const calls = spy.mock.calls;
10
+ if (calls.length > 1) {
11
+ throw new Error(
12
+ "Unexpected calls to `stdout.write()`: " + JSON.stringify(calls)
13
+ );
14
+ }
15
+ const buffer = calls[0]?.[0] ?? Buffer.alloc(0);
16
+ if (buffer instanceof Buffer) {
17
+ return buffer;
18
+ } else {
19
+ throw new Error(
20
+ `Unexpected non-Buffer passed to \`stdout.write()\`: "${JSON.stringify(
21
+ buffer
22
+ )}"`
23
+ );
24
+ }
25
+ }
26
+
27
+ export function mockProcess() {
28
+ beforeEach(() => {
29
+ writeSpy = jest.spyOn(process.stdout, "write").mockImplementation();
30
+ });
31
+ afterEach(() => {
32
+ writeSpy.mockRestore();
33
+ });
34
+ return {
35
+ get write() {
36
+ return captureLastWriteCall(writeSpy);
37
+ },
38
+ };
39
+ }