wrangler 2.0.8 → 2.0.9

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/src/zones.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { fetchListResult } from "./cfetch";
2
+ import type { Route } from "./config/environment";
3
+
4
+ /**
5
+ * An object holding information about a zone for publishing.
6
+ */
7
+ export interface Zone {
8
+ id: string;
9
+ host: string;
10
+ }
11
+
12
+ /**
13
+ * Try to compute the a zone ID and host name for one or more routes.
14
+ *
15
+ * When we're given a route, we do 2 things:
16
+ * - We try to extract a host from it
17
+ * - We try to get a zone id from the host
18
+ */
19
+ export async function getZoneForRoute(route: Route): Promise<Zone | undefined> {
20
+ const host =
21
+ typeof route === "string"
22
+ ? getHostFromUrl(route)
23
+ : typeof route === "object"
24
+ ? "zone_name" in route
25
+ ? getHostFromUrl(route.zone_name)
26
+ : getHostFromUrl(route.pattern)
27
+ : undefined;
28
+ const id =
29
+ typeof route === "object" && "zone_id" in route
30
+ ? route.zone_id
31
+ : host
32
+ ? await getZoneIdFromHost(host)
33
+ : undefined;
34
+ return id && host ? { id, host } : undefined;
35
+ }
36
+
37
+ /**
38
+ * Given something that resembles a URL, try to extract a host from it.
39
+ */
40
+ function getHostFromUrl(urlLike: string): string | undefined {
41
+ // strip leading * / *.
42
+ urlLike = urlLike.replace(/^\*(\.)?/g, "");
43
+
44
+ if (!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))) {
45
+ urlLike = "http://" + urlLike;
46
+ }
47
+ return new URL(urlLike).host;
48
+ }
49
+
50
+ /**
51
+ * Given something that resembles a host, try to infer a zone id from it.
52
+ *
53
+ * It's hard to get a 'valid' domain from a string, so we don't even try to validate TLDs, etc.
54
+ * For each domain-like part of the host (e.g. w.x.y.z) try to get a zone id for it by
55
+ * lopping off subdomains until we get a hit from the API.
56
+ */
57
+ export async function getZoneIdFromHost(host: string): Promise<string> {
58
+ const hostPieces = host.split(".");
59
+
60
+ while (hostPieces.length > 1) {
61
+ const zones = await fetchListResult<{ id: string }>(
62
+ `/zones`,
63
+ {},
64
+ new URLSearchParams({ name: hostPieces.join(".") })
65
+ );
66
+ if (zones.length > 0) {
67
+ return zones[0].id;
68
+ }
69
+ hostPieces.shift();
70
+ }
71
+
72
+ throw new Error(`Could not find zone for ${host}`);
73
+ }
@@ -116942,7 +116942,7 @@ var yargs_default = Yargs;
116942
116942
 
116943
116943
  // package.json
116944
116944
  var name = "wrangler";
116945
- var version = "2.0.8";
116945
+ var version = "2.0.9";
116946
116946
  var author = "wrangler@cloudflare.com";
116947
116947
  var description = "Command-line interface for all things Cloudflare Workers";
