wrangler 2.0.23 → 2.0.26

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 (80) hide show
  1. package/README.md +20 -2
  2. package/bin/wrangler.js +1 -1
  3. package/miniflare-dist/index.mjs +235 -47
  4. package/package.json +11 -6
  5. package/src/__tests__/configuration.test.ts +89 -17
  6. package/src/__tests__/dev.test.tsx +29 -4
  7. package/src/__tests__/generate.test.ts +93 -0
  8. package/src/__tests__/helpers/mock-cfetch.ts +87 -2
  9. package/src/__tests__/index.test.ts +10 -27
  10. package/src/__tests__/init.test.ts +537 -359
  11. package/src/__tests__/jest.setup.ts +34 -1
  12. package/src/__tests__/kv.test.ts +2 -2
  13. package/src/__tests__/metrics.test.ts +5 -0
  14. package/src/__tests__/pages.test.ts +14 -0
  15. package/src/__tests__/publish.test.ts +497 -254
  16. package/src/__tests__/r2.test.ts +173 -71
  17. package/src/__tests__/tail.test.ts +112 -42
  18. package/src/__tests__/user.test.ts +1 -0
  19. package/src/__tests__/validate-dev-props.test.ts +56 -0
  20. package/src/__tests__/whoami.test.tsx +60 -1
  21. package/src/api/dev.ts +7 -0
  22. package/src/bundle.ts +279 -44
  23. package/src/cfetch/internal.ts +73 -2
  24. package/src/config/config.ts +8 -3
  25. package/src/config/environment.ts +40 -8
  26. package/src/config/index.ts +13 -0
  27. package/src/config/validation.ts +102 -8
  28. package/src/create-worker-upload-form.ts +25 -0
  29. package/src/dev/dev.tsx +121 -28
  30. package/src/dev/local.tsx +88 -14
  31. package/src/dev/remote.tsx +39 -8
  32. package/src/dev/use-esbuild.ts +28 -0
  33. package/src/dev/validate-dev-props.ts +31 -0
  34. package/src/dev-registry.tsx +160 -0
  35. package/src/dev.tsx +107 -80
  36. package/src/generate.ts +112 -14
  37. package/src/index.tsx +212 -4
  38. package/src/init.ts +111 -38
  39. package/src/inspect.ts +90 -5
  40. package/src/metrics/index.ts +1 -0
  41. package/src/metrics/metrics-dispatcher.ts +1 -0
  42. package/src/metrics/metrics-usage-headers.ts +24 -0
  43. package/src/metrics/send-event.ts +2 -2
  44. package/src/miniflare-cli/assets.ts +27 -16
  45. package/src/miniflare-cli/index.ts +124 -2
  46. package/src/module-collection.ts +3 -3
  47. package/src/pages/build.tsx +75 -41
  48. package/src/pages/constants.ts +5 -0
  49. package/src/pages/deployments.tsx +10 -10
  50. package/src/pages/dev.tsx +177 -52
  51. package/src/pages/errors.ts +22 -0
  52. package/src/pages/functions/buildPlugin.ts +4 -0
  53. package/src/pages/functions/buildWorker.ts +4 -0
  54. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  55. package/src/pages/functions/routes-consolidation.ts +73 -0
  56. package/src/pages/functions/routes-transformation.test.ts +271 -0
  57. package/src/pages/functions/routes-transformation.ts +122 -0
  58. package/src/pages/functions.tsx +96 -0
  59. package/src/pages/index.tsx +65 -55
  60. package/src/pages/projects.tsx +9 -3
  61. package/src/pages/publish.tsx +76 -23
  62. package/src/pages/types.ts +9 -0
  63. package/src/pages/upload.tsx +38 -21
  64. package/src/publish.ts +126 -112
  65. package/src/r2.ts +81 -0
  66. package/src/tail/filters.ts +3 -1
  67. package/src/tail/index.ts +15 -2
  68. package/src/tail/printing.ts +43 -3
  69. package/src/user/user.tsx +20 -2
  70. package/src/whoami.tsx +79 -1
  71. package/src/worker.ts +12 -0
  72. package/templates/first-party-worker-module-facade.ts +18 -0
  73. package/templates/format-dev-errors.ts +32 -0
  74. package/templates/pages-template-plugin.ts +16 -4
  75. package/templates/pages-template-worker.ts +16 -5
  76. package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
  77. package/templates/service-bindings-module-facade.js +54 -0
  78. package/templates/service-bindings-sw-facade.js +42 -0
  79. package/wrangler-dist/cli.d.ts +7 -0
  80. package/wrangler-dist/cli.js +40851 -15332
