wrangler 2.15.1 → 2.16.0

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.
@@ -179,6 +179,9 @@ function mergeHeaders(base, extra) {
179
179
  ...Object.fromEntries(extra.entries())
180
180
  });
181
181
  }
182
+ function stripLeadingDoubleSlashes(location) {
183
+ return location.replace(/^(\/|%2F|%2f|%5C|%5c|\\)+(.*)/, "/$2");
184
+ }
182
185
  var OkResponse, MovedPermanentlyResponse, FoundResponse, NotModifiedResponse, PermanentRedirectResponse, NotFoundResponse, MethodNotAllowedResponse, NotAcceptableResponse, InternalServerErrorResponse, SeeOtherResponse, TemporaryRedirectResponse;
183
186
  var init_responses = __esm({
184
187
  "../pages-shared/asset-server/responses.ts"() {
@@ -192,7 +195,12 @@ var init_responses = __esm({
192
195
  }
193
196
  };
194
197
  MovedPermanentlyResponse = class extends Response {
195
- constructor(location, init) {
198
+ constructor(location, init, {
199
+ preventLeadingDoubleSlash = true
200
+ } = {
201
+ preventLeadingDoubleSlash: true
202
+ }) {
203
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
196
204
  super(`Redirecting to ${location}`, {
197
205
  ...init,
198
206
  status: 301,
@@ -204,7 +212,12 @@ var init_responses = __esm({
204
212
  }
205
213
  };
206
214
  FoundResponse = class extends Response {
207
- constructor(location, init) {
215
+ constructor(location, init, {
216
+ preventLeadingDoubleSlash = true
217
+ } = {
218
+ preventLeadingDoubleSlash: true
219
+ }) {
220
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
208
221
  super(`Redirecting to ${location}`, {
209
222
  ...init,
210
223
  status: 302,
@@ -224,7 +237,12 @@ var init_responses = __esm({
224
237
  }
225
238
  };
226
239
  PermanentRedirectResponse = class extends Response {
227
- constructor(location, init) {
240
+ constructor(location, init, {
241
+ preventLeadingDoubleSlash = true
242
+ } = {
243
+ preventLeadingDoubleSlash: true
244
+ }) {
245
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
228
246
  super(void 0, {
229
247
  ...init,
230
248
  status: 308,
@@ -278,7 +296,12 @@ ${err.stack}`;
278
296
  }
279
297
  };
280
298
  SeeOtherResponse = class extends Response {
281
- constructor(location, init) {
299
+ constructor(location, init, {
300
+ preventLeadingDoubleSlash = true
301
+ } = {
302
+ preventLeadingDoubleSlash: true
303
+ }) {
304
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
282
305
  super(`Redirecting to ${location}`, {
283
306
  ...init,
284
307
  status: 303,
@@ -288,7 +311,12 @@ ${err.stack}`;
288
311
  }
289
312
  };
290
313
  TemporaryRedirectResponse = class extends Response {
291
- constructor(location, init) {
314
+ constructor(location, init, {
315
+ preventLeadingDoubleSlash = true
316
+ } = {
317
+ preventLeadingDoubleSlash: true
318
+ }) {
319
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
292
320
  super(`Redirecting to ${location}`, {
293
321
  ...init,
294
322
  status: 307,
@@ -351,15 +379,6 @@ var init_rulesEngine = __esm({
351
379
  }
352
380
  });
353
381
 
354
- // ../pages-shared/asset-server/url.ts
355
- function stringifyURLToRootRelativePathname(url) {
356
- return `${url.pathname}${url.search}${url.hash}`;
357
- }
358
- var init_url = __esm({
359
- "../pages-shared/asset-server/url.ts"() {
360
- }
361
- });
362
-
363
382
  // ../pages-shared/asset-server/handler.ts
364
383
  var handler_exports = {};
365
384
  __export(handler_exports, {
@@ -370,7 +389,6 @@ __export(handler_exports, {
370
389
  HEADERS_VERSION_V1: () => HEADERS_VERSION_V1,
371
390
  REDIRECTS_VERSION: () => REDIRECTS_VERSION2,
372
391
  generateHandler: () => generateHandler,
373
- getResponseFromMatch: () => getResponseFromMatch,
374
392
  normaliseHeaders: () => normaliseHeaders,
375
393
  parseQualityWeightedList: () => parseQualityWeightedList
376
394
  });
@@ -441,7 +459,32 @@ async function generateHandler({
441
459
  async function generateResponse() {
442
460
  const match = staticRedirectsMatcher() || generateRedirectsMatcher()({ request })[0];
443
461
  if (match) {
444
- return getResponseFromMatch(match, url);
462
+ const { status, to } = match;
463
+ const destination = new URL(to, request.url);
464
+ const location = destination.origin === new URL(request.url).origin ? `${destination.pathname}${destination.search || search}${destination.hash}` : `${destination.href}${destination.search ? "" : search}${destination.hash}`;
465
+ switch (status) {
466
+ case 301:
467
+ return new MovedPermanentlyResponse(location, void 0, {
468
+ preventLeadingDoubleSlash: false
469
+ });
470
+ case 303:
471
+ return new SeeOtherResponse(location, void 0, {
472
+ preventLeadingDoubleSlash: false
473
+ });
474
+ case 307:
475
+ return new TemporaryRedirectResponse(location, void 0, {
476
+ preventLeadingDoubleSlash: false
477
+ });
478
+ case 308:
479
+ return new PermanentRedirectResponse(location, void 0, {
480
+ preventLeadingDoubleSlash: false
481
+ });
482
+ case 302:
483
+ default:
484
+ return new FoundResponse(location, void 0, {
485
+ preventLeadingDoubleSlash: false
486
+ });
487
+ }
445
488
  }
446
489
  if (!request.method.match(/^(get|head)$/i)) {
447
490
  return new MethodNotAllowedResponse();
@@ -720,27 +763,6 @@ async function generateHandler({
720
763
  );
721
764
  }
722
765
  }
723
- function getResponseFromMatch({
724
- status,
725
- to
726
- }, requestUrl) {
727
- const destination = new URL(to, requestUrl);
728
- destination.search = destination.search || requestUrl.search;
729
- const location = destination.origin === requestUrl.origin ? stringifyURLToRootRelativePathname(destination) : destination.toString();
730
- switch (status) {
731
- case 301:
732
- return new MovedPermanentlyResponse(location);
733
- case 303:
734
- return new SeeOtherResponse(location);
735
- case 307:
736
- return new TemporaryRedirectResponse(location);
737
- case 308:
738
- return new PermanentRedirectResponse(location);
739
- case 302:
740
- default:
741
- return new FoundResponse(location);
742
- }
743
- }
744
766
  function parseQualityWeightedList(list = "") {
745
767
  const items = {};
746
768
  list.replace(/\s/g, "").split(",").forEach((el) => {
@@ -766,7 +788,6 @@ var init_handler = __esm({
766
788
  "../pages-shared/asset-server/handler.ts"() {
767
789
  init_responses();
768
790
  init_rulesEngine();
769
- init_url();
770
791
  ASSET_PRESERVATION_CACHE = "assetPreservationCache";
771
792
  CACHE_CONTROL_PRESERVATION = "public, s-maxage=604800";
772
793
  CACHE_CONTROL_BROWSER = "public, max-age=0, must-revalidate";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.15.1",
3
+ "version": "2.16.0",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -120,7 +120,7 @@
120
120
  "@cloudflare/workers-types": "^4.20221111.1",
121
121
  "@iarna/toml": "^3.0.0",
122
122
  "@microsoft/api-extractor": "^7.28.3",
123
- "@miniflare/tre": "3.0.0-next.12",
123
+ "@miniflare/tre": "3.0.0-next.13",
124
124
  "@types/better-sqlite3": "^7.6.0",
125
125
  "@types/busboy": "^1.5.0",
126
126
  "@types/command-exists": "^1.2.0",
@@ -1,8 +1,13 @@
1
1
  import { cwd } from "process";
2
+ import { rest } from "msw";
2
3
  import { reinitialiseAuthTokens } from "../../user";
3
4
  import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
4
5
  import { mockConsoleMethods } from "../helpers/mock-console";
6
+ import { mockConfirm } from "../helpers/mock-dialogs";
5
7
  import { useMockIsTTY } from "../helpers/mock-istty";
8
+ import { mockGetMemberships, mockOAuthFlow } from "../helpers/mock-oauth-flow";
9
+ import { mockSetTimeout } from "../helpers/mock-set-timeout";
10
+ import { msw } from "../helpers/msw";
6
11
  import { runInTempDir } from "../helpers/run-in-tmp";
7
12
  import { runWrangler } from "../helpers/run-wrangler";
8
13
  import writeWranglerToml from "../helpers/write-wrangler-toml";
@@ -10,6 +15,8 @@ import writeWranglerToml from "../helpers/write-wrangler-toml";
10
15
  describe("migrate", () => {
11
16
  runInTempDir();
12
17
  mockConsoleMethods();
18
+ mockSetTimeout();
19
+
13
20
  const { setIsTTY } = useMockIsTTY();
14
21
 
15
22
  describe("create", () => {
@@ -28,6 +35,9 @@ describe("migrate", () => {
28
35
  });
29
36
 
30
37
  describe("apply", () => {
38
+ mockAccountId({ accountId: null });
39
+ mockApiToken();
40
+ const { mockOAuthServerCallback } = mockOAuthFlow();
31
41
  it("should not attempt to login in local mode", async () => {
32
42
  setIsTTY(false);
33
43
  writeWranglerToml({
@@ -77,6 +87,96 @@ describe("migrate", () => {
77
87
  runWrangler("d1 migrations apply --local db --preview")
78
88
  ).rejects.toThrowError(`Error: can't use --preview with --local`);
79
89
  });
90
+
91
+ it("multiple accounts: should throw when trying to apply migrations without an account_id in config", async () => {
92
+ setIsTTY(false);
93
+
94
+ writeWranglerToml({
95
+ d1_databases: [
96
+ {
97
+ binding: "DATABASE",
98
+ database_name: "db",
99
+ database_id: "xxxx",
100
+ migrations_dir: "/tmp/my-migrations-go-here",
101
+ },
102
+ ],
103
+ });
104
+ mockOAuthServerCallback();
105
+ mockGetMemberships([
106
+ { id: "IG-88", account: { id: "1701", name: "enterprise" } },
107
+ { id: "R2-D2", account: { id: "nx01", name: "enterprise-nx" } },
108
+ ]);
109
+ mockConfirm({
110
+ text: `No migrations folder found.
111
+ Ok to create /tmp/my-migrations-go-here?`,
112
+ result: true,
113
+ });
114
+ await runWrangler("d1 migrations create db test");
115
+ mockConfirm({
116
+ text: `About to apply 1 migration(s)
117
+ Your database may not be available to serve requests during the migration, continue?`,
118
+ result: true,
119
+ });
120
+ await expect(runWrangler("d1 migrations apply db")).rejects.toThrowError(
121
+ `More than one account available but unable to select one in non-interactive mode.`
122
+ );
123
+ });
124
+ it("multiple accounts: should let the user apply migrations with an account_id in config", async () => {
125
+ setIsTTY(false);
126
+ msw.use(
127
+ rest.post(
128
+ "*/accounts/:accountId/d1/database/:databaseId/query",
129
+ async (req, res, ctx) => {
130
+ return res(
131
+ ctx.status(200),
132
+ ctx.json({
133
+ result: [
134
+ {
135
+ results: [],
136
+ success: true,
137
+ meta: {},
138
+ },
139
+ ],
140
+ success: true,
141
+ errors: [],
142
+ messages: [],
143
+ })
144
+ );
145
+ }
146
+ )
147
+ );
148
+ writeWranglerToml({
149
+ d1_databases: [
150
+ {
151
+ binding: "DATABASE",
152
+ database_name: "db",
153
+ database_id: "xxxx",
154
+ migrations_dir: "/tmp/my-migrations-go-here",
155
+ },
156
+ ],
157
+ account_id: "nx01",
158
+ });
159
+ mockOAuthServerCallback();
160
+ mockGetMemberships([
161
+ { id: "IG-88", account: { id: "1701", name: "enterprise" } },
162
+ { id: "R2-D2", account: { id: "nx01", name: "enterprise-nx" } },
163
+ ]);
164
+ mockConfirm({
165
+ text: `No migrations folder found.
166
+ Ok to create /tmp/my-migrations-go-here?`,
167
+ result: true,
168
+ });
169
+ await runWrangler("d1 migrations create db test");
170
+ mockConfirm({
171
+ text: `About to apply 1 migration(s)
172
+ Your database may not be available to serve requests during the migration, continue?`,
173
+ result: true,
174
+ });
175
+ //if we get to this point, wrangler knows the account_id
176
+ await expect(runWrangler("d1 migrations apply db")).rejects.toThrowError(
177
+ `request to https://api.cloudflare.com/client/v4/accounts/nx01/d1/database/xxxx/backup failed`
178
+ );
179
+ });
80
180
  });
81
181
 
82
182
  describe("list", () => {