116948
116948
  var bin = {
@@ -117223,6 +117223,7 @@ function indexLocation(file, index) {
117223
117223
 
117224
117224
  // src/cfetch/internal.ts
117225
117225
  init_import_meta_url();
117226
+ var import_node_assert2 = __toESM(require("node:assert"));
117226
117227
  var import_undici2 = __toESM(require_undici());
117227
117228
 
117228
117229
  // src/environment-variables.ts
@@ -117940,6 +117941,13 @@ async function requireAuth(config) {
117940
117941
  }
117941
117942
  return accountId;
117942
117943
  }
117944
+ function requireApiToken() {
117945
+ const authToken = getAPIToken();
117946
+ if (!authToken) {
117947
+ throw new Error("No API token found.");
117948
+ }
117949
+ return authToken;
117950
+ }
117943
117951
 
117944
117952
  // src/cfetch/internal.ts
117945
117953
  var getCloudflareAPIBaseURL = getEnvironmentVariableFactory({
@@ -117948,6 +117956,7 @@ var getCloudflareAPIBaseURL = getEnvironmentVariableFactory({
117948
117956
  defaultValue: "https://api.cloudflare.com/client/v4"
117949
117957
  });
117950
117958
  async function fetchInternal(resource, init = {}, queryParams, abortSignal) {
117959
+ (0, import_node_assert2.default)(resource.startsWith("/"), `CF API fetch - resource path must start with a "/" but got "${resource}"`);
117951
117960
  await requireLoggedIn();
117952
117961
  const apiToken = requireApiToken();
117953
117962
  const headers = cloneHeaders(init.headers);
@@ -117994,13 +118003,6 @@ async function requireLoggedIn() {
117994
118003
  throw new Error("Not logged in.");
117995
118004
  }
117996
118005
  }
117997
- function requireApiToken() {
117998
- const authToken = getAPIToken();
117999
- if (!authToken) {
118000
- throw new Error("No API token found.");
118001
- }
118002
- return authToken;
118003
- }
118004
118006
  function addAuthorizationHeaderIfUnspecified(headers, apiToken) {
118005
118007
  if (!("Authorization" in headers)) {
118006
118008
  headers["Authorization"] = `Bearer ${apiToken}`;
@@ -119451,7 +119453,7 @@ var import_undici5 = __toESM(require_undici());
119451
119453
 
119452
119454
  // src/entry.ts
119453
119455
  init_import_meta_url();
119454
- var import_node_assert2 = __toESM(require("node:assert"));
119456
+ var import_node_assert3 = __toESM(require("node:assert"));
119455
119457
  var import_node_fs4 = require("node:fs");
119456
119458
  var import_node_path10 = __toESM(require("node:path"));
119457
119459
  var esbuild = __toESM(require("esbuild"));
@@ -119528,8 +119530,8 @@ async function guessWorkerFormat(entryFile, entryWorkingDirectory, hint, tsconfi
119528
119530
  });
119529
119531
  const metafile = result.metafile;
119530
119532
  const entryPoints = Object.entries(metafile.outputs).filter(([_path, output]) => output.entryPoint !== void 0);
119531
- (0, import_node_assert2.default)(entryPoints.length > 0, `Cannot find entry-point "${entryFile}" in generated bundle.` + listEntryPoints(entryPoints));
119532
- (0, import_node_assert2.default)(entryPoints.length < 2, "More than one entry-point found for generated bundle." + listEntryPoints(entryPoints));
119533
+ (0, import_node_assert3.default)(entryPoints.length > 0, `Cannot find entry-point "${entryFile}" in generated bundle.` + listEntryPoints(entryPoints));
119534
+ (0, import_node_assert3.default)(entryPoints.length < 2, "More than one entry-point found for generated bundle." + listEntryPoints(entryPoints));
119533
119535
  let guessedWorkerFormat;
119534
119536
  const scriptExports = entryPoints[0][1].exports;
119535
119537
  if (scriptExports.length > 0) {
@@ -119623,7 +119625,7 @@ Did you mean to set the main field to${possiblePaths.length > 1 ? " one of" : ""
119623
119625
 
119624
119626
  // src/inspect.ts
119625
119627
  init_import_meta_url();
119626
- var import_node_assert3 = __toESM(require("node:assert"));
119628
+ var import_node_assert4 = __toESM(require("node:assert"));
119627
119629
  var import_node_http3 = require("node:http");
119628
119630
  var import_node_os6 = __toESM(require("node:os"));
119629
119631
  var import_node_url8 = require("node:url");
@@ -120138,7 +120140,7 @@ function useInspector(props) {
120138
120140
  }
120139
120141
  function sendMessageToRemoteWebSocket(event) {
120140
120142
  try {
120141
- (0, import_node_assert3.default)(remoteWebSocket, "Trying to send a message to an undefined `remoteWebSocket`");
120143
+ (0, import_node_assert4.default)(remoteWebSocket, "Trying to send a message to an undefined `remoteWebSocket`");
120142
120144
  remoteWebSocket.send(event.data);
120143
120145
  } catch (e2) {
120144
120146
  if (e2.message !== "WebSocket is not open: readyState 0 (CONNECTING)") {
@@ -120147,7 +120149,7 @@ function useInspector(props) {
120147
120149
  }
120148
120150
  }
120149
120151
  function sendMessageToLocalWebSocket(event) {
120150
- (0, import_node_assert3.default)(localWebSocket, "Trying to send a message to an undefined `localWebSocket`");
120152
+ (0, import_node_assert4.default)(localWebSocket, "Trying to send a message to an undefined `localWebSocket`");
120151
120153
  localWebSocket.send(event.data);
120152
120154
  }
120153
120155
  if (localWebSocket && remoteWebSocket) {
@@ -120645,7 +120647,6 @@ function useLocalWorker({
120645
120647
 
120646
120648
  // src/dev/remote.tsx
120647
120649
  init_import_meta_url();
120648
- var import_node_assert5 = __toESM(require("node:assert"));
120649
120650
  var import_promises4 = require("node:fs/promises");
120650
120651
  var import_node_path13 = __toESM(require("node:path"));
120651
120652
  var import_react5 = __toESM(require_react());
@@ -120656,7 +120657,7 @@ var import_node_url9 = require("node:url");
120656
120657
  var import_undici4 = __toESM(require_undici());
120657
120658
  async function sessionToken(account, ctx, abortSignal) {
120658
120659
  const { accountId } = account;
120659
- const initUrl = ctx.zone ? `/zones/${ctx.zone.id}/workers/edge-preview` : `/accounts/${accountId}/workers/subdomain/edge-preview`;
120660
+ const initUrl = ctx.zone ? `/zones/${ctx.zone}/workers/edge-preview` : `/accounts/${accountId}/workers/subdomain/edge-preview`;
120660
120661
  const { exchange_url } = await fetchResult(initUrl, void 0, void 0, abortSignal);
120661
120662
  const { inspector_websocket, prewarm, token } = await (await (0, import_undici4.fetch)(exchange_url, { signal: abortSignal })).json();
120662
120663
  const { host } = new import_node_url9.URL(inspector_websocket);
@@ -120677,7 +120678,7 @@ function randomId2() {
120677
120678
  async function createPreviewToken(account, worker, ctx, abortSignal) {
120678
120679
  const { value, host, inspectorUrl, prewarmUrl } = await sessionToken(account, ctx, abortSignal);
120679
120680
  const { accountId } = account;
120680
- const scriptId = ctx.zone ? randomId2() : worker.name || host.split(".")[0];
120681
+ const scriptId = worker.name || (ctx.zone ? randomId2() : host.split(".")[0]);
120681
120682
  const url3 = ctx.env && !ctx.legacyEnv ? `/accounts/${accountId}/workers/services/${scriptId}/environments/${ctx.env}/edge-preview` : `/accounts/${accountId}/workers/scripts/${scriptId}/edge-preview`;
120682
120683
  const mode = ctx.zone ? { routes: ["*/*"] } : { workers_dev: true };
120683
120684
  const formData = createWorkerUploadForm(worker);
@@ -120691,7 +120692,7 @@ async function createPreviewToken(account, worker, ctx, abortSignal) {
120691
120692
  }, void 0, abortSignal);
120692
120693
  return {
120693
120694
  value: preview_token,
120694
- host: ctx.zone ? ctx.zone.host : worker.name ? `${worker.name}.${host.split(".").slice(1).join(".")}` : host,
120695
+ host: ctx.host ?? (worker.name ? `${worker.name}.${host.split(".").slice(1).join(".")}` : host),
120695
120696
  inspectorUrl,
120696
120697
  prewarmUrl
120697
120698
  };
@@ -120713,7 +120714,7 @@ async function createWorkerPreview(init, account, ctx, abortSignal) {
120713
120714
 
120714
120715
  // src/sites.tsx
120715
120716
  init_import_meta_url();
120716
- var import_node_assert4 = __toESM(require("node:assert"));
120717
+ var import_node_assert5 = __toESM(require("node:assert"));
120717
120718
  var import_promises3 = require("node:fs/promises");
120718
120719
  var path13 = __toESM(require("node:path"));
120719
120720
  var import_ignore = __toESM(require_ignore());
@@ -120992,7 +120993,7 @@ async function syncAssets(accountId, scriptName, siteAssets, preview, dryRun) {
120992
120993
  logger.log("(Note: doing a dry run, not uploading or deleting anything.)");
120993
120994
  return { manifest: void 0, namespace: void 0 };
120994
120995
  }
120995
- (0, import_node_assert4.default)(accountId, "Missing accountId");
120996
+ (0, import_node_assert5.default)(accountId, "Missing accountId");
120996
120997
  const title = `__${scriptName}-workers_sites_assets${preview ? "_preview" : ""}`;
120997
120998
  const { id: namespace } = await createKVNamespaceIfNotAlreadyExisting(title, accountId);
120998
120999
  const namespaceKeysResponse = await listKVNamespaceKeys(accountId, namespace);
@@ -121074,15 +121075,12 @@ function getAssetPaths(config, assetDirectory = config.site?.bucket, includePatt
121074
121075
 
121075
121076
  // src/dev/remote.tsx
121076
121077
  function Remote(props) {
121077
- (0, import_node_assert5.default)(props.accountId, "accountId is required");
121078
- (0, import_node_assert5.default)(props.apiToken, "apiToken is required");
121079
121078
  const previewToken = useWorker({
121080
121079
  name: props.name,
121081
121080
  bundle: props.bundle,
121082
121081
  format: props.format,
121083
121082
  modules: props.bundle ? props.bundle.modules : [],
121084
121083
  accountId: props.accountId,
121085
- apiToken: props.apiToken,
121086
121084
  bindings: props.bindings,
121087
121085
  assetPaths: props.assetPaths,
121088
121086
  port: props.port,
@@ -121091,7 +121089,8 @@ function Remote(props) {
121091
121089
  usageModel: props.usageModel,
121092
121090
  env: props.env,
121093
121091
  legacyEnv: props.legacyEnv,
121094
- zone: props.zone
121092
+ zone: props.zone,
121093
+ host: props.host
121095
121094
  });
121096
121095
  usePreviewServer({
121097
121096
  previewToken,
@@ -121114,7 +121113,6 @@ function useWorker(props) {
121114
121113
  format: format4,
121115
121114
  modules,
121116
121115
  accountId,
121117
- apiToken,
121118
121116
  bindings,
121119
121117
  assetPaths,
121120
121118
  compatibilityDate,
@@ -121124,6 +121122,7 @@ function useWorker(props) {
121124
121122
  } = props;
121125
121123
  const [token, setToken] = (0, import_react5.useState)();
121126
121124
  const startedRef = (0, import_react5.useRef)(false);
121125
+ const accountIdRef = (0, import_react5.useRef)(accountId);
121127
121126
  (0, import_react5.useEffect)(() => {
121128
121127
  const abortController = new AbortController();
121129
121128
  async function start() {
@@ -121135,7 +121134,10 @@ function useWorker(props) {
121135
121134
  } else {
121136
121135
  logger.log("\u2394 Detected changes, restarted server.");
121137
121136
  }
121138
- const assets = await syncAssets(accountId, name2 + (!props.legacyEnv && props.env ? `-${props.env}` : ""), assetPaths, true, false);
121137
+ accountIdRef.current = await requireAuth({
121138
+ account_id: accountIdRef.current
121139
+ });
121140
+ const assets = await syncAssets(accountIdRef.current, name2 + (!props.legacyEnv && props.env ? `-${props.env}` : ""), assetPaths, true, false);
121139
121141
  const content = await (0, import_promises4.readFile)(bundle.path, "utf-8");
121140
121142
  const init = {
121141
121143
  name: name2,
@@ -121165,16 +121167,21 @@ function useWorker(props) {
121165
121167
  usage_model: usageModel
121166
121168
  };
121167
121169
  setToken(await createWorkerPreview(init, {
121168
- accountId,
121169
- apiToken
121170
- }, { env: props.env, legacyEnv: props.legacyEnv, zone: props.zone }, abortController.signal));
121170
+ accountId: accountIdRef.current,
121171
+ apiToken: requireApiToken()
121172
+ }, {
121173
+ env: props.env,
121174
+ legacyEnv: props.legacyEnv,
121175
+ zone: props.zone,
121176
+ host: props.host
121177
+ }, abortController.signal));
121171
121178
  }
121172
121179
  start().catch((err2) => {
121173
121180
  if (err2.code !== "ABORT_ERR") {
121174
121181
  if (err2.code === 10063) {
121175
121182
  const errorMessage = "Error: You need to register a workers.dev subdomain before running the dev command in remote mode";
121176
121183
  const solutionMessage = "You can either enable local mode by pressing l, or register a workers.dev subdomain here:";
121177
- const onboardingLink = `https://dash.cloudflare.com/${accountId}/workers/onboarding`;
121184
+ const onboardingLink = `https://dash.cloudflare.com/${accountIdRef.current}/workers/onboarding`;
121178
121185
  logger.error(`${errorMessage}
121179
121186
  ${solutionMessage}
121180
121187
  ${onboardingLink}`);
@@ -121191,7 +121198,6 @@ ${onboardingLink}`);
121191
121198
  bundle,
121192
121199
  format4,
121193
121200
  accountId,
121194
- apiToken,
121195
121201
  port,
121196
121202
  assetPaths,
121197
121203
  compatibilityDate,
@@ -121201,7 +121207,8 @@ ${onboardingLink}`);
121201
121207
  modules,
121202
121208
  props.env,
121203
121209
  props.legacyEnv,
121204
- props.zone
121210
+ props.zone,
121211
+ props.host
121205
121212
  ]);
121206
121213
  return token;
121207
121214
  }
@@ -121390,7 +121397,6 @@ function useEsbuild({
121390
121397
 
121391
121398
  // src/dev/dev.tsx
121392
121399
  function DevImplementation(props) {
121393
- const apiToken = props.initialMode === "remote" ? getAPIToken() : void 0;
121394
121400
  const directory = useTmpDir();
121395
121401
  useCustomBuild(props.entry, props.build);
121396
121402
  if (props.public && props.entry.format === "service-worker") {
@@ -121420,12 +121426,10 @@ function DevImplementation(props) {
121420
121426
  const { isRawModeSupported } = (0, import_ink3.useStdin)();
121421
121427
  return isRawModeSupported ? /* @__PURE__ */ import_react7.default.createElement(InteractiveDevSession, {
121422
121428
  ...props,
121423
- bundle,
121424
- apiToken
121429
+ bundle
121425
121430
  }) : /* @__PURE__ */ import_react7.default.createElement(DevSession, {
121426
121431
  ...props,
121427
121432
  bundle,
121428
- apiToken,
121429
121433
  local: props.initialMode === "local"
121430
121434
  });
121431
121435
  }
@@ -121475,7 +121479,6 @@ function DevSession(props) {
121475
121479
  bundle: props.bundle,
121476
121480
  format: props.entry.format,
121477
121481
  accountId: props.accountId,
121478
- apiToken: props.apiToken,
121479
121482
  bindings: props.bindings,
121480
121483
  assetPaths: props.assetPaths,
121481
121484
  public: props.public,
@@ -121488,7 +121491,8 @@ function DevSession(props) {
121488
121491
  usageModel: props.usageModel,
121489
121492
  env: props.env,
121490
121493
  legacyEnv: props.legacyEnv,
121491
- zone: props.zone
121494
+ zone: props.zone,
121495
+ host: props.host
121492
121496
  });
121493
121497
  }
121494
121498
  function useTmpDir() {
@@ -123605,7 +123609,10 @@ ${name2} is ${prettyBytes(filestat.size)} in size`);
123605
123609
  throw new FatalError(`Error: Pages only supports up to 20,000 files in a deployment. Ensure you have specified your build output directory correctly.`, 1);
123606
123610
  }
123607
123611
  const files2 = [...fileMap.values()];
123608
- const { jwt } = await fetchResult(`/accounts/${accountId}/pages/projects/${projectName}/upload-token`);
123612
+ async function fetchJwt() {
123613
+ return (await fetchResult(`/accounts/${accountId}/pages/projects/${projectName}/upload-token`)).jwt;
123614
+ }
123615
+ let jwt = await fetchJwt();
123609
123616
  const start = Date.now();
123610
123617
  const missingHashes = await fetchResult(`/pages/assets/check-missing`, {
123611
123618
  method: "POST",
@@ -123673,6 +123680,9 @@ ${name2} is ${prettyBytes(filestat.size)} in size`);
123673
123680
  } catch (e2) {
123674
123681
  if (attempts < MAX_UPLOAD_ATTEMPTS) {
123675
123682
  await new Promise((resolve11) => setTimeout(resolve11, attempts++ * 1e3));
123683
+ if (e2.code === 8000013) {
123684
+ jwt = await fetchJwt();
123685
+ }
123676
123686
  return doUpload();
123677
123687
  } else {
123678
123688
  throw e2;
@@ -124265,6 +124275,32 @@ async function getMigrationsToUpload(scriptName, props) {
124265
124275
  return migrations;
124266
124276
  }
124267
124277
 
124278
+ // src/zones.ts
124279
+ init_import_meta_url();
124280
+ async function getZoneForRoute(route) {
124281
+ const host = typeof route === "string" ? getHostFromUrl(route) : typeof route === "object" ? "zone_name" in route ? getHostFromUrl(route.zone_name) : getHostFromUrl(route.pattern) : void 0;
124282
+ const id = typeof route === "object" && "zone_id" in route ? route.zone_id : host ? await getZoneIdFromHost(host) : void 0;
124283
+ return id && host ? { id, host } : void 0;
124284
+ }
124285
+ function getHostFromUrl(urlLike) {
124286
+ urlLike = urlLike.replace(/^\*(\.)?/g, "");
124287
+ if (!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))) {
124288
+ urlLike = "http://" + urlLike;
124289
+ }
124290
+ return new URL(urlLike).host;
124291
+ }
124292
+ async function getZoneIdFromHost(host) {
124293
+ const hostPieces = host.split(".");
124294
+ while (hostPieces.length > 1) {
124295
+ const zones = await fetchListResult(`/zones`, {}, new URLSearchParams({ name: hostPieces.join(".") }));
124296
+ if (zones.length > 0) {
124297
+ return zones[0].id;
124298
+ }
124299
+ hostPieces.shift();
124300
+ }
124301
+ throw new Error(`Could not find zone for ${host}`);
124302
+ }
124303
+
124268
124304
  // src/publish.ts
124269
124305
  function sleep3(ms) {
124270
124306
  return new Promise((resolve11) => setTimeout(resolve11, ms));
@@ -124398,7 +124434,7 @@ async function publish(props) {
124398
124434
  const minify = props.minify ?? config.minify;
124399
124435
  const nodeCompat = props.nodeCompat ?? config.node_compat;
124400
124436
  if (nodeCompat) {
124401
- logger.warn("Enabling node.js compatibility mode for builtins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.");
124437
+ logger.warn("Enabling node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.");
124402
124438
  }
124403
124439
  const scriptName = props.name;
124404
124440
  (0, import_node_assert9.default)(scriptName, 'You need to provide a name when publishing a worker. Either pass it as a cli arg with `--name <name>` or in your config file as `name = "<name>"`');
@@ -124411,7 +124447,7 @@ async function publish(props) {
124411
124447
  const destination = props.outDir ?? await import_tmp_promise2.default.dir({ unsafeCleanup: true });
124412
124448
  const envName = props.env ?? "production";
124413
124449
  const start = Date.now();
124414
- const notProd = !props.legacyEnv && props.env;
124450
+ const notProd = Boolean(!props.legacyEnv && props.env);
124415
124451
  const workerName = notProd ? `${scriptName} (${envName})` : scriptName;
124416
124452
  const workerUrl = notProd ? `/accounts/${accountId}/workers/services/${scriptName}/environments/${envName}` : `/accounts/${accountId}/workers/scripts/${scriptName}`;
124417
124453
  let available_on_subdomain;
@@ -124539,13 +124575,7 @@ async function publish(props) {
124539
124575
  }
124540
124576
  logger.log("Uploaded", workerName, formatTime2(uploadMs));
124541
124577
  if (routesOnly.length > 0) {
124542
- deployments.push(fetchResult(`${workerUrl}/routes`, {
124543
- method: "PUT",
124544
- body: JSON.stringify(routesOnly.map((route) => typeof route !== "object" ? { pattern: route } : route)),
124545
- headers: {
124546
- "Content-Type": "application/json"
124547
- }
124548
- }).then(() => {
124578
+ deployments.push(publishRoutes(routesOnly, { workerUrl, scriptName, notProd }).then(() => {
124549
124579
  if (routesOnly.length > 10) {
124550
124580
  return routesOnly.slice(0, 9).map((route) => renderRoute(route)).concat([`...and ${routesOnly.length - 10} more routes`]);
124551
124581
  }
@@ -124596,6 +124626,92 @@ ${onboardingLink}`);
124596
124626
  }
124597
124627
  }
124598
124628
  }
124629
+ async function publishRoutes(routes, {
124630
+ workerUrl,
124631
+ scriptName,
124632
+ notProd
124633
+ }) {
124634
+ try {
124635
+ return await fetchResult(`${workerUrl}/routes`, {
124636
+ method: "PUT",
124637
+ body: JSON.stringify(routes.map((route) => typeof route !== "object" ? { pattern: route } : route)),
124638
+ headers: {
124639
+ "Content-Type": "application/json"
124640
+ }
124641
+ });
124642
+ } catch (e2) {
124643
+ if (isAuthenticationError(e2)) {
124644
+ return await publishRoutesFallback(routes, { scriptName, notProd });
124645
+ } else {
124646
+ throw e2;
124647
+ }
124648
+ }
124649
+ }
124650
+ async function publishRoutesFallback(routes, { scriptName, notProd }) {
124651
+ if (notProd) {
124652
+ throw new Error("Service environments combined with an API token that doesn't have 'All Zones' permissions is not supported.\nEither turn off service environments by setting `legacy_env = true`, creating an API token with 'All Zones' permissions, or logging in via OAuth");
124653
+ }
124654
+ logger.warn("The current authentication token does not have 'All Zones' permissions.\nFalling back to using the zone-based API endpoint to update each route individually.\nNote that there is no access to routes associated with zones that the API token does not have permission for.\nExisting routes for this Worker in such zones will not be deleted.");
124655
+ const deployedRoutes = [];
124656
+ const activeZones = /* @__PURE__ */ new Map();
124657
+ const routesToDeploy = /* @__PURE__ */ new Map();
124658
+ for (const route of routes) {
124659
+ const zone = await getZoneForRoute(route);
124660
+ if (zone) {
124661
+ activeZones.set(zone.id, zone.host);
124662
+ routesToDeploy.set(typeof route === "string" ? route : route.pattern, zone.id);
124663
+ }
124664
+ }
124665
+ const allRoutes = /* @__PURE__ */ new Map();
124666
+ const alreadyDeployedRoutes = /* @__PURE__ */ new Set();
124667
+ for (const [zone, host] of activeZones) {
124668
+ try {
124669
+ for (const { pattern, script } of await fetchListResult(`/zones/${zone}/workers/routes`)) {
124670
+ allRoutes.set(pattern, script);
124671
+ if (script === scriptName) {
124672
+ alreadyDeployedRoutes.add(pattern);
124673
+ }
124674
+ }
124675
+ } catch (e2) {
124676
+ if (isAuthenticationError(e2)) {
124677
+ e2.notes.push({
124678
+ text: `This could be because the API token being used does not have permission to access the zone "${host}" (${zone}).`
124679
+ });
124680
+ }
124681
+ throw e2;
124682
+ }
124683
+ }
124684
+ for (const [routePattern, zoneId] of routesToDeploy.entries()) {
124685
+ if (allRoutes.has(routePattern)) {
124686
+ const knownScript = allRoutes.get(routePattern);
124687
+ if (knownScript === scriptName) {
124688
+ alreadyDeployedRoutes.delete(routePattern);
124689
+ continue;
124690
+ } else {
124691
+ throw new Error(`The route with pattern "${routePattern}" is already associated with another worker called "${knownScript}".`);
124692
+ }
124693
+ }
124694
+ const { pattern } = await fetchResult(`/zones/${zoneId}/workers/routes`, {
124695
+ method: "POST",
124696
+ body: JSON.stringify({
124697
+ pattern: routePattern,
124698
+ script: scriptName
124699
+ }),
124700
+ headers: {
124701
+ "Content-Type": "application/json"
124702
+ }
124703
+ });
124704
+ deployedRoutes.push(pattern);
124705
+ }
124706
+ if (alreadyDeployedRoutes.size) {
124707
+ logger.warn("Previously deployed routes:\nThe following routes were already associated with this worker, and have not been deleted:\n" + [...alreadyDeployedRoutes.values()].map((route) => ` - "${route}"
124708
+ `) + "If these routes are not wanted then you can remove them in the dashboard.");
124709
+ }
124710
+ return deployedRoutes;
124711
+ }
124712
+ function isAuthenticationError(e2) {
124713
+ return e2 instanceof ParseError && e2.code === 1e4;
124714
+ }
124599
124715
 
124600
124716
  // src/r2.ts
124601
124717
  init_import_meta_url();
@@ -124824,9 +124940,10 @@ function Accounts(props) {
124824
124940
  }
124825
124941
  async function getUserInfo() {
124826
124942
  const apiToken = getAPIToken();
124943
+ const apiTokenFromEnv = getCloudflareAPITokenFromEnv();
124827
124944
  return apiToken ? {
124828
124945
  apiToken,
124829
- authType: "OAuth",
124946
+ authType: apiTokenFromEnv ? "API" : "OAuth",
124830
124947
  email: await getEmail(),
124831
124948
  accounts: await getAccounts()
124832
124949
  } : void 0;
@@ -125037,7 +125154,10 @@ ${err2.message ?? err2}`);
125037
125154
  if (!isInsideGitProject && isGitInstalled) {
125038
125155
  const shouldInitGit = yesFlag || await confirm("Would you like to use git to manage this Worker?");
125039
125156
  if (shouldInitGit) {
125040
- await execa("git", ["init", "--initial-branch=main"], {
125157
+ await execa("git", ["init"], {
125158
+ cwd: creationDirectory
125159
+ });
125160
+ await execa("git", ["branch", "-m", "main"], {
125041
125161
  cwd: creationDirectory
125042
125162
  });
125043
125163
  await (0, import_promises10.writeFile)(import_node_path21.default.join(creationDirectory, ".gitignore"), readFileSync5(import_node_path21.default.join(__dirname, "../templates/gitignore")));
@@ -125378,35 +125498,21 @@ To start developing your Worker, run \`npx wrangler dev\`${isCreatingWranglerTom
125378
125498
  if (upstreamProtocol === "http") {
125379
125499
  logger.warn("Setting upstream-protocol to http is not currently implemented.\nIf this is required in your project, please add your use case to the following issue:\nhttps://github.com/cloudflare/wrangler2/issues/583.");
125380
125500
  }
125381
- const accountId = !args.local ? await requireAuth(config) : void 0;
125382
- function getHost(urlLike) {
125383
- urlLike = urlLike.replace(/^\*(\.)?/g, "");
125384
- if (!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))) {
125385
- urlLike = "http://" + urlLike;
125386
- }
125387
- return new URL(urlLike).host;
125388
- }
125389
- async function getZoneId(host) {
125390
- const zones = await fetchResult(`/zones`, {}, new URLSearchParams({ name: host }));
125391
- return zones[0]?.id;
125392
- }
125393
- let zone;
125501
+ let host = args.host || config.dev.host;
125502
+ let zoneId;
125394
125503
  if (!args.local) {
125395
- const hostLike = args.host || config.dev.host || args.routes && args.routes[0] || config.route || config.routes && config.routes[0];
125396
- let zoneId = typeof hostLike === "object" && "zone_id" in hostLike ? hostLike.zone_id : void 0;
125397
- const host = typeof hostLike === "string" ? getHost(hostLike) : typeof hostLike === "object" ? "zone_name" in hostLike ? getHost(hostLike.zone_name) : getHost(hostLike.pattern) : void 0;
125398
- const hostPieces = typeof host === "string" ? host.split(".") : void 0;
125399
- while (!zoneId && hostPieces && hostPieces.length > 1) {
125400
- zoneId = await getZoneId(hostPieces.join("."));
125401
- hostPieces.shift();
125402
- }
125403
- if (host && !zoneId) {
125404
- throw new Error(`Could not find zone for ${hostLike}`);
125405
- }
125406
- zone = typeof zoneId === "string" && typeof host === "string" ? {
125407
- host,
125408
- id: zoneId
125409
- } : void 0;
125504
+ if (host) {
125505
+ zoneId = await getZoneIdFromHost(host);
125506
+ }
125507
+ const routes = args.routes || config.route || config.routes;
125508
+ if (!zoneId && routes) {
125509
+ const firstRoute = Array.isArray(routes) ? routes[0] : routes;
125510
+ const zone = await getZoneForRoute(firstRoute);
125511
+ if (zone) {
125512
+ zoneId = zone.id;
125513
+ host = zone.host;
125514
+ }
125515
+ }
125410
125516
  }
125411
125517
  const nodeCompat = args.nodeCompat ?? config.node_compat;
125412
125518
  if (nodeCompat) {
@@ -125453,7 +125559,8 @@ To start developing your Worker, run \`npx wrangler dev\`${isCreatingWranglerTom
125453
125559
  name: getScriptName(args, config),
125454
125560
  entry,
125455
125561
  env: args.env,
125456
- zone,
125562
+ zone: zoneId,
125563
+ host,
125457
125564
  rules: getRules(config),
125458
125565
  legacyEnv: isLegacyEnv(config),
125459
125566
  minify: args.minify ?? config.minify,
@@ -125466,7 +125573,7 @@ To start developing your Worker, run \`npx wrangler dev\`${isCreatingWranglerTom
125466
125573
  upstreamProtocol,
125467
125574
  localProtocol: args["local-protocol"] || config.dev.local_protocol,
125468
125575
  enableLocalPersistence: args["experimental-enable-local-persistence"] || false,
125469
- accountId,
125576
+ accountId: config.account_id,
125470
125577
  assetPaths: getAssetPaths(config, args.site, args.siteInclude, args.siteExclude),
125471
125578
  port: args.port || config.dev.port || await getPorts({ port: DEFAULT_LOCAL_PORT }),
125472
125579
  ip: args.ip || config.dev.ip,
@@ -125739,6 +125846,7 @@ To start developing your Worker, run \`npx wrangler dev\`${isCreatingWranglerTom
125739
125846
  rules: getRules(config),
125740
125847
  env: args.env,
125741
125848
  zone: void 0,
125849
+ host: void 0,
125742
125850
  legacyEnv: isLegacyEnv(config),
125743
125851
  build: config.build || {},
125744
125852
  minify: void 0,