package/README.md CHANGED
@@ -39,11 +39,25 @@ npm run deploy
39
39
  $ npm install wrangler --save-dev
40
40
  ```
41
41
 
42
+ ## Configuration:
43
+
44
+ Wrangler is configured via a `wrangler.toml` file in the project root. When utilizing the `wrangler init` command, a `wrangler.toml` file will be created for you.
45
+
46
+ example:
47
+
48
+ ```toml
49
+ main = "./src/index.ts" # init w/ TypeScript
50
+ name = "my-worker"
51
+ compatibility_date = "YYY-MM-DD"
52
+ ```
53
+
54
+ for more detailed information about configuration, see the [documentation](https://developers.cloudflare.com/workers/cli-wrangler/configuration)
55
+
42
56
  ## Commands
43
57
 
44
58
  ### `wrangler init [name]`
45
59
 
46
- Creates a Worker project. For details on configuration keys and values, refer to the [documentation](https://developers.cloudflare.com/workers/cli-wrangler/configuration).
60
+ Creates a Worker project. For details on configuration keys and values, refer to the [documentation](https://developers.cloudflare.com/workers/wrangler/commands/#init).
47
61
 
48
62
  ### `wrangler dev`
49
63
 
@@ -67,4 +81,8 @@ For more commands and options, refer to the [documentation](https://developers.c
67
81
 
68
82
  ## Documentation
69
83
 
70
- For the latest Wrangler documentation, [click here](https://6b05b6e1.cloudflare-docs-7ou.pages.dev/workers/wrangler/).
84
+ For the latest Wrangler documentation, [click here](https://developers.cloudflare.com/workers/wrangler/).
85
+
86
+ ```
87
+
88
+ ```
package/bin/wrangler.js CHANGED
@@ -35,7 +35,7 @@ Consider using a Node.js version manager such as https://volta.sh/ or https://gi
35
35
  // - maybe we can generate a certificate that concatenates with ours?
36
36
  //
37
37
  // I do think it'll be rare that someone wants to add a cert AND
38
- // use cloudflare WARP, but let's wait till the situation actually
38
+ // use Cloudflare WARP, but let's wait till the situation actually
39
39
  // arises before we do anything about it
40
40
  } else {
41
41
  const osTempDir = os.tmpdir();
@@ -22,7 +22,10 @@ var __copyProps = (to, from, except, desc) => {
22
22
  }
23
23
  return to;
24
24
  };
25
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
26
29
 
27
30
  // ../../node_modules/mime/Mime.js
28
31
  var require_Mime = __commonJS({
@@ -50,7 +53,9 @@ var require_Mime = __commonJS({
50
53
  continue;
51
54
  }
52
55
  if (!force && ext in this._types) {
53
- throw new Error('Attempt to change mapping for "' + ext + '" extension from "' + this._types[ext] + '" to "' + type + '". Pass `force=true` to allow this, otherwise remove "' + ext + '" from the list of extensions for "' + type + '".');
56
+ throw new Error(
57
+ 'Attempt to change mapping for "' + ext + '" extension from "' + this._types[ext] + '" to "' + type + '". Pass `force=true` to allow this, otherwise remove "' + ext + '" from the list of extensions for "' + type + '".'
58
+ );
54
59
  }
55
60
  this._types[ext] = type;
56
61
  }
@@ -100,7 +105,18 @@ var require_mime = __commonJS({
100
105
  });
101
106
 
102
107
  // src/miniflare-cli/index.ts
103
- import { Log, LogLevel, Miniflare } from "miniflare";
108
+ import { fetch } from "@miniflare/core";
109
+ import {
110
+ DurableObjectNamespace,
111
+ DurableObjectStub
112
+ } from "@miniflare/durable-objects";
113
+ import {
114
+ Log,
115
+ LogLevel,
116
+ Miniflare,
117
+ Response as MiniflareResponse,
118
+ Request as MiniflareRequest
119
+ } from "miniflare";
104
120
 
105
121
  // ../../node_modules/yargs/lib/platform-shims/esm.mjs
106
122
  import { notStrictEqual, strictEqual } from "assert";
@@ -4909,6 +4925,14 @@ function isYargsInstance(y) {
4909
4925
  var Yargs = YargsFactory(esm_default);
4910
4926
  var yargs_default = Yargs;
4911
4927
 
4928
+ // src/errors.ts
4929
+ var FatalError = class extends Error {
4930
+ constructor(message, code) {
4931
+ super(message);
4932
+ this.code = code;
4933
+ }
4934
+ };
4935
+
4912
4936
  // src/miniflare-cli/assets.ts
4913
4937
  var import_mime = __toESM(require_mime());
4914
4938
  import { existsSync, lstatSync, readFileSync as readFileSync4 } from "node:fs";
@@ -4935,7 +4959,10 @@ async function generateASSETSBinding(options) {
4935
4959
  return await assetsFetch(request);
4936
4960
  } catch (thrown) {
4937
4961
  options.log.error(new Error(`Could not serve static asset: ${thrown}`));
4938
- return new Response(`[wrangler] Could not serve static asset: ${thrown}`, { status: 502 });
4962
+ return new Response(
4963
+ `[wrangler] Could not serve static asset: ${thrown}`,
4964
+ { status: 502 }
4965
+ );
4939
4966
  }
4940
4967
  }
4941
4968
  };
@@ -4955,7 +4982,9 @@ function generateRulesMatcher(rules, replacerFn = (match) => match) {
4955
4982
  const compiledRules = Object.entries(rules).map(([rule, match]) => {
4956
4983
  const crossHost = rule.startsWith("https://");
4957
4984
  rule = rule.split("*").map(escapeRegex).join("(?<splat>.*)");
4958
- const host_matches = rule.matchAll(/(?<=^https:\\\/\\\/[^/]*?):([^\\]+)(?=\\)/g);
4985
+ const host_matches = rule.matchAll(
4986
+ /(?<=^https:\\\/\\\/[^/]*?):([^\\]+)(?=\\)/g
4987
+ );
4959
4988
  for (const hostMatch of host_matches) {
4960
4989
  rule = rule.split(hostMatch[0]).join(`(?<${hostMatch[1]}>[^/.]+)`);
4961
4990
  }
@@ -5016,10 +5045,15 @@ function generateHeadersMatcher(headersFile) {
5016
5045
  if (rule && Object.keys(rule.headers).length > 0) {
5017
5046
  rules[rule.path] = rule.headers;
5018
5047
  }
5019
- const rulesMatcher = generateRulesMatcher(rules, (match, replacements) => Object.fromEntries(Object.entries(match).map(([name, value]) => [
5020
- name,
5021
- replacer(value, replacements)
5022
- ])));
5048
+ const rulesMatcher = generateRulesMatcher(
5049
+ rules,
5050
+ (match, replacements) => Object.fromEntries(
5051
+ Object.entries(match).map(([name, value]) => [
5052
+ name,
5053
+ replacer(value, replacements)
5054
+ ])
5055
+ )
5056
+ );
5023
5057
  return (request) => {
5024
5058
  const matches = rulesMatcher({
5025
5059
  request
@@ -5035,17 +5069,22 @@ function generateRedirectsMatcher(redirectsFile) {
5035
5069
  if (existsSync(redirectsFile)) {
5036
5070
  const contents = readFileSync4(redirectsFile).toString();
5037
5071
  const lines = contents.split("\n").map((line) => line.trim()).filter((line) => !line.startsWith("#") && line !== "");
5038
- const rules = Object.fromEntries(lines.map((line) => line.split(" ")).filter((tokens) => tokens.length === 2 || tokens.length === 3).map((tokens) => {
5039
- const from = validateURL(tokens[0], true, false, false);
5040
- const to = validateURL(tokens[1], false, true, true);
5041
- let status = parseInt(tokens[2]) || 302;
5042
- status = [301, 302, 303, 307, 308].includes(status) ? status : void 0;
5043
- return from && to && status ? [from, { to, status }] : void 0;
5044
- }).filter((rule) => rule !== void 0));
5045
- const rulesMatcher = generateRulesMatcher(rules, ({ status, to }, replacements) => ({
5046
- status,
5047
- to: replacer(to, replacements)
5048
- }));
5072
+ const rules = Object.fromEntries(
5073
+ lines.map((line) => line.split(" ")).filter((tokens) => tokens.length === 2 || tokens.length === 3).map((tokens) => {
5074
+ const from = validateURL(tokens[0], true, false, false);
5075
+ const to = validateURL(tokens[1], false, true, true);
5076
+ let status = parseInt(tokens[2]) || 302;
5077
+ status = [301, 302, 303, 307, 308].includes(status) ? status : void 0;
5078
+ return from && to && status ? [from, { to, status }] : void 0;
5079
+ }).filter((rule) => rule !== void 0)
5080
+ );
5081
+ const rulesMatcher = generateRulesMatcher(
5082
+ rules,
5083
+ ({ status, to }, replacements) => ({
5084
+ status,
5085
+ to: replacer(to, replacements)
5086
+ })
5087
+ );
5049
5088
  return (request) => {
5050
5089
  const match = rulesMatcher({
5051
5090
  request
@@ -5068,7 +5107,11 @@ function validateURL(token, onlyRelative = false, includeSearch = false, include
5068
5107
  if (host && host.groups && host.groups.host) {
5069
5108
  if (onlyRelative)
5070
5109
  return;
5071
- return `https://${host.groups.host}${extractPathname(host.groups.path, includeSearch, includeHash)}`;
5110
+ return `https://${host.groups.host}${extractPathname(
5111
+ host.groups.path,
5112
+ includeSearch,
5113
+ includeHash
5114
+ )}`;
5072
5115
  } else {
5073
5116
  if (!token.startsWith("/") && onlyRelative)
5074
5117
  token = `/${token}`;
@@ -5123,6 +5166,11 @@ async function generateAssetsFetch(directory, log) {
5123
5166
  };
5124
5167
  const generateResponse = (request) => {
5125
5168
  const url = new URL(request.url);
5169
+ let assetName = url.pathname;
5170
+ try {
5171
+ assetName = decodeURIComponent(url.pathname);
5172
+ } catch {
5173
+ }
5126
5174
  const deconstructedResponse = {
5127
5175
  status: 200,
5128
5176
  headers: new Headers(),
@@ -5152,70 +5200,108 @@ async function generateAssetsFetch(directory, log) {
5152
5200
  return deconstructedResponse;
5153
5201
  }
5154
5202
  const notFound = () => {
5155
- let cwd = url.pathname;
5203
+ let cwd = assetName;
5156
5204
  while (cwd) {
5157
5205
  cwd = cwd.slice(0, cwd.lastIndexOf("/"));
5158
5206
  if (asset = getAsset(`${cwd}/404.html`)) {
5159
5207
  deconstructedResponse.status = 404;
5160
5208
  deconstructedResponse.body = serveAsset(asset);
5161
- deconstructedResponse.headers.set("Content-Type", (0, import_mime.getType)(asset) || "application/octet-stream");
5209
+ deconstructedResponse.headers.set(
5210
+ "Content-Type",
5211
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5212
+ );
5162
5213
  return deconstructedResponse;
5163
5214
  }
5164
5215
  }
5165
5216
  if (asset = getAsset(`/index.html`)) {
5166
5217
  deconstructedResponse.body = serveAsset(asset);
5167
- deconstructedResponse.headers.set("Content-Type", (0, import_mime.getType)(asset) || "application/octet-stream");
5218
+ deconstructedResponse.headers.set(
5219
+ "Content-Type",
5220
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5221
+ );
5168
5222
  return deconstructedResponse;
5169
5223
  }
5170
5224
  deconstructedResponse.status = 404;
5171
5225
  return deconstructedResponse;
5172
5226
  };
5173
5227
  let asset;
5174
- if (url.pathname.endsWith("/")) {
5175
- if (asset = getAsset(`${url.pathname}/index.html`)) {
5228
+ if (assetName.endsWith("/")) {
5229
+ if (asset = getAsset(`${assetName}/index.html`)) {
5176
5230
  deconstructedResponse.body = serveAsset(asset);
5177
- deconstructedResponse.headers.set("Content-Type", (0, import_mime.getType)(asset) || "application/octet-stream");
5231
+ deconstructedResponse.headers.set(
5232
+ "Content-Type",
5233
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5234
+ );
5178
5235
  return deconstructedResponse;
5179
- } else if (asset = getAsset(`${url.pathname.replace(/\/$/, ".html")}`)) {
5236
+ } else if (asset = getAsset(`${assetName.replace(/\/$/, ".html")}`)) {
5180
5237
  deconstructedResponse.status = 301;
5181
- deconstructedResponse.headers.set("Location", `${url.pathname.slice(0, -1)}${url.search}`);
5238
+ deconstructedResponse.headers.set(
5239
+ "Location",
5240
+ `${assetName.slice(0, -1)}${url.search}`
5241
+ );
5182
5242
  return deconstructedResponse;
5183
5243
  }
5184
5244
  }
5185
- if (url.pathname.endsWith("/index")) {
5245
+ if (assetName.endsWith("/index")) {
5186
5246
  deconstructedResponse.status = 301;
5187
- deconstructedResponse.headers.set("Location", `${url.pathname.slice(0, -"index".length)}${url.search}`);
5247
+ deconstructedResponse.headers.set(
5248
+ "Location",
5249
+ `${assetName.slice(0, -"index".length)}${url.search}`
5250
+ );
5188
5251
  return deconstructedResponse;
5189
5252
  }
5190
- if (asset = getAsset(url.pathname)) {
5191
- if (url.pathname.endsWith(".html")) {
5192
- const extensionlessPath = url.pathname.slice(0, -".html".length);
5253
+ if (asset = getAsset(assetName)) {
5254
+ if (assetName.endsWith(".html")) {
5255
+ const extensionlessPath = assetName.slice(0, -".html".length);
5193
5256
  if (getAsset(extensionlessPath) || extensionlessPath === "/") {
5194
5257
  deconstructedResponse.body = serveAsset(asset);
5195
- deconstructedResponse.headers.set("Content-Type", (0, import_mime.getType)(asset) || "application/octet-stream");
5258
+ deconstructedResponse.headers.set(
5259
+ "Content-Type",
5260
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5261
+ );
5196
5262
  return deconstructedResponse;
5197
5263
  } else {
5198
5264
  deconstructedResponse.status = 301;
5199
- deconstructedResponse.headers.set("Location", `${extensionlessPath}${url.search}`);
5265
+ deconstructedResponse.headers.set(
5266
+ "Location",
5267
+ `${extensionlessPath}${url.search}`
5268
+ );
5200
5269
  return deconstructedResponse;
5201
5270
  }
5202
5271
  } else {
5203
5272
  deconstructedResponse.body = serveAsset(asset);
5204
- deconstructedResponse.headers.set("Content-Type", (0, import_mime.getType)(asset) || "application/octet-stream");
5273
+ deconstructedResponse.headers.set(
5274
+ "Content-Type",
5275
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5276
+ );
5277
+ return deconstructedResponse;
5278
+ }
5279
+ } else if (hasFileExtension(assetName)) {
5280
+ if (asset = getAsset(assetName + ".html")) {
5281
+ deconstructedResponse.body = serveAsset(asset);
5282
+ deconstructedResponse.headers.set(
5283
+ "Content-Type",
5284
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5285
+ );
5205
5286
  return deconstructedResponse;
5206
5287
  }
5207
- } else if (hasFileExtension(url.pathname)) {
5208
5288
  notFound();
5209
5289
  return deconstructedResponse;
5210
5290
  }
5211
- if (asset = getAsset(`${url.pathname}.html`)) {
5291
+ if (asset = getAsset(`${assetName}.html`)) {
5212
5292
  deconstructedResponse.body = serveAsset(asset);
5213
- deconstructedResponse.headers.set("Content-Type", (0, import_mime.getType)(asset) || "application/octet-stream");
5293
+ deconstructedResponse.headers.set(
5294
+ "Content-Type",
5295
+ (0, import_mime.getType)(asset) || "application/octet-stream"
5296
+ );
5214
5297
  return deconstructedResponse;
5215
5298
  }
5216
- if (asset = getAsset(`${url.pathname}/index.html`)) {
5299
+ if (asset = getAsset(`${assetName}/index.html`)) {
5217
5300
  deconstructedResponse.status = 301;
5218
- deconstructedResponse.headers.set("Location", `${url.pathname}/${url.search}`);
5301
+ deconstructedResponse.headers.set(
5302
+ "Location",
5303
+ `${assetName}/${url.search}`
5304
+ );
5219
5305
  return deconstructedResponse;
5220
5306
  } else {
5221
5307
  notFound();
@@ -5257,13 +5343,17 @@ async function generateAssetsFetch(directory, log) {
5257
5343
  };
5258
5344
  }
5259
5345
  var invalidAssetsFetch = () => {
5260
- throw new Error("Trying to fetch assets directly when there is no `directory` option specified.");
5346
+ throw new Error(
5347
+ "Trying to fetch assets directly when there is no `directory` option specified."
5348
+ );
5261
5349
  };
5262
5350
 
5263
5351
  // src/miniflare-cli/enum-keys.ts
5264
5352
  var enumObject = (e) => {
5265
5353
  const copy = { ...e };
5266
- Object.values(e).forEach((value) => typeof value === "number" && delete copy[value]);
5354
+ Object.values(e).forEach(
5355
+ (value) => typeof value === "number" && delete copy[value]
5356
+ );
5267
5357
  return copy;
5268
5358
  };
5269
5359
  var enumKeys = (e) => {
@@ -5311,12 +5401,53 @@ async function main() {
5311
5401
  if (logLevel > LogLevel.INFO) {
5312
5402
  console.log("OPTIONS:\n", JSON.stringify(config, null, 2));
5313
5403
  }
5404
+ config.bindings = {
5405
+ ...config.bindings,
5406
+ ...Object.fromEntries(
5407
+ Object.entries(
5408
+ config.externalDurableObjects
5409
+ ).map(([binding, { name, host, port }]) => {
5410
+ const factory = () => {
5411
+ throw new FatalError(
5412
+ "An external Durable Object instance's state has somehow been attempted to be accessed.",
5413
+ 1
5414
+ );
5415
+ };
5416
+ const namespace = new DurableObjectNamespace(name, factory);
5417
+ namespace.get = (id) => {
5418
+ const stub = new DurableObjectStub(factory, id);
5419
+ stub.fetch = (...reqArgs) => {
5420
+ const requestFromArgs = new MiniflareRequest(...reqArgs);
5421
+ const url = new URL(requestFromArgs.url);
5422
+ url.host = host;
5423
+ if (port !== void 0)
5424
+ url.port = port.toString();
5425
+ const request = new MiniflareRequest(
5426
+ url.toString(),
5427
+ requestFromArgs
5428
+ );
5429
+ request.headers.set("x-miniflare-durable-object-name", name);
5430
+ request.headers.set("x-miniflare-durable-object-id", id.toString());
5431
+ return fetch(request);
5432
+ };
5433
+ return stub;
5434
+ };
5435
+ return [binding, namespace];
5436
+ })
5437
+ )
5438
+ };
5314
5439
  let mf;
5440
+ let durableObjectsMf = void 0;
5441
+ let durableObjectsMfPort = void 0;
5315
5442
  try {
5316
5443
  if (args._[1]) {
5317
- const opts = JSON.parse(args._[1]);
5444
+ const opts = JSON.parse(
5445
+ args._[1]
5446
+ );
5318
5447
  if (isNaN(opts.proxyPort || NaN) && !opts.directory) {
5319
- throw new Error("MiniflareCLIOptions: built in service bindings set to true, but no port or directory provided");
5448
+ throw new Error(
5449
+ "MiniflareCLIOptions: built in service bindings set to true, but no port or directory provided"
5450
+ );
5320
5451
  }
5321
5452
  const options = {
5322
5453
  log: config.log,
@@ -5331,11 +5462,68 @@ async function main() {
5331
5462
  mf = new Miniflare(config);
5332
5463
  await mf.startServer();
5333
5464
  await mf.startScheduler();
5334
- process.send && process.send("ready");
5465
+ const internalDurableObjectClassNames = Object.values(
5466
+ config.durableObjects
5467
+ );
5468
+ if (internalDurableObjectClassNames.length > 0) {
5469
+ durableObjectsMf = new Miniflare({
5470
+ host: config.host,
5471
+ port: 0,
5472
+ script: `
5473
+ export default {
5474
+ fetch(request, env) {
5475
+ return env.DO.fetch(request)
5476
+ }
5477
+ }`,
5478
+ serviceBindings: {
5479
+ DO: async (request) => {
5480
+ request = new MiniflareRequest(request);
5481
+ const name = request.headers.get("x-miniflare-durable-object-name");
5482
+ const idString = request.headers.get(
5483
+ "x-miniflare-durable-object-id"
5484
+ );
5485
+ request.headers.delete("x-miniflare-durable-object-name");
5486
+ request.headers.delete("x-miniflare-durable-object-id");
5487
+ if (!name || !idString) {
5488
+ return new MiniflareResponse(
5489
+ "[durable-object-proxy-err] Missing `x-miniflare-durable-object-name` or `x-miniflare-durable-object-id` headers.",
5490
+ { status: 400 }
5491
+ );
5492
+ }
5493
+ const namespace = await mf?.getDurableObjectNamespace(name);
5494
+ const id = namespace?.idFromString(idString);
5495
+ if (!id) {
5496
+ return new MiniflareResponse(
5497
+ "[durable-object-proxy-err] Could not generate an ID. Possibly due to a mismatched DO name and ID?",
5498
+ { status: 500 }
5499
+ );
5500
+ }
5501
+ const stub = namespace?.get(id);
5502
+ if (!stub) {
5503
+ return new MiniflareResponse(
5504
+ "[durable-object-proxy-err] Could not generate a stub. Possibly due to a mismatched DO name and ID?",
5505
+ { status: 500 }
5506
+ );
5507
+ }
5508
+ return stub.fetch(request);
5509
+ }
5510
+ },
5511
+ modules: true
5512
+ });
5513
+ const server = await durableObjectsMf.startServer();
5514
+ durableObjectsMfPort = server.address().port;
5515
+ }
5516
+ process.send && process.send(
5517
+ JSON.stringify({
5518
+ ready: true,
5519
+ durableObjectsPort: durableObjectsMfPort
5520
+ })
5521
+ );
5335
5522
  } catch (e) {
5336
5523
  mf?.log.error(e);
5337
5524
  process.exitCode = 1;
5338
5525
  await mf?.dispose();
5526
+ await durableObjectsMf?.dispose();
5339
5527
  }
5340
5528
  }
5341
5529
  await main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.0.23",
3
+ "version": "2.0.26",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -52,16 +52,16 @@
52
52
  "build": "npm run clean && npm run bundle && npm run emit-types",
53
53
  "bundle": "node -r esbuild-register scripts/bundle.ts",
54
54
  "check:type": "tsc",
55
- "clean": "rm -rf wrangler-dist miniflare-dist emitted-types",
55
+ "clean": "rimraf wrangler-dist miniflare-dist emitted-types",
56
56
  "dev": "npm run clean && concurrently -c black,blue --kill-others-on-fail false 'npm run bundle -- --watch' 'npm run check:type -- --watch --preserveWatchOutput'",
57
57
  "emit-types": "tsc -p tsconfig.emit.json && node -r esbuild-register scripts/emit-types.ts",
58
58
  "prepublishOnly": "SOURCEMAPS=false npm run build",
59
- "start": "npm run bundle && NODE_OPTIONS=--enable-source-maps ./bin/wrangler.js",
59
+ "start": "npm run bundle && cross-env NODE_OPTIONS=--enable-source-maps ./bin/wrangler.js",
60
60
  "test": "jest --silent=false --verbose=true",
61
- "test-watch": "npm run test -- --runInBand --testTimeout=50000 --watch"
61
+ "test-watch": "npm run test -- --runInBand --testTimeout=50000 --watch",
62
+ "test:ci": "npm run test -- --verbose=true --coverage"
62
63
  },
63
64
  "jest": {
64
- "collectCoverage": true,
65
65
  "coverageReporters": [
66
66
  "json",
67
67
  "html",
@@ -96,17 +96,19 @@
96
96
  "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
97
97
  "blake3-wasm": "^2.1.5",
98
98
  "chokidar": "^3.5.3",
99
- "esbuild": "0.14.47",
99
+ "esbuild": "0.14.51",
100
100
  "miniflare": "^2.6.0",
101
101
  "nanoid": "^3.3.3",
102
102
  "path-to-regexp": "^6.2.0",
103
103
  "selfsigned": "^2.0.1",
104
+ "source-map": "^0.7.4",
104
105
  "xxhash-wasm": "^1.0.1"
105
106
  },
106
107
  "devDependencies": {
107
108
  "@iarna/toml": "^3.0.0",
108
109
  "@microsoft/api-extractor": "^7.28.3",
109
110
  "@types/command-exists": "^1.2.0",
111
+ "@types/express": "^4.17.13",
110
112
  "@types/glob-to-regexp": "0.4.1",
111
113
  "@types/mime": "^2.0.3",
112
114
  "@types/prompts": "^2.0.14",
@@ -117,13 +119,16 @@
117
119
  "@types/ws": "^8.5.3",
118
120
  "@types/yargs": "^17.0.10",
119
121
  "@webcontainer/env": "^1.0.1",
122
+ "body-parser": "^1.20.0",
120
123
  "clipboardy": "^3.0.0",
121
124
  "cmd-shim": "^4.1.0",
122
125
  "command-exists": "^1.2.9",
123
126
  "concurrently": "^7.2.2",
127
+ "create-cloudflare": "^1.0.0",
124
128
  "devtools-protocol": "^0.0.955664",
125
129
  "dotenv": "^16.0.0",
126
130
  "execa": "^6.1.0",
131
+ "express": "^4.18.1",
127
132
  "faye-websocket": "^0.11.4",
128
133
  "finalhandler": "^1.2.0",
129
134
  "find-up": "^6.3.0",