@cloudflare/workers-utils 0.22.0 → 0.23.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.
package/dist/index.mjs CHANGED
@@ -1,8 +1,7 @@
1
- export { assertNever, constructWranglerConfig, getTodaysCompatDate, isCompatDate, mapWorkerMetadataBindings } from './chunk-AKFE3ND4.mjs';
1
+ export { assertNever, constructWranglerConfig, getTodaysCompatDate, isCompatDate, mapWorkerMetadataBindings } from './chunk-J6D57QVQ.mjs';
2
2
  export { MetricsRegistry } from './chunk-O4YGOZSW.mjs';
3
- import { isDirectory, UserError, isRedirectedRawConfig, dedent, configFileName, formatConfigSnippet, FatalError, removeDirSync, readFileSync as readFileSync$1, parseTOML, modify, applyEdits, format, dist_default, parseJSONC } from './chunk-GMTGAG26.mjs';
4
- export { APIError, CommandLineArgsError, DeprecationError, FatalError, JsonFriendlyFatalError, MissingConfigError, ParseError, UserError, configFileName, configFormat, createFatalError, experimental_readRawConfig, findWranglerConfig, formatConfigSnippet, indexLocation, isDirectory, isRedirectedConfig, parseByteSize, parseHumanDuration, parseJSON, parseJSONC, parseNonHyphenedUuid, parsePackageJSON, parseTOML, readFileSync, readFileSyncToBuffer, removeDir, removeDirSync, resolveWranglerConfigPath, searchLocation } from './chunk-GMTGAG26.mjs';
5
- export { ENVIRONMENT_TAG_PREFIX, INHERIT_SYMBOL, JSON_CONFIG_FORMATS, PATH_TO_DEPLOY_CONFIG, SERVICE_TAG_PREFIX } from './chunk-OZQVB3L3.mjs';
3
+ import { isDirectory, UserError, isRedirectedRawConfig, dedent, configFileName, formatConfigSnippet, FatalError, removeDirSync, ParseError, parseJSON, APIError, readFileSync as readFileSync$1, parseTOML, modify, applyEdits, format, dist_default, parseJSONC } from './chunk-ULVYGN52.mjs';
4
+ export { APIError, CommandLineArgsError, DeprecationError, ENVIRONMENT_TAG_PREFIX, FatalError, INHERIT_SYMBOL, JSON_CONFIG_FORMATS, JsonFriendlyFatalError, MissingConfigError, PATH_TO_DEPLOY_CONFIG, ParseError, SERVICE_TAG_PREFIX, UserError, configFileName, configFormat, createFatalError, experimental_readRawConfig, findWranglerConfig, formatConfigSnippet, indexLocation, isDirectory, isRedirectedConfig, parseByteSize, parseHumanDuration, parseJSON, parseJSONC, parseNonHyphenedUuid, parsePackageJSON, parseTOML, readFileSync, readFileSyncToBuffer, removeDir, removeDirSync, resolveWranglerConfigPath, searchLocation } from './chunk-ULVYGN52.mjs';
6
5
  import { __commonJS, __name, __require, __export, __toESM, __reExport } from './chunk-DCOBXSFB.mjs';
7
6
  import fs2, { accessSync, constants, writeFileSync, renameSync, existsSync, unlinkSync, mkdirSync, chmodSync, readFileSync } from 'node:fs';
8
7
  import assert from 'node:assert';
@@ -10,8 +9,10 @@ import path3, { join, dirname } from 'node:path';
10
9
  import os, { arch } from 'node:os';
11
10
  import { execFileSync, spawn } from 'node:child_process';
12
11
  import { createHash } from 'node:crypto';
13
- import { fetch } from 'undici';
12
+ import { fetch, Headers, FormData, Response } from 'undici';
13
+ import { URLSearchParams } from 'node:url';
14
14
  import * as timersPromises from 'node:timers/promises';
15
+ import { setTimeout as setTimeout$1 } from 'node:timers/promises';
15
16
 
16
17
  // ../../node_modules/.pnpm/xdg-app-paths@8.3.0/node_modules/xdg-app-paths/dist/cjs/lib/XDGAppPaths.js
