create-cloudflare 2.72.6 → 2.72.8

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 (2) hide show
  1. package/dist/cli.js +1061 -457
  2. package/package.json +7 -8
package/dist/cli.js CHANGED
@@ -77461,7 +77461,7 @@ function dedent(templ) {
77461
77461
  __name(dedent, "dedent");
77462
77462
  var esm_default = dedent;
77463
77463
 
77464
- // ../workers-utils/dist/chunk-V6JSHOVJ.mjs
77464
+ // ../workers-utils/dist/chunk-JGKSDUFK.mjs
77465
77465
  init_chunk_Q72B4Q5Z();
77466
77466
  var import_node_fs = require("node:fs");
77467
77467
  var import_node_path = __toESM(require("node:path"), 1);
@@ -77495,6 +77495,28 @@ function hasDurableObjectExports(exports$1) {
77495
77495
  return Object.keys(getDurableObjectExports(exports$1)).length > 0;
77496
77496
  }
77497
77497
  __name(hasDurableObjectExports, "hasDurableObjectExports");
77498
+ var CONTAINER_IMAGES_BINDING = "EXPERIMENTAL_CLOUDFLARE_CONTAINER_IMAGES";
77499
+ function isDurableObjectContainerApp(container) {
77500
+ return container.scheduling_policy === "durable_object";
77501
+ }
77502
+ __name(isDurableObjectContainerApp, "isDurableObjectContainerApp");
77503
+ function getDurableObjectContainerApps(containers) {
77504
+ return Array.isArray(containers) ? containers.filter(isDurableObjectContainerApp) : [];
77505
+ }
77506
+ __name(getDurableObjectContainerApps, "getDurableObjectContainerApps");
77507
+ function getResolvedDurableObjectContainerApps(containers, exports$1) {
77508
+ return getDurableObjectContainerApps(containers).map((container) => {
77509
+ const className = resolveContainerClassName(container, exports$1);
77510
+ if (typeof className !== "string" || className.length === 0) {
77511
+ throw new UserError(
77512
+ `The container "${container.name}" is not linked to a Durable Object. Either set "containers.class_name", or reference this container from a Durable Object's \`exports\` entry via its "container" field.`,
77513
+ { telemetryMessage: "durable object container class unresolved" }
77514
+ );
77515
+ }
77516
+ return { ...container, class_name: className };
77517
+ });
77518
+ }
77519
+ __name(getResolvedDurableObjectContainerApps, "getResolvedDurableObjectContainerApps");
77498
77520
  function getContainerNameToClassNameMap(exports$1) {
77499
77521
  const containerNameToClassName = /* @__PURE__ */ new Map();
77500
77522
  for (const [className, entry] of Object.entries(
@@ -77528,6 +77550,113 @@ function getContainerDurableObjectClassNames(containers, exports$1) {
77528
77550
  return classNames;
77529
77551
  }
77530
77552
  __name(getContainerDurableObjectClassNames, "getContainerDurableObjectClassNames");
77553
+ function getDurableObjectClassNameToUseSQLiteMap(migrations, exports$1) {
77554
+ const durableObjectClassNameToUseSQLiteMap = /* @__PURE__ */ new Map();
77555
+ (migrations ?? []).forEach((migration) => {
77556
+ migration.deleted_classes?.forEach((deleted_class) => {
77557
+ if (!durableObjectClassNameToUseSQLiteMap.delete(deleted_class)) {
77558
+ throw new UserError(
77559
+ `Cannot apply deleted_classes migration to non-existent class ${deleted_class}`,
77560
+ {
77561
+ telemetryMessage: "durable object deleted class migration missing class"
77562
+ }
77563
+ );
77564
+ }
77565
+ });
77566
+ migration.renamed_classes?.forEach(({ from, to }) => {
77567
+ const useSQLite = durableObjectClassNameToUseSQLiteMap.get(from);
77568
+ if (useSQLite === void 0) {
77569
+ throw new UserError(
77570
+ `Cannot apply renamed_classes migration to non-existent class ${from}`,
77571
+ {
77572
+ telemetryMessage: "durable object renamed class migration missing class"
77573
+ }
77574
+ );
77575
+ } else {
77576
+ durableObjectClassNameToUseSQLiteMap.delete(from);
77577
+ durableObjectClassNameToUseSQLiteMap.set(to, useSQLite);
77578
+ }
77579
+ });
77580
+ migration.new_classes?.forEach((new_class) => {
77581
+ if (durableObjectClassNameToUseSQLiteMap.has(new_class)) {
77582
+ throw new UserError(
77583
+ `Cannot apply new_classes migration to existing class ${new_class}`,
77584
+ {
77585
+ telemetryMessage: "durable object new class migration existing class"
77586
+ }
77587
+ );
77588
+ } else {
77589
+ durableObjectClassNameToUseSQLiteMap.set(new_class, false);
77590
+ }
77591
+ });
77592
+ migration.new_sqlite_classes?.forEach((new_class) => {
77593
+ if (durableObjectClassNameToUseSQLiteMap.has(new_class)) {
77594
+ throw new UserError(
77595
+ `Cannot apply new_sqlite_classes migration to existing class ${new_class}`,
77596
+ {
77597
+ telemetryMessage: "durable object new sqlite class migration existing class"
77598
+ }
77599
+ );
77600
+ } else {
77601
+ durableObjectClassNameToUseSQLiteMap.set(new_class, true);
77602
+ }
77603
+ });
77604
+ });
77605
+ const durableObjectExports = getDurableObjectExports(exports$1 ?? {});
77606
+ for (const [className, entry] of Object.entries(durableObjectExports)) {
77607
+ if (entry.type !== "durable-object") {
77608
+ continue;
77609
+ }
77610
+ if (entry.state === void 0 || entry.state === "created" || entry.state === "expecting-transfer") {
77611
+ durableObjectClassNameToUseSQLiteMap.set(
77612
+ className,
77613
+ entry.storage === "sqlite"
77614
+ );
77615
+ }
77616
+ }
77617
+ return durableObjectClassNameToUseSQLiteMap;
77618
+ }
77619
+ __name(getDurableObjectClassNameToUseSQLiteMap, "getDurableObjectClassNameToUseSQLiteMap");
77620
+ function validateDurableObjectContainerApplications(config50, containers = getDurableObjectContainerApps(
77621
+ config50.containers
77622
+ )) {
77623
+ const allDOs = getDurableObjectClassNameToUseSQLiteMap(
77624
+ config50.migrations,
77625
+ config50.exports
77626
+ );
77627
+ for (const container of getResolvedDurableObjectContainerApps(
77628
+ containers,
77629
+ config50.exports
77630
+ )) {
77631
+ const maybeBoundDO = config50.durable_objects.bindings.find(
77632
+ (durableObject) => durableObject.class_name === container.class_name
77633
+ );
77634
+ const useSQLite = allDOs.get(container.class_name);
77635
+ if (useSQLite === void 0 && maybeBoundDO === void 0) {
77636
+ throw new UserError(
77637
+ `The container class_name ${container.class_name} does not match any durable object class_name defined in your Wrangler config file. Note that the durable object must be defined in the same script as the container.`,
77638
+ { telemetryMessage: "no DO defined that matches container class_name" }
77639
+ );
77640
+ }
77641
+ if (maybeBoundDO?.script_name !== void 0) {
77642
+ throw new UserError(
77643
+ `The container ${container.name} is referencing the durable object ${container.class_name}, which appears to be defined on the ${maybeBoundDO.script_name} Worker instead (via the 'script_name' field). You cannot configure a container on a Durable Object that is defined in another Worker.`,
77644
+ {
77645
+ telemetryMessage: "container class_name refers to an external durable object"
77646
+ }
77647
+ );
77648
+ }
77649
+ if (useSQLite === false) {
77650
+ throw new UserError(
77651
+ `The container ${container.name} references Durable Object class ${container.class_name}, which uses the legacy KV storage backend. Durable Object-managed Containers require SQLite-backed Durable Objects.`,
77652
+ {
77653
+ telemetryMessage: "durable object container class uses legacy storage"
77654
+ }
77655
+ );
77656
+ }
77657
+ }
77658
+ }
77659
+ __name(validateDurableObjectContainerApplications, "validateDurableObjectContainerApplications");
77531
77660
  function createScanner(text, ignoreTrivia = false) {
77532
77661
  const len = text.length;
77533
77662
  let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
@@ -79824,7 +79953,7 @@ var APIError = class extends ParseError {
79824
79953
  }
79825
79954
  isGatewayError() {
79826
79955
  if (this.#status !== void 0) {
79827
- return [524].includes(this.#status);
79956
+ return [502, 503, 504, 524].includes(this.#status);
79828
79957
  }
79829
79958
  return false;
79830
79959
  }
@@ -80284,9 +80413,9 @@ function formatConfigSnippet(snippet, configPath, formatted = true) {
80284
80413
  }
80285
80414
  __name(formatConfigSnippet, "formatConfigSnippet");
80286
80415
 
80287
- // ../workers-utils/dist/chunk-XADL62NU.mjs
80416
+ // ../workers-utils/dist/chunk-5H6GBNUC.mjs
80288
80417
  init_chunk_Q72B4Q5Z();
80289
- var DEFAULT_COMPAT_DATE = "2026-09-07";
80418
+ var DEFAULT_COMPAT_DATE = "2026-09-15";
80290
80419
  function assertNever(_value) {
80291
80420
  }
80292
80421
  __name(assertNever, "assertNever");
@@ -80566,13 +80695,6 @@ function mapWorkerMetadataBindings(bindings) {
80566
80695
  }
80567
80696
  ];
80568
80697
  break;
80569
- case "websearch":
80570
- {
80571
- configObj.websearch = {
80572
- binding: binding.name
80573
- };
80574
- }
80575
- break;
80576
80698
  case "agent_memory": {
80577
80699
  configObj.agent_memory = [
80578
80700
  ...configObj.agent_memory ?? [],
@@ -81043,7 +81165,7 @@ function getGlobalWranglerCachePath() {
81043
81165
  }
81044
81166
  __name(getGlobalWranglerCachePath, "getGlobalWranglerCachePath");
81045
81167
 
81046
- // ../workers-utils/dist/chunk-XUGGRRBO.mjs
81168
+ // ../workers-utils/dist/chunk-IYSONYTF.mjs
81047
81169
  init_chunk_Q72B4Q5Z();
81048
81170
  var import_node_path3 = __toESM(require("node:path"), 1);
81049
81171
  var getC3CommandFromEnv = getEnvironmentVariableFactory({
@@ -81082,6 +81204,9 @@ var getCloudflareApiEnvironmentFromEnv = getEnvironmentVariableFactory(
81082
81204
  choices: ["production", "staging"]
81083
81205
  }
81084
81206
  );
81207
+ var COMPLIANCE_REGION_CONFIG_UNKNOWN = {
81208
+ compliance_region: void 0
81209
+ };
81085
81210
  var getCloudflareComplianceRegionFromEnv = getEnvironmentVariableFactory({
81086
81211
  variableName: "CLOUDFLARE_COMPLIANCE_REGION",
81087
81212
  choices: ["public", "fedramp_high"]
@@ -81109,6 +81234,15 @@ function getComplianceRegionSubdomain(complianceConfig) {
81109
81234
  return getCloudflareComplianceRegion(complianceConfig) === "fedramp_high" ? ".fed" : "";
81110
81235
  }
81111
81236
  __name(getComplianceRegionSubdomain, "getComplianceRegionSubdomain");
81237
+ function getCloudflareContainerRegistry(complianceConfig = COMPLIANCE_REGION_CONFIG_UNKNOWN) {
81238
+ if (process.env.CLOUDFLARE_CONTAINER_REGISTRY) {
81239
+ return process.env.CLOUDFLARE_CONTAINER_REGISTRY;
81240
+ }
81241
+ const environmentPrefix = process.env.WRANGLER_API_ENVIRONMENT === "staging" ? "staging." : "";
81242
+ const complianceRegionSubdomain = getComplianceRegionSubdomain(complianceConfig);
81243
+ return `${environmentPrefix}registry${complianceRegionSubdomain}.cloudflare.com`;
81244
+ }
81245
+ __name(getCloudflareContainerRegistry, "getCloudflareContainerRegistry");
81112
81246
  function getStagingSubdomain() {
81113
81247
  return getCloudflareApiEnvironmentFromEnv() === "staging" ? ".staging" : "";
81114
81248
  }
@@ -81217,11 +81351,11 @@ var import_node_assert2 = __toESM(require("node:assert"), 1);
81217
81351
  var path5 = __toESM(require("node:path"), 1);
81218
81352
  var import_node_path5 = __toESM(require("node:path"), 1);
81219
81353
  var import_node_util3 = require("node:util");
81354
+ var import_node_url2 = require("node:url");
81355
+ var import_undici = __toESM(require_undici(), 1);
81220
81356
  var import_node_child_process2 = require("node:child_process");
81221
81357
  var import_node_crypto = require("node:crypto");
81222
81358
  var import_node_os5 = require("node:os");
81223
- var import_undici = __toESM(require_undici(), 1);
81224
- var import_node_url2 = require("node:url");
81225
81359
  var timersPromises = __toESM(require("node:timers/promises"), 1);
81226
81360
  var import_promises2 = require("node:timers/promises");
81227
81361
  var import_node_console = require("node:console");
@@ -82853,7 +82987,6 @@ var defaultWranglerConfig = {
82853
82987
  vectorize: [],
82854
82988
  ai_search_namespaces: [],
82855
82989
  ai_search: [],
82856
- websearch: void 0,
82857
82990
  agent_memory: [],
82858
82991
  hyperdrive: [],
82859
82992
  workflows: [],
@@ -98162,7 +98295,6 @@ var friendlyBindingNames = {
98162
98295
  vectorize: "Vectorize Index",
98163
98296
  ai_search_namespaces: "AI Search Namespace",
98164
98297
  ai_search: "AI Search Instance",
98165
- websearch: "Web Search",
98166
98298
  agent_memory: "Agent Memory",
98167
98299
  hyperdrive: "Hyperdrive Config",
98168
98300
  r2_buckets: "R2 Bucket",
@@ -98216,7 +98348,6 @@ var bindingTypeFriendlyNames = {
98216
98348
  vectorize: "Vectorize Index",
98217
98349
  ai_search_namespace: "AI Search Namespace",
98218
98350
  ai_search: "AI Search Instance",
98219
- websearch: "Web Search",
98220
98351
  agent_memory: "Agent Memory",
98221
98352
  hyperdrive: "Hyperdrive Config",
98222
98353
  service: "Worker",
@@ -99399,7 +99530,16 @@ function normalizeAndValidateEnvironment(diagnostics, configPath, rawEnv, isDisp
99399
99530
  // `name` is inheritable, so a named environment that doesn't redeclare it
99400
99531
  // still runs under the top level Worker name — fall back to it so the
99401
99532
  // generated container name isn't built from `undefined`.
99402
- validateContainerApp(envName, rawEnv.name ?? rawConfig?.name, configPath),
99533
+ validateContainerApp(
99534
+ envName,
99535
+ rawEnv.name ?? rawConfig?.name,
99536
+ configPath,
99537
+ {
99538
+ complianceConfig: {
99539
+ compliance_region: rawEnv.compliance_region ?? topLevelEnv?.compliance_region
99540
+ }
99541
+ }
99542
+ ),
99403
99543
  void 0
99404
99544
  ),
99405
99545
  send_email: notInheritable(
@@ -99482,16 +99622,6 @@ function normalizeAndValidateEnvironment(diagnostics, configPath, rawEnv, isDisp
99482
99622
  validateBindingArray(envName, validateAISearchBinding),
99483
99623
  []
99484
99624
  ),
99485
- websearch: notInheritable(
99486
- diagnostics,
99487
- topLevelEnv,
99488
- rawConfig,
99489
- rawEnv,
99490
- envName,
99491
- "websearch",
99492
- validateNamedSimpleBinding(envName),
99493
- void 0
99494
- ),
99495
99625
  agent_memory: notInheritable(
99496
99626
  diagnostics,
99497
99627
  topLevelEnv,
@@ -100744,7 +100874,6 @@ var validateUnsafeBinding = /* @__PURE__ */ __name((diagnostics, field, value) =
100744
100874
  "ai",
100745
100875
  "ai_search_namespace",
100746
100876
  "ai_search",
100747
- "websearch",
100748
100877
  "agent_memory",
100749
100878
  "kv_namespace",
100750
100879
  "durable_object_namespace",
@@ -100851,6 +100980,15 @@ function validatePreviewsContainers(envName, configPath) {
100851
100980
  });
100852
100981
  return (diagnostics, field, value, config210) => {
100853
100982
  if (Array.isArray(value)) {
100983
+ const durableObjectPolicyFields = [...value.entries()].filter(
100984
+ ([, entry]) => entry && typeof entry === "object" && entry.scheduling_policy === "durable_object"
100985
+ ).map(([index]) => `"${field}[${index}].scheduling_policy"`);
100986
+ if (durableObjectPolicyFields.length > 0) {
100987
+ diagnostics.errors.push(
100988
+ `${durableObjectPolicyFields.join(", ")} cannot be "durable_object". Durable Object-managed Containers are configured only in the top-level "containers" array.`
100989
+ );
100990
+ return false;
100991
+ }
100854
100992
  const nameFields = [...value.entries()].filter(
100855
100993
  ([, entry]) => entry && typeof entry === "object" && "name" in entry
100856
100994
  ).map(([index]) => `"${field}[${index}].name"`);
@@ -100885,6 +101023,128 @@ function validatePreviewsContainers(envName, configPath) {
100885
101023
  };
100886
101024
  }
100887
101025
  __name(validatePreviewsContainers, "validatePreviewsContainers");
101026
+ function validateDurableObjectContainerImages(diagnostics, field, images, complianceConfig) {
101027
+ if (images === void 0) {
101028
+ return true;
101029
+ }
101030
+ if (typeof images !== "object" || images === null || Array.isArray(images) || Object.keys(images).length === 0) {
101031
+ diagnostics.errors.push(
101032
+ `"${field}" must be a non-empty object when present.`
101033
+ );
101034
+ return false;
101035
+ }
101036
+ let valid = true;
101037
+ const entries = Object.entries(images);
101038
+ if (entries.length > 100) {
101039
+ diagnostics.errors.push(`"${field}" must contain at most 100 images.`);
101040
+ valid = false;
101041
+ }
101042
+ for (const [imageName, imageValue] of entries) {
101043
+ const imageField = `${field}.${imageName}`;
101044
+ if (imageName.length === 0 || imageName.length > 128) {
101045
+ diagnostics.errors.push(
101046
+ `"${field}" image names must be between 1 and 128 characters.`
101047
+ );
101048
+ valid = false;
101049
+ }
101050
+ if (typeof imageValue !== "object" || imageValue === null || Array.isArray(imageValue)) {
101051
+ diagnostics.errors.push(
101052
+ `"${imageField}" must be an object with either a "dockerfile" or "image" field.`
101053
+ );
101054
+ valid = false;
101055
+ continue;
101056
+ }
101057
+ const image = imageValue;
101058
+ const hasDockerfile = image.dockerfile !== void 0;
101059
+ const hasImage = image.image !== void 0;
101060
+ if (hasDockerfile === hasImage) {
101061
+ diagnostics.errors.push(
101062
+ `"${imageField}" must specify exactly one of "dockerfile" or "image".`
101063
+ );
101064
+ valid = false;
101065
+ }
101066
+ if (hasDockerfile && (typeof image.dockerfile !== "string" || image.dockerfile.length === 0)) {
101067
+ diagnostics.errors.push(
101068
+ `"${imageField}.dockerfile" must be a non-empty string.`
101069
+ );
101070
+ valid = false;
101071
+ }
101072
+ if (hasImage && (typeof image.image !== "string" || image.image.length === 0)) {
101073
+ diagnostics.errors.push(
101074
+ `"${imageField}.image" must be a non-empty string.`
101075
+ );
101076
+ valid = false;
101077
+ }
101078
+ if (typeof image.image === "string" && image.image.length > 0) {
101079
+ const registry2 = getCloudflareContainerRegistry(complianceConfig);
101080
+ const prefix = `${registry2}/`;
101081
+ const reference = image.image.slice(prefix.length);
101082
+ const digestReference = reference.match(
101083
+ /^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*)+@sha256:[a-f0-9]{64}$/
101084
+ );
101085
+ if (!image.image.startsWith(prefix) || digestReference?.[0] !== reference) {
101086
+ diagnostics.errors.push(
101087
+ `"${imageField}.image" must be a digest-pinned image in the managed registry, in the form "${registry2}/<account-id>/<repository>@sha256:<64 lowercase hex characters>".`
101088
+ );
101089
+ valid = false;
101090
+ }
101091
+ }
101092
+ const isDockerfileBuild = hasDockerfile && !hasImage;
101093
+ if (isDockerfileBuild) {
101094
+ if (image.build_context !== void 0 && (typeof image.build_context !== "string" || image.build_context.length === 0)) {
101095
+ diagnostics.errors.push(
101096
+ `"${imageField}.build_context" must be a non-empty string.`
101097
+ );
101098
+ valid = false;
101099
+ }
101100
+ if (image.build_vars !== void 0 && (typeof image.build_vars !== "object" || image.build_vars === null || Array.isArray(image.build_vars) || Object.values(image.build_vars).some(
101101
+ (value) => typeof value !== "string"
101102
+ ))) {
101103
+ diagnostics.errors.push(
101104
+ `"${imageField}.build_vars" must be an object with string values.`
101105
+ );
101106
+ valid = false;
101107
+ }
101108
+ }
101109
+ const unsupportedFields = Object.keys(image).filter(
101110
+ (property) => property !== "dockerfile" && property !== "image" && !(isDockerfileBuild && (property === "build_context" || property === "build_vars"))
101111
+ );
101112
+ if (unsupportedFields.length > 0) {
101113
+ diagnostics.errors.push(
101114
+ `Unexpected fields found in ${imageField} field: ${unsupportedFields.map((property) => `"${property}"`).join(", ")}`
101115
+ );
101116
+ valid = false;
101117
+ }
101118
+ }
101119
+ return valid;
101120
+ }
101121
+ __name(validateDurableObjectContainerImages, "validateDurableObjectContainerImages");
101122
+ function validateDurableObjectContainerUnsafe(diagnostics, field, value) {
101123
+ if (value === void 0) {
101124
+ return;
101125
+ }
101126
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
101127
+ diagnostics.errors.push(`"${field}" should be an object.`);
101128
+ return;
101129
+ }
101130
+ const unsafe = value;
101131
+ const configuration = unsafe.configuration;
101132
+ if (Object.keys(unsafe).some((key) => key !== "configuration") || configuration !== void 0 && (typeof configuration !== "object" || configuration === null || Array.isArray(configuration) || Object.keys(configuration).some((key) => key !== "experimental_flags"))) {
101133
+ diagnostics.errors.push(
101134
+ `Only "${field}.configuration.experimental_flags" is supported for Durable Object-managed Containers.`
101135
+ );
101136
+ return;
101137
+ }
101138
+ if (configuration !== void 0) {
101139
+ const flags = configuration.experimental_flags;
101140
+ if (flags !== void 0 && (!Array.isArray(flags) || flags.some((flag) => typeof flag !== "string"))) {
101141
+ diagnostics.errors.push(
101142
+ `"${field}.configuration.experimental_flags" should be an array of strings.`
101143
+ );
101144
+ }
101145
+ }
101146
+ }
101147
+ __name(validateDurableObjectContainerUnsafe, "validateDurableObjectContainerUnsafe");
100888
101148
  function validateContainerApp(envName, topLevelName, configPath, options = {}) {
100889
101149
  const { generateDefaultName = true } = options;
100890
101150
  return (diagnostics, field, value, config210) => {
@@ -100898,6 +101158,8 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
100898
101158
  return false;
100899
101159
  }
100900
101160
  for (const containerAppOptional of value) {
101161
+ const isDurableObjectManaged = containerAppOptional.scheduling_policy === "durable_object";
101162
+ const hasValidDurableObjectClassName = typeof containerAppOptional.class_name === "string" && containerAppOptional.class_name.length > 0;
100901
101163
  validateOptionalProperty(
100902
101164
  diagnostics,
100903
101165
  field,
@@ -100905,6 +101167,11 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
100905
101167
  containerAppOptional.class_name,
100906
101168
  "string"
100907
101169
  );
101170
+ if (isDurableObjectManaged && containerAppOptional.class_name === "") {
101171
+ diagnostics.errors.push(
101172
+ `"containers.class_name" must be a non-empty string when specified for a Durable Object-managed Container.`
101173
+ );
101174
+ }
100908
101175
  validateOptionalProperty(
100909
101176
  diagnostics,
100910
101177
  field,
@@ -100912,7 +101179,7 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
100912
101179
  containerAppOptional.name,
100913
101180
  "string"
100914
101181
  );
100915
- if (generateDefaultName && !containerAppOptional.name) {
101182
+ if (generateDefaultName && !containerAppOptional.name && (!isDurableObjectManaged || containerAppOptional.class_name === void 0 || hasValidDurableObjectClassName)) {
100916
101183
  if (containerAppOptional.class_name === void 0) {
100917
101184
  diagnostics.errors.push(
100918
101185
  `"containers.name" is required when "containers.class_name" is not defined, because there is no class name to derive a default name from. Either name this container and reference it from a Durable Object's \`exports\` entry, or set "containers.class_name".`
@@ -100927,6 +101194,46 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
100927
101194
  containerAppOptional.name = name3.toLowerCase().replace(/ /g, "-");
100928
101195
  }
100929
101196
  }
101197
+ if (isDurableObjectManaged) {
101198
+ validateDurableObjectContainerImages(
101199
+ diagnostics,
101200
+ `${field}.images`,
101201
+ containerAppOptional.images,
101202
+ options.complianceConfig
101203
+ );
101204
+ validateContainerObservability(
101205
+ diagnostics,
101206
+ `${field}.observability`,
101207
+ containerAppOptional.observability,
101208
+ config210
101209
+ );
101210
+ if (containerAppOptional.observability?.target_instance_count !== void 0 || containerAppOptional.observability?.target_instance_percentage !== void 0) {
101211
+ diagnostics.errors.push(
101212
+ `"${field}.observability" only supports enabling or disabling logs for Durable Object-managed Containers; instance targeting is not supported.`
101213
+ );
101214
+ }
101215
+ validateDurableObjectContainerUnsafe(
101216
+ diagnostics,
101217
+ `${field}.unsafe`,
101218
+ containerAppOptional.unsafe
101219
+ );
101220
+ const unsupportedFields = Object.keys(containerAppOptional).filter(
101221
+ (key) => ![
101222
+ "name",
101223
+ "class_name",
101224
+ "scheduling_policy",
101225
+ "images",
101226
+ "observability",
101227
+ "unsafe"
101228
+ ].includes(key)
101229
+ );
101230
+ if (unsupportedFields.length > 0) {
101231
+ diagnostics.errors.push(
101232
+ `Unsupported fields for Durable Object-managed Containers in ${field}: ${unsupportedFields.map((key) => `"${key}"`).join(",")}. Only "name", "class_name", "scheduling_policy", "images", "observability", and restricted "unsafe" settings are supported.`
101233
+ );
101234
+ }
101235
+ continue;
101236
+ }
100930
101237
  if (!containerAppOptional.configuration?.image && !containerAppOptional.image) {
100931
101238
  diagnostics.errors.push(
100932
101239
  `"containers.image" field must be defined for each container app. This should be the path to your Dockerfile or an image URI pointing to the Cloudflare registry.`
@@ -101065,6 +101372,12 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
101065
101372
  containerAppOptional.image_vars,
101066
101373
  "object"
101067
101374
  );
101375
+ validateContainerObservability(
101376
+ diagnostics,
101377
+ `${field}.observability`,
101378
+ containerAppOptional.observability,
101379
+ config210
101380
+ );
101068
101381
  validateOptionalProperty(
101069
101382
  diagnostics,
101070
101383
  field,
@@ -101108,6 +101421,7 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
101108
101421
  "image",
101109
101422
  "image_build_context",
101110
101423
  "image_vars",
101424
+ "observability",
101111
101425
  "class_name",
101112
101426
  "scheduling_policy",
101113
101427
  "instance_type",
@@ -101933,6 +102247,7 @@ var validateBindingsHaveUniqueNames = /* @__PURE__ */ __name((diagnostics, confi
101933
102247
  ])
101934
102248
  );
101935
102249
  bindingsGroupedByType["Secret"] = config210.secrets?.required ?? [];
102250
+ bindingsGroupedByType["Container images"] = [CONTAINER_IMAGES_BINDING];
101936
102251
  const bindingsGroupedByName = {};
101937
102252
  for (const bindingType in bindingsGroupedByType) {
101938
102253
  const bindingNames = bindingsGroupedByType[bindingType];
@@ -102757,6 +103072,8 @@ var validatePreviewsConfig = /* @__PURE__ */ __name((envName, configPath) => (di
102757
103072
  "d1_databases",
102758
103073
  "r2_buckets",
102759
103074
  "vectorize",
103075
+ "ai_search_namespaces",
103076
+ "ai_search",
102760
103077
  "hyperdrive",
102761
103078
  "services",
102762
103079
  "analytics_engine_datasets",
@@ -102843,6 +103160,18 @@ var validatePreviewsConfig = /* @__PURE__ */ __name((envName, configPath) => (di
102843
103160
  previews.vectorize,
102844
103161
  void 0
102845
103162
  ) && isValid;
103163
+ isValid = validateBindingArray(envName, validateAISearchNamespaceBinding)(
103164
+ diagnostics,
103165
+ `${field}.ai_search_namespaces`,
103166
+ previews.ai_search_namespaces,
103167
+ void 0
103168
+ ) && isValid;
103169
+ isValid = validateBindingArray(envName, validateAISearchBinding)(
103170
+ diagnostics,
103171
+ `${field}.ai_search`,
103172
+ previews.ai_search,
103173
+ void 0
103174
+ ) && isValid;
102846
103175
  isValid = validateBindingArray(envName, validateHyperdriveBinding)(
102847
103176
  diagnostics,
102848
103177
  `${field}.hyperdrive`,
@@ -103349,6 +103678,133 @@ var validateExports = /* @__PURE__ */ __name((diagnostics, field, value) => {
103349
103678
  }
103350
103679
  return valid;
103351
103680
  }, "validateExports");
103681
+ var CONTAINER_OBSERVABILITY_TARGET_INSTANCE_PERCENTAGE_MIN = 1;
103682
+ var CONTAINER_OBSERVABILITY_TARGET_INSTANCE_PERCENTAGE_MAX = 99;
103683
+ var CONTAINER_OBSERVABILITY_TARGET_INSTANCE_COUNT_MIN = 1;
103684
+ function isContainerObservabilityEnabled(observability) {
103685
+ return observability?.logs?.enabled === true || observability?.enabled === true;
103686
+ }
103687
+ __name(isContainerObservabilityEnabled, "isContainerObservabilityEnabled");
103688
+ function hasConflictingContainerObservabilityEnabledValues(observability) {
103689
+ return typeof observability.enabled === "boolean" && typeof observability.logs?.enabled === "boolean" && observability.enabled !== observability.logs.enabled;
103690
+ }
103691
+ __name(hasConflictingContainerObservabilityEnabledValues, "hasConflictingContainerObservabilityEnabledValues");
103692
+ var validateContainerObservability = /* @__PURE__ */ __name((diagnostics, field, value) => {
103693
+ if (value === void 0) {
103694
+ return true;
103695
+ }
103696
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
103697
+ diagnostics.errors.push(
103698
+ `"${field}" should be an object but got ${JSON.stringify(value)}.`
103699
+ );
103700
+ return false;
103701
+ }
103702
+ const val = value;
103703
+ let isValid = true;
103704
+ isValid = validateOptionalProperty(
103705
+ diagnostics,
103706
+ field,
103707
+ "enabled",
103708
+ val.enabled,
103709
+ "boolean"
103710
+ ) && isValid;
103711
+ if (val.logs !== void 0) {
103712
+ if (typeof val.logs !== "object" || val.logs === null || Array.isArray(val.logs)) {
103713
+ diagnostics.errors.push(
103714
+ `Expected "${field}.logs" to be of type object but got ${JSON.stringify(
103715
+ val.logs
103716
+ )}.`
103717
+ );
103718
+ isValid = false;
103719
+ } else {
103720
+ isValid = validateOptionalProperty(
103721
+ diagnostics,
103722
+ field,
103723
+ "logs.enabled",
103724
+ val.logs.enabled,
103725
+ "boolean"
103726
+ ) && isValid;
103727
+ isValid = validateAdditionalProperties(
103728
+ diagnostics,
103729
+ `${field}.logs`,
103730
+ Object.keys(val.logs),
103731
+ ["enabled"]
103732
+ ) && isValid;
103733
+ }
103734
+ }
103735
+ if (val.enabled === void 0 && val.target_instance_percentage === void 0 && val.target_instance_count === void 0 && (val.logs === void 0 || typeof val.logs === "object" && val.logs !== null && !Array.isArray(val.logs) && val.logs.enabled === void 0)) {
103736
+ isValid = validateAtLeastOnePropertyRequired(diagnostics, field, [
103737
+ {
103738
+ key: "enabled",
103739
+ value: val.enabled,
103740
+ type: "boolean"
103741
+ },
103742
+ {
103743
+ key: "logs.enabled",
103744
+ value: val.logs?.enabled,
103745
+ type: "boolean"
103746
+ }
103747
+ ]) && isValid;
103748
+ }
103749
+ isValid = validateOptionalProperty(
103750
+ diagnostics,
103751
+ field,
103752
+ "target_instance_percentage",
103753
+ val.target_instance_percentage,
103754
+ "number"
103755
+ ) && isValid;
103756
+ isValid = validateOptionalProperty(
103757
+ diagnostics,
103758
+ field,
103759
+ "target_instance_count",
103760
+ val.target_instance_count,
103761
+ "number"
103762
+ ) && isValid;
103763
+ isValid = validateAdditionalProperties(diagnostics, field, Object.keys(val), [
103764
+ "enabled",
103765
+ "logs",
103766
+ "target_instance_percentage",
103767
+ "target_instance_count"
103768
+ ]) && isValid;
103769
+ if (hasConflictingContainerObservabilityEnabledValues(val)) {
103770
+ diagnostics.errors.push(
103771
+ `"${field}.enabled" and "${field}.logs.enabled" cannot be set to different values.`
103772
+ );
103773
+ isValid = false;
103774
+ }
103775
+ if (val.target_instance_percentage !== void 0 && val.target_instance_count !== void 0) {
103776
+ diagnostics.errors.push(
103777
+ `"${field}.target_instance_percentage" and "${field}.target_instance_count" cannot both be set.`
103778
+ );
103779
+ isValid = false;
103780
+ }
103781
+ if (typeof val.target_instance_percentage === "number" && (!Number.isInteger(val.target_instance_percentage) || val.target_instance_percentage < CONTAINER_OBSERVABILITY_TARGET_INSTANCE_PERCENTAGE_MIN || val.target_instance_percentage > CONTAINER_OBSERVABILITY_TARGET_INSTANCE_PERCENTAGE_MAX)) {
103782
+ diagnostics.errors.push(
103783
+ `"${field}.target_instance_percentage" must be an integer between ${CONTAINER_OBSERVABILITY_TARGET_INSTANCE_PERCENTAGE_MIN} and ${CONTAINER_OBSERVABILITY_TARGET_INSTANCE_PERCENTAGE_MAX} inclusive.`
103784
+ );
103785
+ isValid = false;
103786
+ }
103787
+ if (typeof val.target_instance_count === "number" && (!Number.isInteger(val.target_instance_count) || val.target_instance_count < CONTAINER_OBSERVABILITY_TARGET_INSTANCE_COUNT_MIN)) {
103788
+ diagnostics.errors.push(
103789
+ `"${field}.target_instance_count" must be a positive integer.`
103790
+ );
103791
+ isValid = false;
103792
+ }
103793
+ const observabilityEnabled = isContainerObservabilityEnabled(val);
103794
+ if (val.target_instance_percentage !== void 0 && !observabilityEnabled) {
103795
+ diagnostics.errors.push(
103796
+ `"${field}.target_instance_percentage" requires "${field}.enabled" or "${field}.logs.enabled" to be true because container observability overrides root observability.`
103797
+ );
103798
+ isValid = false;
103799
+ }
103800
+ if (val.target_instance_count !== void 0 && !observabilityEnabled) {
103801
+ diagnostics.errors.push(
103802
+ `"${field}.target_instance_count" requires "${field}.enabled" or "${field}.logs.enabled" to be true because container observability overrides root observability.`
103803
+ );
103804
+ isValid = false;
103805
+ }
103806
+ return isValid;
103807
+ }, "validateContainerObservability");
103352
103808
  var validateObservability = /* @__PURE__ */ __name((diagnostics, field, value) => {
103353
103809
  if (value === void 0) {
103354
103810
  return true;
@@ -103869,7 +104325,6 @@ var BINDING_LOCAL_SUPPORT = {
103869
104325
  flagship: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
103870
104326
  vpc_service: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
103871
104327
  vpc_network: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
103872
- websearch: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator",
103873
104328
  agent_memory: "DO-NOT-USE-this-resource-will-never-have-a-local-simulator"
103874
104329
  };
103875
104330
  function getBindingLocalSupport(type) {
@@ -104363,11 +104818,6 @@ function convertConfigToBindings(config210, options) {
104363
104818
  }
104364
104819
  break;
104365
104820
  }
104366
- case "websearch": {
104367
- const { binding, ...x } = info;
104368
- output[binding] = { type: "websearch", ...x };
104369
- break;
104370
- }
104371
104821
  case "agent_memory": {
104372
104822
  for (const { binding, ...x } of info) {
104373
104823
  output[binding] = { type: "agent_memory", ...x };
@@ -104540,7 +104990,6 @@ function printBindings(bindings, options) {
104540
104990
  bindings
104541
104991
  );
104542
104992
  const ai_search = extractBindingsOfType("ai_search", bindings);
104543
- const websearch = extractBindingsOfType("websearch", bindings);
104544
104993
  const agent_memory = extractBindingsOfType("agent_memory", bindings);
104545
104994
  const hyperdrive = extractBindingsOfType("hyperdrive", bindings);
104546
104995
  const r2_buckets = extractBindingsOfType("r2_bucket", bindings);
@@ -104758,16 +105207,6 @@ function printBindings(bindings, options) {
104758
105207
  }))
104759
105208
  );
104760
105209
  }
104761
- if (websearch.length > 0) {
104762
- output.push(
104763
- ...websearch.map(({ binding }) => ({
104764
- name: binding,
104765
- type: getBindingTypeFriendlyName("websearch"),
104766
- value: void 0,
104767
- mode: getMode({ isSimulatedLocally: false })
104768
- }))
104769
- );
104770
- }
104771
105210
  if (agent_memory.length > 0) {
104772
105211
  output.push(
104773
105212
  ...agent_memory.map(({ binding, namespace }) => ({
@@ -105248,7 +105687,9 @@ ${allTailConsumers.map(({ service, streaming }) => {
105248
105687
  }
105249
105688
  log2(
105250
105689
  `${containersTitle}
105251
- ${containers.map((c2) => `- ${c2.name} (${c2.image})`).join("\n")}`
105690
+ ${containers.map(
105691
+ (container) => container.scheduling_policy === "durable_object" ? `- ${container.class_name ?? container.name} (durable_object)` : `- ${container.name} (${container.image})`
105692
+ ).join("\n")}`
105252
105693
  );
105253
105694
  log2("");
105254
105695
  }
@@ -105715,6 +106156,409 @@ function getWranglerTmpDir(projectRoot, prefix, cleanup = true) {
105715
106156
  };
105716
106157
  }
105717
106158
  __name(getWranglerTmpDir, "getWranglerTmpDir");
106159
+ function buildDetailedError(message, ...extra) {
106160
+ return new ParseError({
106161
+ text: message,
106162
+ notes: extra.map((text) => ({ text })),
106163
+ telemetryMessage: false
106164
+ });
106165
+ }
106166
+ __name(buildDetailedError, "buildDetailedError");
106167
+ function maybeThrowFriendlyError(error51) {
106168
+ if (error51.message === "workers.api.error.email_verification_required") {
106169
+ throw buildDetailedError(
106170
+ "Please verify your account's email address and try again.",
106171
+ "Check your email for a verification link, or login to https://dash.cloudflare.com and request a new one."
106172
+ );
106173
+ }
106174
+ }
106175
+ __name(maybeThrowFriendlyError, "maybeThrowFriendlyError");
106176
+ function logHeaders(headers, logger) {
106177
+ const clone2 = cloneHeaders(headers);
106178
+ clone2.delete("Authorization");
106179
+ logger.debugWithSanitization?.(
106180
+ "HEADERS:",
106181
+ JSON.stringify(Object.fromEntries(clone2), null, 2)
106182
+ );
106183
+ }
106184
+ __name(logHeaders, "logHeaders");
106185
+ async function performApiFetchBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
106186
+ (0, import_node_assert2.default)(credentials, "credentials are required for performApiFetch");
106187
+ const method = init.method ?? "GET";
106188
+ (0, import_node_assert2.default)(
106189
+ resource.startsWith("/"),
106190
+ `CF API fetch - resource path must start with a "/" but got "${resource}"`
106191
+ );
106192
+ const headers = cloneHeaders(new import_undici.Headers(init.headers));
106193
+ addAuthorizationHeader(headers, credentials);
106194
+ headers.set("User-Agent", userAgent);
106195
+ maybeAddTraceHeader(headers);
106196
+ const queryString = queryParams ? `?${queryParams.toString()}` : "";
106197
+ logger.debug(
106198
+ `-- START CF API REQUEST: ${method} ${getCloudflareApiBaseUrl(complianceConfig)}${resource}`
106199
+ );
106200
+ logger.debugWithSanitization?.("QUERY STRING:", queryString);
106201
+ logHeaders(headers, logger);
106202
+ logger.debugWithSanitization?.("INIT:", JSON.stringify({ ...init }, null, 2));
106203
+ if (init.body instanceof import_undici.FormData) {
106204
+ logger.debugWithSanitization?.(
106205
+ "BODY:",
106206
+ await new import_undici.Response(init.body).text(),
106207
+ null,
106208
+ 2
106209
+ );
106210
+ }
106211
+ logger.debug("-- END CF API REQUEST");
106212
+ return await (0, import_undici.fetch)(
106213
+ `${getCloudflareApiBaseUrl(complianceConfig)}${resource}${queryString}`,
106214
+ {
106215
+ method,
106216
+ ...init,
106217
+ headers,
106218
+ signal: abortSignal
106219
+ }
106220
+ );
106221
+ }
106222
+ __name(performApiFetchBase, "performApiFetchBase");
106223
+ async function fetchInternalBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
106224
+ const method = init.method ?? "GET";
106225
+ const response = await performApiFetchBase(
106226
+ complianceConfig,
106227
+ resource,
106228
+ init,
106229
+ userAgent,
106230
+ logger,
106231
+ queryParams,
106232
+ abortSignal,
106233
+ credentials
106234
+ );
106235
+ const jsonText = await response.text();
106236
+ logger.debug(
106237
+ "-- START CF API RESPONSE:",
106238
+ response.statusText,
106239
+ response.status
106240
+ );
106241
+ logHeaders(response.headers, logger);
106242
+ logger.debugWithSanitization?.("RESPONSE:", jsonText);
106243
+ logger.debug("-- END CF API RESPONSE");
106244
+ const retryAfterMs = parseRetryAfterMs(response.headers);
106245
+ if (!jsonText && (response.status === 204 || response.status === 205)) {
106246
+ return {
106247
+ response: {
106248
+ result: {},
106249
+ success: true,
106250
+ errors: [],
106251
+ messages: []
106252
+ },
106253
+ status: response.status,
106254
+ retryAfterMs
106255
+ };
106256
+ }
106257
+ if (isWAFBlockResponse(response.headers)) {
106258
+ throwWAFBlockError(
106259
+ response.headers,
106260
+ method,
106261
+ resource,
106262
+ response.status,
106263
+ response.statusText,
106264
+ retryAfterMs
106265
+ );
106266
+ }
106267
+ try {
106268
+ const json2 = parseJSON(jsonText);
106269
+ return { response: json2, status: response.status, retryAfterMs };
106270
+ } catch {
106271
+ const rayId = extractWAFBlockRayId(response.headers);
106272
+ throw new APIError({
106273
+ text: "Received a malformed response from the API",
106274
+ notes: [
106275
+ {
106276
+ text: truncate(jsonText, 100)
106277
+ },
106278
+ {
106279
+ text: `${method} ${resource} -> ${response.status} ${response.statusText}`
106280
+ },
106281
+ ...rayId ? [{ text: `Cloudflare Ray ID: ${rayId}` }] : []
106282
+ ],
106283
+ status: response.status,
106284
+ retryAfterMs,
106285
+ telemetryMessage: false
106286
+ });
106287
+ }
106288
+ }
106289
+ __name(fetchInternalBase, "fetchInternalBase");
106290
+ async function fetchResultBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
106291
+ const {
106292
+ response: json2,
106293
+ status: status2,
106294
+ retryAfterMs
106295
+ } = await fetchInternalBase(
106296
+ complianceConfig,
106297
+ resource,
106298
+ init,
106299
+ userAgent,
106300
+ logger,
106301
+ queryParams,
106302
+ abortSignal,
106303
+ credentials
106304
+ );
106305
+ if (json2.success) {
106306
+ return json2.result;
106307
+ } else {
106308
+ throwFetchError(resource, json2, status2, retryAfterMs);
106309
+ }
106310
+ }
106311
+ __name(fetchResultBase, "fetchResultBase");
106312
+ async function fetchListResultBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, credentials) {
106313
+ const results = [];
106314
+ let getMoreResults = true;
106315
+ let cursor;
106316
+ while (getMoreResults) {
106317
+ if (cursor) {
106318
+ queryParams = new import_node_url2.URLSearchParams(queryParams);
106319
+ queryParams.set("cursor", cursor);
106320
+ }
106321
+ const {
106322
+ response: json2,
106323
+ status: status2,
106324
+ retryAfterMs
106325
+ } = await fetchInternalBase(
106326
+ complianceConfig,
106327
+ resource,
106328
+ init,
106329
+ userAgent,
106330
+ logger,
106331
+ queryParams,
106332
+ void 0,
106333
+ credentials
106334
+ );
106335
+ if (json2.success) {
106336
+ results.push(...json2.result);
106337
+ if (hasCursor(json2.result_info)) {
106338
+ cursor = json2.result_info?.cursor;
106339
+ } else {
106340
+ getMoreResults = false;
106341
+ }
106342
+ } else {
106343
+ throwFetchError(resource, json2, status2, retryAfterMs);
106344
+ }
106345
+ }
106346
+ return results;
106347
+ }
106348
+ __name(fetchListResultBase, "fetchListResultBase");
106349
+ function truncate(text, maxLength) {
106350
+ const { length } = text;
106351
+ if (length <= maxLength) {
106352
+ return text;
106353
+ }
106354
+ return `${text.substring(0, maxLength)}... (length = ${length})`;
106355
+ }
106356
+ __name(truncate, "truncate");
106357
+ function isWAFBlockResponse(headers) {
106358
+ return headers.get("cf-mitigated") === "challenge";
106359
+ }
106360
+ __name(isWAFBlockResponse, "isWAFBlockResponse");
106361
+ function parseRetryAfterValue(retryAfter) {
106362
+ if (!retryAfter) {
106363
+ return void 0;
106364
+ }
106365
+ if (/^\d+$/.test(retryAfter.trim())) {
106366
+ return Number(retryAfter) * 1e3;
106367
+ }
106368
+ const retryAfterDate = new Date(retryAfter);
106369
+ if (!Number.isNaN(retryAfterDate.getTime())) {
106370
+ return Math.max(0, retryAfterDate.getTime() - Date.now());
106371
+ }
106372
+ return void 0;
106373
+ }
106374
+ __name(parseRetryAfterValue, "parseRetryAfterValue");
106375
+ function parseRetryAfterMs(headers) {
106376
+ return parseRetryAfterValue(headers.get("Retry-After"));
106377
+ }
106378
+ __name(parseRetryAfterMs, "parseRetryAfterMs");
106379
+ function extractWAFBlockRayId(headers) {
106380
+ return headers.get("cf-ray") ?? void 0;
106381
+ }
106382
+ __name(extractWAFBlockRayId, "extractWAFBlockRayId");
106383
+ function extractAccountTag(resource) {
106384
+ const re = new RegExp("/accounts/([a-zA-Z0-9]+)/?");
106385
+ const matches = re.exec(resource);
106386
+ return matches?.[1];
106387
+ }
106388
+ __name(extractAccountTag, "extractAccountTag");
106389
+ function hasMorePages(result_info) {
106390
+ const page = result_info?.page;
106391
+ const per_page = result_info?.per_page;
106392
+ const total = result_info?.total_count;
106393
+ return page !== void 0 && per_page !== void 0 && total !== void 0 && page * per_page < total;
106394
+ }
106395
+ __name(hasMorePages, "hasMorePages");
106396
+ function renderError(err, level = 0) {
106397
+ const indent2 = " ".repeat(level);
106398
+ const message = err.message ?? "";
106399
+ const chainedMessages = "error_chain" in err ? err.error_chain?.map(
106400
+ (chainedError) => `
106401
+
106402
+ ${indent2}- ${renderError(chainedError, level + 1)}`
106403
+ ).join("\n") ?? "" : "";
106404
+ return (err.code ? `${message} [code: ${err.code}]` : message) + (err.documentation_url ? `
106405
+ ${indent2}To learn more about this error, visit: ${err.documentation_url}` : "") + chainedMessages;
106406
+ }
106407
+ __name(renderError, "renderError");
106408
+ function addAuthorizationHeader(headers, auth, overrideExisting = false) {
106409
+ if (!headers.has("Authorization") || overrideExisting) {
106410
+ if ("apiToken" in auth) {
106411
+ const authorizationHeader = `Bearer ${auth.apiToken}`;
106412
+ validateAuthorizationHeaderValue(authorizationHeader);
106413
+ headers.set("Authorization", authorizationHeader);
106414
+ } else {
106415
+ headers.set("X-Auth-Key", auth.authKey);
106416
+ headers.set("X-Auth-Email", auth.authEmail);
106417
+ }
106418
+ }
106419
+ }
106420
+ __name(addAuthorizationHeader, "addAuthorizationHeader");
106421
+ function validateAuthorizationHeaderValue(value) {
106422
+ for (const character of value) {
106423
+ const codePoint = character.codePointAt(0);
106424
+ if (codePoint === void 0 || codePoint > 255) {
106425
+ throw new UserError(
106426
+ `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.`,
106427
+ {
106428
+ telemetryMessage: "cfetch auth invalid authorization header"
106429
+ }
106430
+ );
106431
+ }
106432
+ }
106433
+ }
106434
+ __name(validateAuthorizationHeaderValue, "validateAuthorizationHeaderValue");
106435
+ function formatAuthorizationHeaderCharacter(character, codePoint) {
106436
+ if (codePoint === void 0) {
106437
+ return '"\\u{unknown}"';
106438
+ }
106439
+ const codePointLabel = `U+${codePoint.toString(16).toUpperCase().padStart(4, "0")}`;
106440
+ const characterLabel = isPrintableCharacter(character) ? `"${character}"` : `"${escapeCharacter(character)}"`;
106441
+ return `${characterLabel} (${codePointLabel})`;
106442
+ }
106443
+ __name(formatAuthorizationHeaderCharacter, "formatAuthorizationHeaderCharacter");
106444
+ function isPrintableCharacter(character) {
106445
+ return !/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(character);
106446
+ }
106447
+ __name(isPrintableCharacter, "isPrintableCharacter");
106448
+ function escapeCharacter(character) {
106449
+ return Array.from(character).map((c2) => {
106450
+ const codePoint = c2.codePointAt(0);
106451
+ if (codePoint === void 0) {
106452
+ return "";
106453
+ }
106454
+ return codePoint <= 65535 ? `\\u${codePoint.toString(16).toUpperCase().padStart(4, "0")}` : `\\u{${codePoint.toString(16).toUpperCase()}}`;
106455
+ }).join("");
106456
+ }
106457
+ __name(escapeCharacter, "escapeCharacter");
106458
+ function throwFetchError(resource, response, status2, retryAfterMs) {
106459
+ const errors = response.errors ?? [];
106460
+ for (const error52 of errors) {
106461
+ maybeThrowFriendlyError(error52);
106462
+ }
106463
+ const notes = [
106464
+ ...errors.map((err) => ({ text: renderError(err) })),
106465
+ ...response.messages?.map((msg) => ({
106466
+ text: typeof msg === "string" ? msg : msg.message ?? String(msg)
106467
+ })) ?? []
106468
+ ];
106469
+ if (notes.length === 0) {
106470
+ const raw = response;
106471
+ const fallbackMessage = typeof raw.error === "string" ? `${raw.error}${raw.code ? ` [code: ${raw.code}]` : ""}` : void 0;
106472
+ if (fallbackMessage) {
106473
+ notes.push({ text: fallbackMessage });
106474
+ }
106475
+ }
106476
+ if (retryAfterMs !== void 0) {
106477
+ notes.push({
106478
+ text: `The API responded with a "Retry-After" header indicating you should wait ${Math.ceil(retryAfterMs / 1e3)} second(s) before retrying.`
106479
+ });
106480
+ }
106481
+ const error51 = new APIError({
106482
+ text: `A request to the Cloudflare API (${resource}) failed.`,
106483
+ notes,
106484
+ status: status2,
106485
+ // hoist the parsed `Retry-After` header (if any) so consumers such as
106486
+ // `retryOnAPIFailure()` can back off for the amount of time the API
106487
+ // asked us to wait, e.g. when rate limited (HTTP 429).
106488
+ retryAfterMs,
106489
+ telemetryMessage: false
106490
+ });
106491
+ const code = errors[0]?.code;
106492
+ if (code) {
106493
+ error51.code = code;
106494
+ }
106495
+ const meta3 = errors[0]?.meta;
106496
+ if (meta3) {
106497
+ error51.meta = meta3;
106498
+ }
106499
+ error51.accountTag = extractAccountTag(resource);
106500
+ throw error51;
106501
+ }
106502
+ __name(throwFetchError, "throwFetchError");
106503
+ function throwWAFBlockError(headers, method, resource, status2, statusText, retryAfterMs) {
106504
+ const rayId = extractWAFBlockRayId(headers);
106505
+ throw new APIError({
106506
+ text: "The Cloudflare API responded with a WAF block page instead of the expected JSON response",
106507
+ notes: [
106508
+ {
106509
+ text: "Cloudflare's firewall (WAF) blocked this API request. This is usually a false positive."
106510
+ },
106511
+ ...rayId ? [{ text: `Cloudflare Ray ID: ${rayId}` }] : [],
106512
+ {
106513
+ 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."
106514
+ },
106515
+ {
106516
+ text: `${method} ${resource} -> ${status2} ${statusText}`
106517
+ }
106518
+ ],
106519
+ status: status2,
106520
+ retryAfterMs,
106521
+ telemetryMessage: false
106522
+ });
106523
+ }
106524
+ __name(throwWAFBlockError, "throwWAFBlockError");
106525
+ async function fetchKVGetValueBase(complianceConfig, accountId, namespaceId, key, userAgent, logger, credentials) {
106526
+ const headers = new import_undici.Headers();
106527
+ addAuthorizationHeader(headers, credentials);
106528
+ headers.set("User-Agent", userAgent);
106529
+ maybeAddTraceHeader(headers);
106530
+ const resource = `${getCloudflareApiBaseUrl(complianceConfig)}/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`;
106531
+ logger.debug(`-- START CF API REQUEST: GET ${resource}`);
106532
+ logger.debug("-- END CF API REQUEST");
106533
+ const response = await (0, import_undici.fetch)(resource, {
106534
+ method: "GET",
106535
+ headers
106536
+ });
106537
+ if (response.ok) {
106538
+ return await response.arrayBuffer();
106539
+ } else {
106540
+ throw new Error(
106541
+ `Failed to fetch ${resource} - ${response.status}: ${response.statusText}`
106542
+ );
106543
+ }
106544
+ }
106545
+ __name(fetchKVGetValueBase, "fetchKVGetValueBase");
106546
+ function hasCursor(result_info) {
106547
+ const cursor = result_info?.cursor;
106548
+ return cursor !== void 0 && cursor !== null && cursor !== "";
106549
+ }
106550
+ __name(hasCursor, "hasCursor");
106551
+ function maybeAddTraceHeader(headers) {
106552
+ const traceHeader = getTraceHeader();
106553
+ if (traceHeader) {
106554
+ headers.set("Cf-Trace-Id", traceHeader);
106555
+ }
106556
+ }
106557
+ __name(maybeAddTraceHeader, "maybeAddTraceHeader");
106558
+ function cloneHeaders(headers) {
106559
+ return new import_undici.Headers(headers);
106560
+ }
106561
+ __name(cloneHeaders, "cloneHeaders");
105718
106562
  var import_command_exists = __toESM2(require_command_exists2());
105719
106563
  var UPDATE_SERVICE_URL = "https://update.argotunnel.com";
105720
106564
  var CLOUDFLARED_VERSION_PATTERN = /^\d{4}\.\d+\.\d+$/;
@@ -106229,12 +107073,154 @@ function removeCloudflaredCache(version22) {
106229
107073
  }
106230
107074
  __name(removeCloudflaredCache, "removeCloudflaredCache");
106231
107075
  var TUNNEL_STARTUP_TIMEOUT_MS = 3e4;
107076
+ var TUNNEL_API_TIMEOUT_MS = 6e4;
106232
107077
  var TUNNEL_FORCE_KILL_TIMEOUT_MS = 5e3;
106233
107078
  var DEFAULT_TUNNEL_EXPIRY_MS = 60 * 60 * 1e3;
106234
107079
  var DEFAULT_TUNNEL_EXTENSION_MS = 60 * 60 * 1e3;
106235
107080
  var DEFAULT_TUNNEL_MAX_REMAINING_MS = 3 * 60 * 60 * 1e3;
106236
107081
  var DEFAULT_TUNNEL_REMINDER_INTERVAL_MS = 10 * 60 * 1e3;
106237
107082
  var QUICK_TUNNEL_URL_REGEX = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/;
107083
+ var LOCAL_TUNNEL_HOSTNAMES = /* @__PURE__ */ new Set([
107084
+ "localhost",
107085
+ "127.0.0.1",
107086
+ "::1",
107087
+ "0.0.0.0",
107088
+ "::"
107089
+ ]);
107090
+ async function resolveNamedTunnel(name3, origin, options) {
107091
+ const {
107092
+ accountId,
107093
+ apiToken,
107094
+ complianceRegion,
107095
+ logger,
107096
+ userAgent,
107097
+ abortSignal
107098
+ } = options;
107099
+ const complianceConfig = { compliance_region: complianceRegion };
107100
+ const resource = `/accounts/${accountId}/cfd_tunnel`;
107101
+ const tunnels = await fetchResultBase(
107102
+ complianceConfig,
107103
+ resource,
107104
+ void 0,
107105
+ userAgent,
107106
+ logger,
107107
+ new URLSearchParams({ name: name3, is_deleted: "false" }),
107108
+ createApiAbortSignal(TUNNEL_API_TIMEOUT_MS, abortSignal),
107109
+ apiToken
107110
+ );
107111
+ const tunnel = tunnels.find((item) => item.name === name3);
107112
+ if (!tunnel) {
107113
+ throw new UserError(
107114
+ `No Cloudflare Tunnel named "${name3}" was found in this account. Use "wrangler tunnel list" to see available tunnels.`,
107115
+ { telemetryMessage: "tunnel resolve named missing tunnel" }
107116
+ );
107117
+ }
107118
+ const tunnelId = tunnel.id;
107119
+ if (!tunnelId) {
107120
+ throw new FatalError(
107121
+ `Tunnel "${name3}" was found but has no ID. This is unexpected.`,
107122
+ { telemetryMessage: "tunnel resolve named missing tunnel id" }
107123
+ );
107124
+ }
107125
+ const configuration = await fetchResultBase(
107126
+ complianceConfig,
107127
+ `${resource}/${tunnelId}/configurations`,
107128
+ void 0,
107129
+ userAgent,
107130
+ logger,
107131
+ void 0,
107132
+ createApiAbortSignal(TUNNEL_API_TIMEOUT_MS, abortSignal),
107133
+ apiToken
107134
+ );
107135
+ const ingress = configuration.config?.ingress ?? [];
107136
+ const hostnames = getMatchingIngressHostnames(origin, ingress);
107137
+ if (hostnames.length === 0) {
107138
+ throw new UserError(
107139
+ createMissingIngressMessage(name3, origin, {
107140
+ dashboardUrl: `https://dash.cloudflare.com/${accountId}/tunnels/${tunnelId}`,
107141
+ ingress
107142
+ }),
107143
+ { telemetryMessage: "tunnel resolve named ingress mismatch" }
107144
+ );
107145
+ }
107146
+ const token = await fetchResultBase(
107147
+ complianceConfig,
107148
+ `${resource}/${tunnelId}/token`,
107149
+ void 0,
107150
+ userAgent,
107151
+ logger,
107152
+ void 0,
107153
+ createApiAbortSignal(TUNNEL_API_TIMEOUT_MS, abortSignal),
107154
+ apiToken
107155
+ );
107156
+ return { hostnames, token: String(token) };
107157
+ }
107158
+ __name(resolveNamedTunnel, "resolveNamedTunnel");
107159
+ function getMatchingIngressHostnames(origin, ingressConfig) {
107160
+ const hostnames = /* @__PURE__ */ new Set();
107161
+ const originUrl = normalizeURL(origin);
107162
+ for (const ingress of ingressConfig) {
107163
+ try {
107164
+ const serviceUrl = normalizeURL(ingress.service);
107165
+ if (ingress.hostname && serviceUrl.toString() === originUrl.toString()) {
107166
+ hostnames.add(ingress.hostname);
107167
+ }
107168
+ } catch {
107169
+ }
107170
+ }
107171
+ return [...hostnames];
107172
+ }
107173
+ __name(getMatchingIngressHostnames, "getMatchingIngressHostnames");
107174
+ function normalizeURL(url2) {
107175
+ const normalizedUrl = new URL(url2);
107176
+ if (LOCAL_TUNNEL_HOSTNAMES.has(normalizedUrl.hostname)) {
107177
+ normalizedUrl.hostname = "localhost";
107178
+ }
107179
+ if (!normalizedUrl.port) {
107180
+ switch (normalizedUrl.protocol) {
107181
+ case "http:":
107182
+ normalizedUrl.port = "80";
107183
+ break;
107184
+ case "https:":
107185
+ normalizedUrl.port = "443";
107186
+ break;
107187
+ }
107188
+ }
107189
+ return normalizedUrl;
107190
+ }
107191
+ __name(normalizeURL, "normalizeURL");
107192
+ function createApiAbortSignal(timeoutMs, abortSignal) {
107193
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
107194
+ return abortSignal ? AbortSignal.any([abortSignal, timeoutSignal]) : timeoutSignal;
107195
+ }
107196
+ __name(createApiAbortSignal, "createApiAbortSignal");
107197
+ function createMissingIngressMessage(name3, origin, {
107198
+ dashboardUrl,
107199
+ ingress
107200
+ }) {
107201
+ if (ingress.length === 0) {
107202
+ return [
107203
+ `Tunnel "${name3}" has no routes configured.`,
107204
+ "",
107205
+ `Add a route for ${origin} in the Cloudflare dashboard:`,
107206
+ dashboardUrl,
107207
+ ""
107208
+ ].join("\n");
107209
+ }
107210
+ return [
107211
+ `Tunnel "${name3}" has no route for ${origin}`,
107212
+ "",
107213
+ "Resolved routes:",
107214
+ ...ingress.map(
107215
+ ({ hostname: hostname3, service }) => ` - ${hostname3 ?? "(no hostname)"} -> ${service}`
107216
+ ),
107217
+ "",
107218
+ "Update your local server settings or the tunnel routes in the Cloudflare dashboard:",
107219
+ dashboardUrl,
107220
+ ""
107221
+ ].join("\n");
107222
+ }
107223
+ __name(createMissingIngressMessage, "createMissingIngressMessage");
106238
107224
  function startTunnel(options) {
106239
107225
  let disposed = false;
106240
107226
  let reminderInterval;
@@ -106467,409 +107453,6 @@ The local dev server started at ${origin.href}
106467
107453
  return new Error(errorMessage);
106468
107454
  }
106469
107455
  __name(createTunnelStartupError, "createTunnelStartupError");
106470
- function buildDetailedError(message, ...extra) {
106471
- return new ParseError({
106472
- text: message,
106473
- notes: extra.map((text) => ({ text })),
106474
- telemetryMessage: false
106475
- });
106476
- }
106477
- __name(buildDetailedError, "buildDetailedError");
106478
- function maybeThrowFriendlyError(error51) {
106479
- if (error51.message === "workers.api.error.email_verification_required") {
106480
- throw buildDetailedError(
106481
- "Please verify your account's email address and try again.",
106482
- "Check your email for a verification link, or login to https://dash.cloudflare.com and request a new one."
106483
- );
106484
- }
106485
- }
106486
- __name(maybeThrowFriendlyError, "maybeThrowFriendlyError");
106487
- function logHeaders(headers, logger) {
106488
- const clone2 = cloneHeaders(headers);
106489
- clone2.delete("Authorization");
106490
- logger.debugWithSanitization?.(
106491
- "HEADERS:",
106492
- JSON.stringify(Object.fromEntries(clone2), null, 2)
106493
- );
106494
- }
106495
- __name(logHeaders, "logHeaders");
106496
- async function performApiFetchBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
106497
- (0, import_node_assert2.default)(credentials, "credentials are required for performApiFetch");
106498
- const method = init.method ?? "GET";
106499
- (0, import_node_assert2.default)(
106500
- resource.startsWith("/"),
106501
- `CF API fetch - resource path must start with a "/" but got "${resource}"`
106502
- );
106503
- const headers = cloneHeaders(new import_undici.Headers(init.headers));
106504
- addAuthorizationHeader(headers, credentials);
106505
- headers.set("User-Agent", userAgent);
106506
- maybeAddTraceHeader(headers);
106507
- const queryString = queryParams ? `?${queryParams.toString()}` : "";
106508
- logger.debug(
106509
- `-- START CF API REQUEST: ${method} ${getCloudflareApiBaseUrl(complianceConfig)}${resource}`
106510
- );
106511
- logger.debugWithSanitization?.("QUERY STRING:", queryString);
106512
- logHeaders(headers, logger);
106513
- logger.debugWithSanitization?.("INIT:", JSON.stringify({ ...init }, null, 2));
106514
- if (init.body instanceof import_undici.FormData) {
106515
- logger.debugWithSanitization?.(
106516
- "BODY:",
106517
- await new import_undici.Response(init.body).text(),
106518
- null,
106519
- 2
106520
- );
106521
- }
106522
- logger.debug("-- END CF API REQUEST");
106523
- return await (0, import_undici.fetch)(
106524
- `${getCloudflareApiBaseUrl(complianceConfig)}${resource}${queryString}`,
106525
- {
106526
- method,
106527
- ...init,
106528
- headers,
106529
- signal: abortSignal
106530
- }
106531
- );
106532
- }
106533
- __name(performApiFetchBase, "performApiFetchBase");
106534
- async function fetchInternalBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
106535
- const method = init.method ?? "GET";
106536
- const response = await performApiFetchBase(
106537
- complianceConfig,
106538
- resource,
106539
- init,
106540
- userAgent,
106541
- logger,
106542
- queryParams,
106543
- abortSignal,
106544
- credentials
106545
- );
106546
- const jsonText = await response.text();
106547
- logger.debug(
106548
- "-- START CF API RESPONSE:",
106549
- response.statusText,
106550
- response.status
106551
- );
106552
- logHeaders(response.headers, logger);
106553
- logger.debugWithSanitization?.("RESPONSE:", jsonText);
106554
- logger.debug("-- END CF API RESPONSE");
106555
- const retryAfterMs = parseRetryAfterMs(response.headers);
106556
- if (!jsonText && (response.status === 204 || response.status === 205)) {
106557
- return {
106558
- response: {
106559
- result: {},
106560
- success: true,
106561
- errors: [],
106562
- messages: []
106563
- },
106564
- status: response.status,
106565
- retryAfterMs
106566
- };
106567
- }
106568
- if (isWAFBlockResponse(response.headers)) {
106569
- throwWAFBlockError(
106570
- response.headers,
106571
- method,
106572
- resource,
106573
- response.status,
106574
- response.statusText,
106575
- retryAfterMs
106576
- );
106577
- }
106578
- try {
106579
- const json2 = parseJSON(jsonText);
106580
- return { response: json2, status: response.status, retryAfterMs };
106581
- } catch {
106582
- const rayId = extractWAFBlockRayId(response.headers);
106583
- throw new APIError({
106584
- text: "Received a malformed response from the API",
106585
- notes: [
106586
- {
106587
- text: truncate(jsonText, 100)
106588
- },
106589
- {
106590
- text: `${method} ${resource} -> ${response.status} ${response.statusText}`
106591
- },
106592
- ...rayId ? [{ text: `Cloudflare Ray ID: ${rayId}` }] : []
106593
- ],
106594
- status: response.status,
106595
- retryAfterMs,
106596
- telemetryMessage: false
106597
- });
106598
- }
106599
- }
106600
- __name(fetchInternalBase, "fetchInternalBase");
106601
- async function fetchResultBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, abortSignal, credentials) {
106602
- const {
106603
- response: json2,
106604
- status: status2,
106605
- retryAfterMs
106606
- } = await fetchInternalBase(
106607
- complianceConfig,
106608
- resource,
106609
- init,
106610
- userAgent,
106611
- logger,
106612
- queryParams,
106613
- abortSignal,
106614
- credentials
106615
- );
106616
- if (json2.success) {
106617
- return json2.result;
106618
- } else {
106619
- throwFetchError(resource, json2, status2, retryAfterMs);
106620
- }
106621
- }
106622
- __name(fetchResultBase, "fetchResultBase");
106623
- async function fetchListResultBase(complianceConfig, resource, init = {}, userAgent, logger, queryParams, credentials) {
106624
- const results = [];
106625
- let getMoreResults = true;
106626
- let cursor;
106627
- while (getMoreResults) {
106628
- if (cursor) {
106629
- queryParams = new import_node_url2.URLSearchParams(queryParams);
106630
- queryParams.set("cursor", cursor);
106631
- }
106632
- const {
106633
- response: json2,
106634
- status: status2,
106635
- retryAfterMs
106636
- } = await fetchInternalBase(
106637
- complianceConfig,
106638
- resource,
106639
- init,
106640
- userAgent,
106641
- logger,
106642
- queryParams,
106643
- void 0,
106644
- credentials
106645
- );
106646
- if (json2.success) {
106647
- results.push(...json2.result);
106648
- if (hasCursor(json2.result_info)) {
106649
- cursor = json2.result_info?.cursor;
106650
- } else {
106651
- getMoreResults = false;
106652
- }
106653
- } else {
106654
- throwFetchError(resource, json2, status2, retryAfterMs);
106655
- }
106656
- }
106657
- return results;
106658
- }
106659
- __name(fetchListResultBase, "fetchListResultBase");
106660
- function truncate(text, maxLength) {
106661
- const { length } = text;
106662
- if (length <= maxLength) {
106663
- return text;
106664
- }
106665
- return `${text.substring(0, maxLength)}... (length = ${length})`;
106666
- }
106667
- __name(truncate, "truncate");
106668
- function isWAFBlockResponse(headers) {
106669
- return headers.get("cf-mitigated") === "challenge";
106670
- }
106671
- __name(isWAFBlockResponse, "isWAFBlockResponse");
106672
- function parseRetryAfterValue(retryAfter) {
106673
- if (!retryAfter) {
106674
- return void 0;
106675
- }
106676
- if (/^\d+$/.test(retryAfter.trim())) {
106677
- return Number(retryAfter) * 1e3;
106678
- }
106679
- const retryAfterDate = new Date(retryAfter);
106680
- if (!Number.isNaN(retryAfterDate.getTime())) {
106681
- return Math.max(0, retryAfterDate.getTime() - Date.now());
106682
- }
106683
- return void 0;
106684
- }
106685
- __name(parseRetryAfterValue, "parseRetryAfterValue");
106686
- function parseRetryAfterMs(headers) {
106687
- return parseRetryAfterValue(headers.get("Retry-After"));
106688
- }
106689
- __name(parseRetryAfterMs, "parseRetryAfterMs");
106690
- function extractWAFBlockRayId(headers) {
106691
- return headers.get("cf-ray") ?? void 0;
106692
- }
106693
- __name(extractWAFBlockRayId, "extractWAFBlockRayId");
106694
- function extractAccountTag(resource) {
106695
- const re = new RegExp("/accounts/([a-zA-Z0-9]+)/?");
106696
- const matches = re.exec(resource);
106697
- return matches?.[1];
106698
- }
106699
- __name(extractAccountTag, "extractAccountTag");
106700
- function hasMorePages(result_info) {
106701
- const page = result_info?.page;
106702
- const per_page = result_info?.per_page;
106703
- const total = result_info?.total_count;
106704
- return page !== void 0 && per_page !== void 0 && total !== void 0 && page * per_page < total;
106705
- }
106706
- __name(hasMorePages, "hasMorePages");
106707
- function renderError(err, level = 0) {
106708
- const indent2 = " ".repeat(level);
106709
- const message = err.message ?? "";
106710
- const chainedMessages = "error_chain" in err ? err.error_chain?.map(
106711
- (chainedError) => `
106712
-
106713
- ${indent2}- ${renderError(chainedError, level + 1)}`
106714
- ).join("\n") ?? "" : "";
106715
- return (err.code ? `${message} [code: ${err.code}]` : message) + (err.documentation_url ? `
106716
- ${indent2}To learn more about this error, visit: ${err.documentation_url}` : "") + chainedMessages;
106717
- }
106718
- __name(renderError, "renderError");
106719
- function addAuthorizationHeader(headers, auth, overrideExisting = false) {
106720
- if (!headers.has("Authorization") || overrideExisting) {
106721
- if ("apiToken" in auth) {
106722
- const authorizationHeader = `Bearer ${auth.apiToken}`;
106723
- validateAuthorizationHeaderValue(authorizationHeader);
106724
- headers.set("Authorization", authorizationHeader);
106725
- } else {
106726
- headers.set("X-Auth-Key", auth.authKey);
106727
- headers.set("X-Auth-Email", auth.authEmail);
106728
- }
106729
- }
106730
- }
106731
- __name(addAuthorizationHeader, "addAuthorizationHeader");
106732
- function validateAuthorizationHeaderValue(value) {
106733
- for (const character of value) {
106734
- const codePoint = character.codePointAt(0);
106735
- if (codePoint === void 0 || codePoint > 255) {
106736
- throw new UserError(
106737
- `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.`,
106738
- {
106739
- telemetryMessage: "cfetch auth invalid authorization header"
106740
- }
106741
- );
106742
- }
106743
- }
106744
- }
106745
- __name(validateAuthorizationHeaderValue, "validateAuthorizationHeaderValue");
106746
- function formatAuthorizationHeaderCharacter(character, codePoint) {
106747
- if (codePoint === void 0) {
106748
- return '"\\u{unknown}"';
106749
- }
106750
- const codePointLabel = `U+${codePoint.toString(16).toUpperCase().padStart(4, "0")}`;
106751
- const characterLabel = isPrintableCharacter(character) ? `"${character}"` : `"${escapeCharacter(character)}"`;
106752
- return `${characterLabel} (${codePointLabel})`;
106753
- }
106754
- __name(formatAuthorizationHeaderCharacter, "formatAuthorizationHeaderCharacter");
106755
- function isPrintableCharacter(character) {
106756
- return !/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(character);
106757
- }
106758
- __name(isPrintableCharacter, "isPrintableCharacter");
106759
- function escapeCharacter(character) {
106760
- return Array.from(character).map((c2) => {
106761
- const codePoint = c2.codePointAt(0);
106762
- if (codePoint === void 0) {
106763
- return "";
106764
- }
106765
- return codePoint <= 65535 ? `\\u${codePoint.toString(16).toUpperCase().padStart(4, "0")}` : `\\u{${codePoint.toString(16).toUpperCase()}}`;
106766
- }).join("");
106767
- }
106768
- __name(escapeCharacter, "escapeCharacter");
106769
- function throwFetchError(resource, response, status2, retryAfterMs) {
106770
- const errors = response.errors ?? [];
106771
- for (const error52 of errors) {
106772
- maybeThrowFriendlyError(error52);
106773
- }
106774
- const notes = [
106775
- ...errors.map((err) => ({ text: renderError(err) })),
106776
- ...response.messages?.map((msg) => ({
106777
- text: typeof msg === "string" ? msg : msg.message ?? String(msg)
106778
- })) ?? []
106779
- ];
106780
- if (notes.length === 0) {
106781
- const raw = response;
106782
- const fallbackMessage = typeof raw.error === "string" ? `${raw.error}${raw.code ? ` [code: ${raw.code}]` : ""}` : void 0;
106783
- if (fallbackMessage) {
106784
- notes.push({ text: fallbackMessage });
106785
- }
106786
- }
106787
- if (retryAfterMs !== void 0) {
106788
- notes.push({
106789
- text: `The API responded with a "Retry-After" header indicating you should wait ${Math.ceil(retryAfterMs / 1e3)} second(s) before retrying.`
106790
- });
106791
- }
106792
- const error51 = new APIError({
106793
- text: `A request to the Cloudflare API (${resource}) failed.`,
106794
- notes,
106795
- status: status2,
106796
- // hoist the parsed `Retry-After` header (if any) so consumers such as
106797
- // `retryOnAPIFailure()` can back off for the amount of time the API
106798
- // asked us to wait, e.g. when rate limited (HTTP 429).
106799
- retryAfterMs,
106800
- telemetryMessage: false
106801
- });
106802
- const code = errors[0]?.code;
106803
- if (code) {
106804
- error51.code = code;
106805
- }
106806
- const meta3 = errors[0]?.meta;
106807
- if (meta3) {
106808
- error51.meta = meta3;
106809
- }
106810
- error51.accountTag = extractAccountTag(resource);
106811
- throw error51;
106812
- }
106813
- __name(throwFetchError, "throwFetchError");
106814
- function throwWAFBlockError(headers, method, resource, status2, statusText, retryAfterMs) {
106815
- const rayId = extractWAFBlockRayId(headers);
106816
- throw new APIError({
106817
- text: "The Cloudflare API responded with a WAF block page instead of the expected JSON response",
106818
- notes: [
106819
- {
106820
- text: "Cloudflare's firewall (WAF) blocked this API request. This is usually a false positive."
106821
- },
106822
- ...rayId ? [{ text: `Cloudflare Ray ID: ${rayId}` }] : [],
106823
- {
106824
- 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."
106825
- },
106826
- {
106827
- text: `${method} ${resource} -> ${status2} ${statusText}`
106828
- }
106829
- ],
106830
- status: status2,
106831
- retryAfterMs,
106832
- telemetryMessage: false
106833
- });
106834
- }
106835
- __name(throwWAFBlockError, "throwWAFBlockError");
106836
- async function fetchKVGetValueBase(complianceConfig, accountId, namespaceId, key, userAgent, logger, credentials) {
106837
- const headers = new import_undici.Headers();
106838
- addAuthorizationHeader(headers, credentials);
106839
- headers.set("User-Agent", userAgent);
106840
- maybeAddTraceHeader(headers);
106841
- const resource = `${getCloudflareApiBaseUrl(complianceConfig)}/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`;
106842
- logger.debug(`-- START CF API REQUEST: GET ${resource}`);
106843
- logger.debug("-- END CF API REQUEST");
106844
- const response = await (0, import_undici.fetch)(resource, {
106845
- method: "GET",
106846
- headers
106847
- });
106848
- if (response.ok) {
106849
- return await response.arrayBuffer();
106850
- } else {
106851
- throw new Error(
106852
- `Failed to fetch ${resource} - ${response.status}: ${response.statusText}`
106853
- );
106854
- }
106855
- }
106856
- __name(fetchKVGetValueBase, "fetchKVGetValueBase");
106857
- function hasCursor(result_info) {
106858
- const cursor = result_info?.cursor;
106859
- return cursor !== void 0 && cursor !== null && cursor !== "";
106860
- }
106861
- __name(hasCursor, "hasCursor");
106862
- function maybeAddTraceHeader(headers) {
106863
- const traceHeader = getTraceHeader();
106864
- if (traceHeader) {
106865
- headers.set("Cf-Trace-Id", traceHeader);
106866
- }
106867
- }
106868
- __name(maybeAddTraceHeader, "maybeAddTraceHeader");
106869
- function cloneHeaders(headers) {
106870
- return new import_undici.Headers(headers);
106871
- }
106872
- __name(cloneHeaders, "cloneHeaders");
106873
107456
  var import_update_check = __toESM2(require_update_check());
106874
107457
  var UPDATE_CHECK_TIMEOUT_MS = 3e3;
106875
107458
  var TIMED_OUT = /* @__PURE__ */ Symbol("timed_out");
@@ -112007,7 +112590,7 @@ var Yargs = YargsFactory(esm_default2);
112007
112590
  var yargs_default = Yargs;
112008
112591
 
112009
112592
  // package.json
112010
- var version2 = "2.72.6";
112593
+ var version2 = "2.72.8";
112011
112594
 
112012
112595
  // src/metrics.ts
112013
112596
  var import_node_async_hooks = require("node:async_hooks");
@@ -114594,20 +115177,20 @@ __name2(getPropertyName, "getPropertyName");
114594
115177
  var package_default = {
114595
115178
  name: "frameworks_clis_info",
114596
115179
  dependencies: {
114597
- "@angular/create": "22.1.7",
115180
+ "@angular/create": "22.1.8",
114598
115181
  "@tanstack/cli": "0.71.0",
114599
- "create-analog": "2.7.1",
115182
+ "create-analog": "2.7.2",
114600
115183
  "create-astro": "5.2.4",
114601
115184
  "create-docusaurus": "3.10.2",
114602
115185
  "create-hono": "0.19.5",
114603
- "create-next-app": "16.3.4",
115186
+ "create-next-app": "16.3.5",
114604
115187
  "create-qwik": "1.20.0",
114605
115188
  "create-react-router": "8.3.1",
114606
115189
  "create-rwsdk": "3.1.3",
114607
115190
  "create-solid": "0.12.0",
114608
115191
  "create-vike": "0.0.681",
114609
115192
  "create-vinext-app": "1.0.0-beta.2",
114610
- "create-vite": "9.2.0",
115193
+ "create-vite": "9.2.1",
114611
115194
  "create-vue": "3.23.0",
114612
115195
  "create-waku": "0.12.5-1.0.0-alpha.10-0",
114613
115196
  gatsby: "5.16.1",
@@ -117173,6 +117756,27 @@ For all limits and quotas, retrieve from the product's \`/platform/limits/\` pag
117173
117756
 
117174
117757
  Run \`wrangler types\` after changing bindings in wrangler.jsonc.
117175
117758
 
117759
+ ## Local Explorer (Debugging & Inspection)
117760
+
117761
+ When running \`npx wrangler dev\`, a Local Explorer API is available for inspecting and debugging local Workers, bindings, and storage state. The API base URL is printed in the terminal when the dev server starts.
117762
+
117763
+ Key endpoints (relative to the dev server URL):
117764
+
117765
+ | Endpoint | Description |
117766
+ |----------|-------------|
117767
+ | \`GET /cdn-cgi/local/explorer/api/local/workers\` | List local Workers and their bindings |
117768
+ | \`GET /cdn-cgi/local/explorer/api/storage/kv/namespaces\` | List KV namespaces |
117769
+ | \`GET /cdn-cgi/local/explorer/api/d1/database\` | List D1 databases |
117770
+ | \`GET /cdn-cgi/local/explorer/api/r2/buckets\` | List R2 buckets |
117771
+ | \`GET /cdn-cgi/local/explorer/api/workers/durable_objects/namespaces\` | List Durable Object namespaces |
117772
+ | \`GET /cdn-cgi/local/explorer/api/workflows\` | List Workflows |
117773
+ | \`POST /cdn-cgi/local/explorer/api/local/observability/query\` | Run a read-only SQL query (SELECT/WITH only) over captured request traces and console logs. Tables: \`spans\`, \`logs\` (read attributes via \`json(attributes)\`). Example: \`curl -X POST <base>/cdn-cgi/local/explorer/api/local/observability/query -H 'Content-Type: application/json' -d '{"sql":"SELECT service, name, outcome, duration_ms FROM spans WHERE parent_id IS NULL LIMIT 20"}'\` |
117774
+ | \`POST /cdn-cgi/local/explorer/api/local/observability/clear\` | Clear all captured traces and logs |
117775
+
117776
+ If the routes above don't cover what you need, fetch the full OpenAPI schema (large - use only as a last resort): \`GET /cdn-cgi/local/explorer/api\`
117777
+
117778
+ Use the Local Explorer to debug issues by inspecting storage state (KV keys, D1 rows, R2 objects, DO storage), viewing Worker bindings, and querying request traces and logs captured during the dev session.
117779
+
117176
117780
  ## Node.js Compatibility
117177
117781
 
117178
117782
  https://developers.cloudflare.com/workers/runtime-apis/nodejs/
@@ -117199,7 +117803,7 @@ If the application uses Durable Objects or Workflows, refer to the relevant best
117199
117803
  var import_node_assert7 = __toESM(require("node:assert"));
117200
117804
 
117201
117805
  // ../wrangler/package.json
117202
- var version3 = "4.129.1";
117806
+ var version3 = "4.132.0";
117203
117807
 
117204
117808
  // src/git.ts
117205
117809
  var offerGit = async (ctx) => {