17
18
  var require_XDGAppPaths = __commonJS({
@@ -569,7 +570,7 @@ var require_signal_exit = __commonJS({
569
570
  };
570
571
  };
571
572
  } else {
572
- assert2 = __require("assert");
573
+ assert3 = __require("assert");
573
574
  signals = require_signals();
574
575
  isWin = /^win/i.test(process2.platform);
575
576
  EE = __require("events");
@@ -592,7 +593,7 @@ var require_signal_exit = __commonJS({
592
593
  return function() {
593
594
  };
594
595
  }
595
- assert2.equal(typeof cb, "function", "a callback must be provided for exit handler");
596
+ assert3.equal(typeof cb, "function", "a callback must be provided for exit handler");
596
597
  if (loaded === false) {
597
598
  load();
598
599
  }
@@ -698,7 +699,7 @@ var require_signal_exit = __commonJS({
698
699
  }
699
700
  }, "processEmit");
700
701
  }
701
- var assert2;
702
+ var assert3;
702
703
  var signals;
703
704
  var isWin;
704
705
  var EE;
@@ -1910,7 +1911,7 @@ var defaultWranglerConfig = {
1910
1911
  vectorize: [],
1911
1912
  ai_search_namespaces: [],
1912
1913
  ai_search: [],
1913
- web_search: void 0,
1914
+ websearch: void 0,
1914
1915
  agent_memory: [],
1915
1916
  hyperdrive: [],
1916
1917
  workflows: [],
@@ -6587,7 +6588,7 @@ var friendlyBindingNames = {
6587
6588
  vectorize: "Vectorize Index",
6588
6589
  ai_search_namespaces: "AI Search Namespace",
6589
6590
  ai_search: "AI Search Instance",
6590
- web_search: "Web Search",
6591
+ websearch: "Web Search",
6591
6592
  agent_memory: "Agent Memory",
6592
6593
  hyperdrive: "Hyperdrive Config",
6593
6594
  r2_buckets: "R2 Bucket",
@@ -6641,7 +6642,7 @@ var bindingTypeFriendlyNames = {
6641
6642
  vectorize: "Vectorize Index",
6642
6643
  ai_search_namespace: "AI Search Namespace",
6643
6644
  ai_search: "AI Search Instance",
6644
- web_search: "Web Search",
6645
+ websearch: "Web Search",
6645
6646
  agent_memory: "Agent Memory",
6646
6647
  hyperdrive: "Hyperdrive Config",
6647
6648
  service: "Worker",
@@ -7313,8 +7314,8 @@ function normalizeAndValidateRoute(diagnostics, topLevelEnv, rawEnv) {
7313
7314
  );
7314
7315
  }
7315
7316
  __name(normalizeAndValidateRoute, "normalizeAndValidateRoute");
7316
- function validateRoutes(diagnostics, topLevelEnv, rawEnv) {
7317
- return inheritable(
7317
+ function validateRoutes(diagnostics, topLevelEnv, rawEnv, envName) {
7318
+ const result = inheritable(
7318
7319
  diagnostics,
7319
7320
  topLevelEnv,
7320
7321
  rawEnv,
@@ -7322,6 +7323,18 @@ function validateRoutes(diagnostics, topLevelEnv, rawEnv) {
7322
7323
  all(isRouteArray, isMutuallyExclusiveWith(rawEnv, "route")),
7323
7324
  void 0
7324
7325
  );
7326
+ if (topLevelEnv !== void 0 && envName !== void 0 && rawEnv.routes === void 0) {
7327
+ const customDomainRoutes = topLevelEnv.routes?.filter(
7328
+ (r2) => typeof r2 === "object" && r2 !== null && r2.custom_domain === true
7329
+ );
7330
+ if (customDomainRoutes && customDomainRoutes.length > 0) {
7331
+ const customDomains = customDomainRoutes.map((r2) => r2.pattern).join(", ");
7332
+ diagnostics.warnings.push(
7333
+ `The "env.${envName}" environment inherits the top-level \`routes\` configuration, which includes the custom domain(s): ${customDomains}. Deploying this environment will reassign these custom domains away from the top-level Worker. Add \`"routes": []\` to "env.${envName}" to prevent inheritance, or copy the route configuration from the top level to hide this warning.`
7334
+ );
7335
+ }
7336
+ }
7337
+ return result;
7325
7338
  }
7326
7339
  __name(validateRoutes, "validateRoutes");
7327
7340
  function normalizeAndValidatePlacement(diagnostics, topLevelEnv, rawEnv) {
@@ -7537,7 +7550,12 @@ function normalizeAndValidateEnvironment(diagnostics, configPath, rawEnv, isDisp
7537
7550
  void 0,
7538
7551
  void 0
7539
7552
  );
7540
- const routes = validateRoutes(diagnostics, topLevelEnv, rawEnv);
7553
+ const routes = validateRoutes(
7554
+ diagnostics,
7555
+ topLevelEnv,
7556
+ rawEnv,
7557
+ topLevelEnv === void 0 ? void 0 : envName
7558
+ );
7541
7559
  const workers_dev = inheritable(
7542
7560
  diagnostics,
7543
7561
  topLevelEnv,
@@ -7837,13 +7855,13 @@ function normalizeAndValidateEnvironment(diagnostics, configPath, rawEnv, isDisp
7837
7855
  validateBindingArray(envName, validateAISearchBinding),
7838
7856
  []
7839
7857
  ),
7840
- web_search: notInheritable(
7858
+ websearch: notInheritable(
7841
7859
  diagnostics,
7842
7860
  topLevelEnv,
7843
7861
  rawConfig,
7844
7862
  rawEnv,
7845
7863
  envName,
7846
- "web_search",
7864
+ "websearch",
7847
7865
  validateNamedSimpleBinding(envName),
7848
7866
  void 0
7849
7867
  ),
@@ -8940,7 +8958,7 @@ var validateUnsafeBinding = /* @__PURE__ */ __name((diagnostics, field, value) =
8940
8958
  "ai",
8941
8959
  "ai_search_namespace",
8942
8960
  "ai_search",
8943
- "web_search",
8961
+ "websearch",
8944
8962
  "agent_memory",
8945
8963
  "kv_namespace",
8946
8964
  "durable_object_namespace",
@@ -9751,12 +9769,21 @@ var validateD1Binding = /* @__PURE__ */ __name((diagnostics, field, value) => {
9751
9769
  if (!isRemoteValid(value, field, diagnostics)) {
9752
9770
  isValid2 = false;
9753
9771
  }
9772
+ if (!isOptionalProperty(value, "migrations_pattern", "string")) {
9773
+ diagnostics.errors.push(
9774
+ `"${field}" bindings should, optionally, have a string "migrations_pattern" field but got ${JSON.stringify(
9775
+ value
9776
+ )}.`
9777
+ );
9778
+ isValid2 = false;
9779
+ }
9754
9780
  validateAdditionalProperties(diagnostics, field, Object.keys(value), [
9755
9781
  "binding",
9756
9782
  "database_id",
9757
9783
  "database_internal_env",
9758
9784
  "database_name",
9759
9785
  "migrations_dir",
9786
+ "migrations_pattern",
9760
9787
  "migrations_table",
9761
9788
  "preview_database_id",
9762
9789
  "remote"
@@ -11349,7 +11376,7 @@ var BINDING_LOCAL_SUPPORT = {
11349
11376
  flagship: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
11350
11377
  vpc_service: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
11351
11378
  vpc_network: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
11352
- web_search: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
11379
+ websearch: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
11353
11380
  agent_memory: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator"
11354
11381
  };
11355
11382
  function getBindingLocalSupport(type) {
@@ -12147,7 +12174,7 @@ function startTunnel(options) {
12147
12174
  return;
12148
12175
  }
12149
12176
  logger?.log(
12150
- `${publicURL ? `The tunnel is still open at ${publicURL}.` : "The tunnel is still open."} It expires in ${formatTunnelDuration(remainingMs)}. ${options.extendHint ?? ""}`
12177
+ `${publicURL ? `Tunnel still open, expires in ${formatTunnelDuration(remainingMs)}: ${publicURL}` : `The tunnel is still open. It expires in ${formatTunnelDuration(remainingMs)}.`}${options.extendHint ? ` ${options.extendHint}` : ""}`
12151
12178
  );
12152
12179
  }, reminderIntervalMs);
12153
12180
  reminderInterval.unref?.();
@@ -12298,7 +12325,7 @@ function createTunnelStartupError(message, stderrOutput, origin) {
12298
12325
  cloudflared output:
12299
12326
  ${stderrOutput || "(no output)"}
12300
12327
 
12301
- The local dev server started at ${origin.href}.
12328
+ The local dev server started at ${origin.href}
12302
12329
  ` + (isQuickTunnelRateLimited ? "Cloudflare Quick Tunnel creation was rate limited. Try again in a few minutes, or use a named tunnel if you need more reliable access." : `Check the cloudflared output above for more details, and verify that ${origin.href} is reachable from this machine if this keeps happening.`);
12303
12330
  if (isQuickTunnelRateLimited) {
12304
12331
  return new UserError(errorMessage, { telemetryMessage: false });
@@ -12307,6 +12334,348 @@ The local dev server started at ${origin.href}.
12307
12334
  }
12308
12335
  __name(createTunnelStartupError, "createTunnelStartupError");
12309
12336
 
12337
+ // src/cfetch/errors.ts
12338
+ function buildDetailedError(message, ...extra) {
12339
+ return new ParseError({
12340
+ text: message,
12341
+ notes: extra.map((text) => ({ text })),
12342
+ telemetryMessage: false
12343
+ });
12344
+ }
12345
+ __name(buildDetailedError, "buildDetailedError");
12346
+ function maybeThrowFriendlyError(error) {
12347
+ if (error.message === "workers.api.error.email_verification_required") {
12348
+ throw buildDetailedError(
12349
+ "Please verify your account's email address and try again.",
12350
+ "Check your email for a verification link, or login to https://dash.cloudflare.com and request a new one."
12351
+ );
12352
+ }
12353
+ }
12354
+ __name(maybeThrowFriendlyError, "maybeThrowFriendlyError");
12355
+
12356
+ // src/cfetch/index.ts
12357
+ function logHeaders(headers, logger) {
12358
+ const clone = cloneHeaders(headers);
12359
+ clone.delete("Authorization");
12360
+ logger.debugWithSanitization(
12361
+ "HEADERS:",
12362
+ JSON.stringify(Object.fromEntries(clone), null, 2)
12363
+ );
12364
+ }
12365
+ __name(logHeaders, "logHeaders");
12366
+ async function performApiFetchBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
12367
+ assert(credentials, "credentials are required for performApiFetch");
12368
+ const method = init.method ?? "GET";
12369
+ assert(
12370
+ resource.startsWith("/"),
12371
+ `CF API fetch - resource path must start with a "/" but got "${resource}"`
12372
+ );
12373
+ const headers = cloneHeaders(new Headers(init.headers));
12374
+ addAuthorizationHeader(headers, credentials);
12375
+ headers.set("User-Agent", userAgent);
12376
+ maybeAddTraceHeader(headers);
12377
+ const queryString = queryParams ? `?${queryParams.toString()}` : "";
12378
+ logger.debug(
12379
+ `-- START CF API REQUEST: ${method} ${getCloudflareApiBaseUrl(complianceConfig)}${resource}`
12380
+ );
12381
+ logger.debugWithSanitization("QUERY STRING:", queryString);
12382
+ logHeaders(headers, logger);
12383
+ logger.debugWithSanitization("INIT:", JSON.stringify({ ...init }, null, 2));
12384
+ if (init.body instanceof FormData) {
12385
+ logger.debugWithSanitization(
12386
+ "BODY:",
12387
+ await new Response(init.body).text(),
12388
+ null,
12389
+ 2
12390
+ );
12391
+ }
12392
+ logger.debug("-- END CF API REQUEST");
12393
+ return await fetch(
12394
+ `${getCloudflareApiBaseUrl(complianceConfig)}${resource}${queryString}`,
12395
+ {
12396
+ method,
12397
+ ...init,
12398
+ headers,
12399
+ signal: abortSignal
12400
+ }
12401
+ );
12402
+ }
12403
+ __name(performApiFetchBase, "performApiFetchBase");
12404
+ async function fetchInternalBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
12405
+ const method = init.method ?? "GET";
12406
+ const response = await performApiFetchBase(
12407
+ complianceConfig,
12408
+ resource,
12409
+ init,
12410
+ userAgent,
12411
+ logger,
12412
+ queryParams,
12413
+ abortSignal,
12414
+ credentials
12415
+ );
12416
+ const jsonText = await response.text();
12417
+ logger.debug(
12418
+ "-- START CF API RESPONSE:",
12419
+ response.statusText,
12420
+ response.status
12421
+ );
12422
+ logHeaders(response.headers, logger);
12423
+ logger.debugWithSanitization("RESPONSE:", jsonText);
12424
+ logger.debug("-- END CF API RESPONSE");
12425
+ if (!jsonText && (response.status === 204 || response.status === 205)) {
12426
+ return {
12427
+ response: {
12428
+ result: {},
12429
+ success: true,
12430
+ errors: [],
12431
+ messages: []
12432
+ },
12433
+ status: response.status
12434
+ };
12435
+ }
12436
+ if (isWAFBlockResponse(response.headers)) {
12437
+ throwWAFBlockError(
12438
+ response.headers,
12439
+ method,
12440
+ resource,
12441
+ response.status,
12442
+ response.statusText
12443
+ );
12444
+ }
12445
+ try {
12446
+ const json = parseJSON(jsonText);
12447
+ return { response: json, status: response.status };
12448
+ } catch {
12449
+ const rayId = extractWAFBlockRayId(response.headers);
12450
+ throw new APIError({
12451
+ text: "Received a malformed response from the API",
12452
+ notes: [
12453
+ {
12454
+ text: truncate(jsonText, 100)
12455
+ },
12456
+ {
12457
+ text: `${method} ${resource} -> ${response.status} ${response.statusText}`
12458
+ },
12459
+ ...rayId ? [{ text: `Cloudflare Ray ID: ${rayId}` }] : []
12460
+ ],
12461
+ status: response.status,
12462
+ telemetryMessage: false
12463
+ });
12464
+ }
12465
+ }
12466
+ __name(fetchInternalBase, "fetchInternalBase");
12467
+ async function fetchResultBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
12468
+ const { response: json, status } = await fetchInternalBase(
12469
+ complianceConfig,
12470
+ resource,
12471
+ init,
12472
+ userAgent,
12473
+ logger,
12474
+ queryParams,
12475
+ abortSignal,
12476
+ credentials
12477
+ );
12478
+ if (json.success) {
12479
+ return json.result;
12480
+ } else {
12481
+ throwFetchError(resource, json, status);
12482
+ }
12483
+ }
12484
+ __name(fetchResultBase, "fetchResultBase");
12485
+ async function fetchListResultBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, credentials) {
12486
+ const results = [];
12487
+ let getMoreResults = true;
12488
+ let cursor;
12489
+ while (getMoreResults) {
12490
+ if (cursor) {
12491
+ queryParams = new URLSearchParams(queryParams);
12492
+ queryParams.set("cursor", cursor);
12493
+ }
12494
+ const { response: json, status } = await fetchInternalBase(
12495
+ complianceConfig,
12496
+ resource,
12497
+ init,
12498
+ userAgent,
12499
+ logger,
12500
+ queryParams,
12501
+ void 0,
12502
+ credentials
12503
+ );
12504
+ if (json.success) {
12505
+ results.push(...json.result);
12506
+ if (hasCursor(json.result_info)) {
12507
+ cursor = json.result_info?.cursor;
12508
+ } else {
12509
+ getMoreResults = false;
12510
+ }
12511
+ } else {
12512
+ throwFetchError(resource, json, status);
12513
+ }
12514
+ }
12515
+ return results;
12516
+ }
12517
+ __name(fetchListResultBase, "fetchListResultBase");
12518
+ function truncate(text, maxLength) {
12519
+ const { length } = text;
12520
+ if (length <= maxLength) {
12521
+ return text;
12522
+ }
12523
+ return `${text.substring(0, maxLength)}... (length = ${length})`;
12524
+ }
12525
+ __name(truncate, "truncate");
12526
+ function isWAFBlockResponse(headers) {
12527
+ return headers.get("cf-mitigated") === "challenge";
12528
+ }
12529
+ __name(isWAFBlockResponse, "isWAFBlockResponse");
12530
+ function extractWAFBlockRayId(headers) {
12531
+ return headers.get("cf-ray") ?? void 0;
12532
+ }
12533
+ __name(extractWAFBlockRayId, "extractWAFBlockRayId");
12534
+ function extractAccountTag(resource) {
12535
+ const re = new RegExp("/accounts/([a-zA-Z0-9]+)/?");
12536
+ const matches = re.exec(resource);
12537
+ return matches?.[1];
12538
+ }
12539
+ __name(extractAccountTag, "extractAccountTag");
12540
+ function hasMorePages(result_info) {
12541
+ const page = result_info?.page;
12542
+ const per_page = result_info?.per_page;
12543
+ const total = result_info?.total_count;
12544
+ return page !== void 0 && per_page !== void 0 && total !== void 0 && page * per_page < total;
12545
+ }
12546
+ __name(hasMorePages, "hasMorePages");
12547
+ function renderError(err, level = 0) {
12548
+ const indent = " ".repeat(level);
12549
+ const message = err.message ?? "";
12550
+ const chainedMessages = "error_chain" in err ? err.error_chain?.map(
12551
+ (chainedError) => `
12552
+
12553
+ ${indent}- ${renderError(chainedError, level + 1)}`
12554
+ ).join("\n") ?? "" : "";
12555
+ return (err.code ? `${message} [code: ${err.code}]` : message) + (err.documentation_url ? `
12556
+ ${indent}To learn more about this error, visit: ${err.documentation_url}` : "") + chainedMessages;
12557
+ }
12558
+ __name(renderError, "renderError");
12559
+ function addAuthorizationHeader(headers, auth, overrideExisting = false) {
12560
+ if (!headers.has("Authorization") || overrideExisting) {
12561
+ if ("apiToken" in auth) {
12562
+ const authorizationHeader = `Bearer ${auth.apiToken}`;
12563
+ validateAuthorizationHeaderValue(authorizationHeader);
12564
+ headers.set("Authorization", authorizationHeader);
12565
+ } else {
12566
+ headers.set("X-Auth-Key", auth.authKey);
12567
+ headers.set("X-Auth-Email", auth.authEmail);
12568
+ }
12569
+ }
12570
+ }
12571
+ __name(addAuthorizationHeader, "addAuthorizationHeader");
12572
+ function validateAuthorizationHeaderValue(value) {
12573
+ for (const character of value) {
12574
+ const codePoint = character.codePointAt(0);
12575
+ if (codePoint === void 0 || codePoint > 255) {
12576
+ throw new UserError(
12577
+ `The configured Cloudflare API token contains a character that cannot be used in an HTTP Authorization header: ${formatAuthorizationHeaderCharacter(character, codePoint)}. Recreate or copy the token again, making sure it does not include characters such as ellipses.`,
12578
+ {
12579
+ telemetryMessage: "cfetch auth invalid authorization header"
12580
+ }
12581
+ );
12582
+ }
12583
+ }
12584
+ }
12585
+ __name(validateAuthorizationHeaderValue, "validateAuthorizationHeaderValue");
12586
+ function formatAuthorizationHeaderCharacter(character, codePoint) {
12587
+ if (codePoint === void 0) {
12588
+ return '"\\u{unknown}"';
12589
+ }
12590
+ const codePointLabel = `U+${codePoint.toString(16).toUpperCase().padStart(4, "0")}`;
12591
+ const characterLabel = isPrintableCharacter(character) ? `"${character}"` : `"${escapeCharacter(character)}"`;
12592
+ return `${characterLabel} (${codePointLabel})`;
12593
+ }
12594
+ __name(formatAuthorizationHeaderCharacter, "formatAuthorizationHeaderCharacter");
12595
+ function isPrintableCharacter(character) {
12596
+ return !/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(character);
12597
+ }
12598
+ __name(isPrintableCharacter, "isPrintableCharacter");
12599
+ function escapeCharacter(character) {
12600
+ return Array.from(character).map((c) => {
12601
+ const codePoint = c.codePointAt(0);
12602
+ if (codePoint === void 0) {
12603
+ return "";
12604
+ }
12605
+ return codePoint <= 65535 ? `\\u${codePoint.toString(16).toUpperCase().padStart(4, "0")}` : `\\u{${codePoint.toString(16).toUpperCase()}}`;
12606
+ }).join("");
12607
+ }
12608
+ __name(escapeCharacter, "escapeCharacter");
12609
+ function throwFetchError(resource, response, status) {
12610
+ const errors = response.errors ?? [];
12611
+ for (const error2 of errors) {
12612
+ maybeThrowFriendlyError(error2);
12613
+ }
12614
+ const notes = [
12615
+ ...errors.map((err) => ({ text: renderError(err) })),
12616
+ ...response.messages?.map((msg) => ({
12617
+ text: typeof msg === "string" ? msg : msg.message ?? String(msg)
12618
+ })) ?? []
12619
+ ];
12620
+ if (notes.length === 0) {
12621
+ const raw = response;
12622
+ const fallbackMessage = typeof raw.error === "string" ? `${raw.error}${raw.code ? ` [code: ${raw.code}]` : ""}` : void 0;
12623
+ if (fallbackMessage) {
12624
+ notes.push({ text: fallbackMessage });
12625
+ }
12626
+ }
12627
+ const error = new APIError({
12628
+ text: `A request to the Cloudflare API (${resource}) failed.`,
12629
+ notes,
12630
+ status,
12631
+ telemetryMessage: false
12632
+ });
12633
+ const code = errors[0]?.code;
12634
+ if (code) {
12635
+ error.code = code;
12636
+ }
12637
+ error.accountTag = extractAccountTag(resource);
12638
+ throw error;
12639
+ }
12640
+ __name(throwFetchError, "throwFetchError");
12641
+ function throwWAFBlockError(headers, method, resource, status, statusText) {
12642
+ const rayId = extractWAFBlockRayId(headers);
12643
+ throw new APIError({
12644
+ text: "The Cloudflare API responded with a WAF block page instead of the expected JSON response",
12645
+ notes: [
12646
+ {
12647
+ text: "Cloudflare's firewall (WAF) blocked this API request. This is usually a false positive."
12648
+ },
12649
+ ...rayId ? [{ text: `Cloudflare Ray ID: ${rayId}` }] : [],
12650
+ {
12651
+ text: rayId ? "If the issue persists, please open a Cloudflare Support ticket and include the Ray ID above." : "If the issue persists, please open a Cloudflare Support ticket. You can find the Cloudflare Ray ID on the block page in your browser."
12652
+ },
12653
+ {
12654
+ text: `${method} ${resource} -> ${status} ${statusText}`
12655
+ }
12656
+ ],
12657
+ status,
12658
+ telemetryMessage: false
12659
+ });
12660
+ }
12661
+ __name(throwWAFBlockError, "throwWAFBlockError");
12662
+ function hasCursor(result_info) {
12663
+ const cursor = result_info?.cursor;
12664
+ return cursor !== void 0 && cursor !== null && cursor !== "";
12665
+ }
12666
+ __name(hasCursor, "hasCursor");
12667
+ function maybeAddTraceHeader(headers) {
12668
+ const traceHeader = getTraceHeader();
12669
+ if (traceHeader) {
12670
+ headers.set("Cf-Trace-Id", traceHeader);
12671
+ }
12672
+ }
12673
+ __name(maybeAddTraceHeader, "maybeAddTraceHeader");
12674
+ function cloneHeaders(headers) {
12675
+ return new Headers(headers);
12676
+ }
12677
+ __name(cloneHeaders, "cloneHeaders");
12678
+
12310
12679
  // src/update-check.ts
12311
12680
  var import_update_check = __toESM(require_update_check());
12312
12681
  var UPDATE_CHECK_TIMEOUT_MS = 3e3;
@@ -12337,6 +12706,77 @@ async function fetchLatestNpmVersion(name, version) {
12337
12706
  return { status: "update-available", latest: result.latest };
12338
12707
  }
12339
12708
  __name(fetchLatestNpmVersion, "fetchLatestNpmVersion");
12709
+ var MAX_ATTEMPTS = 3;
12710
+ async function retryOnAPIFailure(action, logger, backoff = 0, attempts = MAX_ATTEMPTS, abortSignal) {
12711
+ try {
12712
+ return await action();
12713
+ } catch (err) {
12714
+ if (err instanceof APIError) {
12715
+ if (!err.isRetryable()) {
12716
+ throw err;
12717
+ }
12718
+ } else if (err instanceof DOMException && err.name === "TimeoutError") ; else if (!(err instanceof TypeError)) {
12719
+ throw err;
12720
+ }
12721
+ logger.debug(`Retrying API call after error...`);
12722
+ logger.debug(err);
12723
+ if (attempts <= 1) {
12724
+ throw err;
12725
+ }
12726
+ await setTimeout$1(backoff, void 0, { signal: abortSignal });
12727
+ return retryOnAPIFailure(
12728
+ action,
12729
+ logger,
12730
+ backoff + 1e3,
12731
+ attempts - 1,
12732
+ abortSignal
12733
+ );
12734
+ }
12735
+ }
12736
+ __name(retryOnAPIFailure, "retryOnAPIFailure");
12737
+
12738
+ // src/format-time.ts
12739
+ function formatTime(duration) {
12740
+ return `(${(duration / 1e3).toFixed(2)} sec)`;
12741
+ }
12742
+ __name(formatTime, "formatTime");
12743
+
12744
+ // src/route-utils.ts
12745
+ function getHostFromRoute(route) {
12746
+ let host;
12747
+ if (typeof route === "string") {
12748
+ host = getHostFromUrl(route);
12749
+ } else if (typeof route === "object") {
12750
+ host = getHostFromUrl(route.pattern);
12751
+ if (host === void 0 && "zone_name" in route) {
12752
+ host = getHostFromUrl(route.zone_name);
12753
+ }
12754
+ }
12755
+ return host;
12756
+ }
12757
+ __name(getHostFromRoute, "getHostFromRoute");
12758
+ function getZoneFromRoute(route) {
12759
+ if (typeof route === "object" && "zone_name" in route && route.zone_name) {
12760
+ return route.zone_name;
12761
+ }
12762
+ return getHostFromRoute(route);
12763
+ }
12764
+ __name(getZoneFromRoute, "getZoneFromRoute");
12765
+ function getHostFromUrl(urlLike) {
12766
+ if (urlLike.startsWith("*/") || urlLike.startsWith("http://*/") || urlLike.startsWith("https://*/")) {
12767
+ return void 0;
12768
+ }
12769
+ urlLike = urlLike.replace(/\*(\.)?/g, "");
12770
+ if (!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))) {
12771
+ urlLike = "http://" + urlLike;
12772
+ }
12773
+ try {
12774
+ return new URL(urlLike).host;
12775
+ } catch {
12776
+ return void 0;
12777
+ }
12778
+ }
12779
+ __name(getHostFromUrl, "getHostFromUrl");
12340
12780
  /*! Bundled license information:
12341
12781
 
12342
12782
  deep-extend/lib/deep-extend.js:
@@ -12371,4 +12811,4 @@ safe-buffer/index.js:
12371
12811
  (*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
12372
12812
  */
12373
12813
 
12374
- export { COMPLIANCE_REGION_CONFIG_PUBLIC, COMPLIANCE_REGION_CONFIG_UNKNOWN, Diagnostics, PatchConfigError, bucketFormatMessage, defaultWranglerConfig, experimental_patchConfig, fetchLatestNpmVersion, friendlyBindingNames, getBindingLocalSupport, getBindingTypeFriendlyName, getBooleanEnvironmentVariableFactory, getBrowserRenderingHeadfulFromEnv, getBuildConditionsFromEnv, getBuildPlatformFromEnv, getC3CommandFromEnv, getCIGeneratePreviewAlias, getCIMatchTag, getCIOverrideName, getCIOverrideNetworkModeHost, getCfFetchEnabledFromEnv, getCfFetchPathFromEnv, getCloudflareApiBaseUrl, getCloudflareApiEnvironmentFromEnv, getCloudflareComplianceRegion, getCloudflareEnv, getCloudflareIncludeProcessEnvFromEnv, getCloudflareLoadDevVarsFromDotEnv, getCloudflaredPathFromEnv, getComplianceRegionSubdomain, getD1ExtraLocationChoices, getDisableConfigWatching, getDockerPath, getEnvironmentVariableFactory, getGlobalWranglerConfigPath, getLocalExplorerEnabledFromEnv, getOpenNextDeployFromEnv, getOutputFileDirectoryFromEnv, getOutputFilePathFromEnv, getRegistryPath, getSanitizeLogs, getSubdomainMixedStateCheckDisabled, getTraceHeader, getWorkersCIBranchName, getWranglerCacheDirFromEnv, getWranglerHiddenDirPath, getWranglerHideBanner, getWranglerSendErrorReportsFromEnv, getWranglerSendMetricsFromEnv, getWranglerTmpDir, hasProperty, isDockerfile, isOptionalProperty, isPagesConfig, isRequiredProperty, isValidR2BucketName, normalizeAndValidateConfig, spawnCloudflared, startTunnel, sweepStaleWranglerTmpDirs, validatePagesConfig };
12814
+ export { COMPLIANCE_REGION_CONFIG_PUBLIC, COMPLIANCE_REGION_CONFIG_UNKNOWN, Diagnostics, PatchConfigError, addAuthorizationHeader, bucketFormatMessage, defaultWranglerConfig, experimental_patchConfig, extractAccountTag, extractWAFBlockRayId, fetchInternalBase, fetchLatestNpmVersion, fetchListResultBase, fetchResultBase, formatTime, friendlyBindingNames, getBindingLocalSupport, getBindingTypeFriendlyName, getBooleanEnvironmentVariableFactory, getBrowserRenderingHeadfulFromEnv, getBuildConditionsFromEnv, getBuildPlatformFromEnv, getC3CommandFromEnv, getCIGeneratePreviewAlias, getCIMatchTag, getCIOverrideName, getCIOverrideNetworkModeHost, getCfFetchEnabledFromEnv, getCfFetchPathFromEnv, getCloudflareApiBaseUrl, getCloudflareApiEnvironmentFromEnv, getCloudflareComplianceRegion, getCloudflareEnv, getCloudflareIncludeProcessEnvFromEnv, getCloudflareLoadDevVarsFromDotEnv, getCloudflaredPathFromEnv, getComplianceRegionSubdomain, getD1ExtraLocationChoices, getDisableConfigWatching, getDockerPath, getEnvironmentVariableFactory, getGlobalWranglerConfigPath, getHostFromRoute, getHostFromUrl, getLocalExplorerEnabledFromEnv, getOpenNextDeployFromEnv, getOutputFileDirectoryFromEnv, getOutputFilePathFromEnv, getRegistryPath, getSanitizeLogs, getSubdomainMixedStateCheckDisabled, getTraceHeader, getWorkersCIBranchName, getWranglerCacheDirFromEnv, getWranglerHiddenDirPath, getWranglerHideBanner, getWranglerSendErrorReportsFromEnv, getWranglerSendMetricsFromEnv, getWranglerTmpDir, getZoneFromRoute, hasCursor, hasMorePages, hasProperty, isDockerfile, isOptionalProperty, isPagesConfig, isRequiredProperty, isValidR2BucketName, isWAFBlockResponse, maybeAddTraceHeader, normalizeAndValidateConfig, performApiFetchBase, renderError, retryOnAPIFailure, spawnCloudflared, startTunnel, sweepStaleWranglerTmpDirs, throwFetchError, truncate, validatePagesConfig };