@cloudflare/vite-plugin 1.54.11 → 1.55.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
@@ -2614,8 +2614,8 @@ function formatConfigSnippet(snippet, configPath, formatted = true) {
2614
2614
  __name$6(formatConfigSnippet, "formatConfigSnippet");
2615
2615
 
2616
2616
  //#endregion
2617
- //#region ../workers-utils/dist/chunk-YZWVNJ5I.mjs
2618
- var DEFAULT_COMPAT_DATE = "2026-09-16";
2617
+ //#region ../workers-utils/dist/chunk-2OPNWQJ5.mjs
2618
+ var DEFAULT_COMPAT_DATE = "2026-09-17";
2619
2619
  function assertNever(_value) {}
2620
2620
  __name$6(assertNever, "assertNever");
2621
2621
  function mapWorkerMetadataBindings(bindings) {
@@ -44103,19 +44103,34 @@ var validateObservability = /* @__PURE__ */ __name$6((diagnostics, field, value)
44103
44103
  key: "traces.enabled",
44104
44104
  value: val.traces?.enabled,
44105
44105
  type: "boolean"
44106
+ },
44107
+ {
44108
+ key: "issues.enabled",
44109
+ value: val.issues?.enabled,
44110
+ type: "boolean"
44106
44111
  }
44107
44112
  ]) && isValid;
44108
44113
  isValid = validateOptionalProperty(diagnostics, field, "head_sampling_rate", val.head_sampling_rate, "number") && isValid;
44109
44114
  isValid = validateOptionalProperty(diagnostics, field, "redact_query_string", val.redact_query_string, "boolean") && isValid;
44115
+ const issuesIsObject = val.issues === void 0 || val.issues !== null && typeof val.issues === "object" && !Array.isArray(val.issues);
44116
+ if (!issuesIsObject) {
44117
+ diagnostics.errors.push(`"${field}.issues" should be an object but got ${JSON.stringify(val.issues)}.`);
44118
+ isValid = false;
44119
+ }
44110
44120
  isValid = validateOptionalProperty(diagnostics, field, "logs", val.logs, "object") && isValid;
44111
44121
  isValid = validateOptionalProperty(diagnostics, field, "traces", val.traces, "object") && isValid;
44112
44122
  isValid = validateAdditionalProperties(diagnostics, field, Object.keys(val), [
44113
44123
  "enabled",
44114
44124
  "head_sampling_rate",
44115
44125
  "redact_query_string",
44126
+ "issues",
44116
44127
  "logs",
44117
44128
  "traces"
44118
44129
  ]) && isValid;
44130
+ if (val.issues !== void 0 && issuesIsObject) {
44131
+ isValid = validateOptionalProperty(diagnostics, `${field}.issues`, "enabled", val.issues.enabled, "boolean") && isValid;
44132
+ isValid = validateAdditionalProperties(diagnostics, `${field}.issues`, Object.keys(val.issues), ["enabled"]) && isValid;
44133
+ }
44119
44134
  if (typeof val.logs === "object") {
44120
44135
  isValid = validateOptionalProperty(diagnostics, field, "logs.enabled", val.logs.enabled, "boolean") && isValid;
44121
44136
  isValid = validateOptionalProperty(diagnostics, field, "logs.head_sampling_rate", val.logs.head_sampling_rate, "number") && isValid;
@@ -55728,6 +55743,7 @@ const ObservabilitySchema = strictObject({
55728
55743
  enabled: boolean().optional(),
55729
55744
  headSamplingRate: number().optional(),
55730
55745
  redactQueryString: boolean().optional(),
55746
+ issues: strictObject({ enabled: boolean().optional() }).optional(),
55731
55747
  logs: strictObject({
55732
55748
  enabled: boolean().optional(),
55733
55749
  headSamplingRate: number().optional(),
@@ -56175,6 +56191,7 @@ function convertObservability(observability) {
56175
56191
  if (observability.enabled !== void 0) out.enabled = observability.enabled;
56176
56192
  if (observability.headSamplingRate !== void 0) out.head_sampling_rate = observability.headSamplingRate;
56177
56193
  if (observability.redactQueryString !== void 0) out.redact_query_string = observability.redactQueryString;
56194
+ if (observability.issues !== void 0) out.issues = { enabled: observability.issues.enabled };
56178
56195
  if (observability.logs !== void 0) {
56179
56196
  const logs = {};
56180
56197
  const { logs: src$1 } = observability;
@@ -72007,11 +72024,11 @@ var getQueryString = /* @__PURE__ */ __name$2((params) => {
72007
72024
  }, "getQueryString");
72008
72025
  var getUrl = /* @__PURE__ */ __name$2((config$2, options) => {
72009
72026
  const encoder$1 = config$2.ENCODE_PATH || encodeURI;
72010
- const path$2 = options.url.replace("{api-version}", config$2.VERSION).replace(/{(.*?)}/g, (substring, group) => {
72027
+ const path2 = options.url.replace("{api-version}", config$2.VERSION).replace(/{(.*?)}/g, (substring, group) => {
72011
72028
  if (options.path?.hasOwnProperty(group)) return encoder$1(String(options.path[group]));
72012
72029
  return substring;
72013
72030
  });
72014
- const url$2 = `${config$2.BASE}${path$2}`;
72031
+ const url$2 = `${config$2.BASE}${path2}`;
72015
72032
  if (options.query) return `${url$2}${getQueryString(options.query)}`;
72016
72033
  return url$2;
72017
72034
  }, "getUrl");
@@ -73995,7 +74012,7 @@ async function checkExposedPorts(dockerPath, options) {
73995
74012
  if (await dockerImageInspect(dockerPath, {
73996
74013
  imageTag: options.image_tag,
73997
74014
  formatString: "{{ len .Config.ExposedPorts }}"
73998
- }) === "0") throw new UserError(`The container "${options.class_name}" does not expose any ports. In your Dockerfile, please expose any ports you intend to connect to.
74015
+ }) === "0") throw new UserError(`The container "${options.image_name === void 0 ? options.class_name : `${options.class_name}.${options.image_name}`}" does not expose any ports. In your Dockerfile, please expose any ports you intend to connect to.
73999
74016
  For additional information please see: https://developers.cloudflare.com/containers/local-dev/#exposing-ports.
74000
74017
  `, { telemetryMessage: false });
74001
74018
  }
@@ -74025,31 +74042,6 @@ function resolveDockerHost(dockerPath) {
74025
74042
  return process.platform === "win32" ? "//./pipe/docker_engine" : "unix:///var/run/docker.sock";
74026
74043
  }
74027
74044
  __name$2(resolveDockerHost, "resolveDockerHost");
74028
- async function getImageRepoTags(dockerPath, imageTag) {
74029
- try {
74030
- return (await dockerImageInspect(dockerPath, {
74031
- imageTag,
74032
- formatString: "{{ range .RepoTags }}{{ . }}\n{{ end }}"
74033
- })).split("\n").filter((tag) => tag.trim() !== "");
74034
- } catch {
74035
- return [];
74036
- }
74037
- }
74038
- __name$2(getImageRepoTags, "getImageRepoTags");
74039
- async function cleanupDuplicateImageTags(dockerPath, imageTag) {
74040
- try {
74041
- const repoTags = await getImageRepoTags(dockerPath, imageTag);
74042
- const currentBuildId = getImageTag(imageTag);
74043
- const tagsToRemove = repoTags.filter((tag) => tag.startsWith("cloudflare-dev") && getImageTag(tag) !== currentBuildId);
74044
- if (tagsToRemove.length > 0) runDockerCmdWithOutput(dockerPath, ["rmi", ...tagsToRemove]);
74045
- } catch {}
74046
- }
74047
- __name$2(cleanupDuplicateImageTags, "cleanupDuplicateImageTags");
74048
- function getImageTag(imageTag) {
74049
- const tagSeparatorIndex = imageTag.lastIndexOf(":");
74050
- return tagSeparatorIndex === -1 ? void 0 : imageTag.slice(tagSeparatorIndex + 1);
74051
- }
74052
- __name$2(getImageTag, "getImageTag");
74053
74045
  var DEFAULT_CONTAINER_EGRESS_INTERCEPTOR_IMAGE = "cloudflare/proxy-everything:3cb1195@sha256:0ef6716c52430096900b150d84a3302057d6cd2319dae7987128c85d0733e3c8";
74054
74046
  function getEgressInterceptorPlatform() {
74055
74047
  return process.env.MINIFLARE_CONTAINER_EGRESS_IMAGE_PLATFORM;
@@ -74088,6 +74080,7 @@ async function pullImage(dockerPath, options, logger2, complianceConfig) {
74088
74080
  options.image_uri,
74089
74081
  options.image_tag
74090
74082
  ]);
74083
+ return { aborted: aborted$2 };
74091
74084
  });
74092
74085
  return {
74093
74086
  abort: /* @__PURE__ */ __name$2(() => {
@@ -74138,17 +74131,25 @@ async function prepareContainerImagesForDev(args) {
74138
74131
  pull.abort();
74139
74132
  }, "abort")
74140
74133
  });
74141
- await pull.ready;
74134
+ const pullResult = await pull.ready;
74135
+ aborted$2 ||= pullResult.aborted;
74142
74136
  onContainerImagePreparationEnd({ containerOptions: options });
74143
74137
  }
74144
- if (!aborted$2) {
74145
- await cleanupDuplicateImageTags(dockerPath, options.image_tag);
74146
- await checkExposedPorts(dockerPath, options);
74147
- }
74138
+ if (aborted$2) break;
74139
+ await checkExposedPorts(dockerPath, options);
74148
74140
  }
74149
74141
  if (!aborted$2) await pullEgressInterceptorImage(dockerPath);
74142
+ return { aborted: aborted$2 };
74150
74143
  }
74151
74144
  __name$2(prepareContainerImagesForDev, "prepareContainerImagesForDev");
74145
+ function isCloudflareRegistryImage(image, complianceConfig) {
74146
+ let url$2;
74147
+ try {
74148
+ url$2 = new URL(`http://${image}`);
74149
+ } catch {}
74150
+ return url$2 === void 0 || !url$2.host.match(/[:.]/) && url$2.hostname !== "localhost" || url$2.hostname === getCloudflareContainerRegistry(complianceConfig);
74151
+ }
74152
+ __name$2(isCloudflareRegistryImage, "isCloudflareRegistryImage");
74152
74153
  function resolveImageName(accountId, image, complianceConfig) {
74153
74154
  let url$2;
74154
74155
  try {
@@ -74892,10 +74893,10 @@ var Diff = class {
74892
74893
  print(options = { contextLines: 3 }) {
74893
74894
  log$1(this.toString(options));
74894
74895
  }
74895
- #addToPath(path$2, added, removed, oldPosInc) {
74896
- const last = path$2.lastComponent;
74896
+ #addToPath(path2, added, removed, oldPosInc) {
74897
+ const last = path2.lastComponent;
74897
74898
  if (last && last.added === added && last.removed === removed) return {
74898
- oldPos: path$2.oldPos + oldPosInc,
74899
+ oldPos: path2.oldPos + oldPosInc,
74899
74900
  lastComponent: {
74900
74901
  count: last.count + 1,
74901
74902
  added,
@@ -74904,7 +74905,7 @@ var Diff = class {
74904
74905
  }
74905
74906
  };
74906
74907
  return {
74907
- oldPos: path$2.oldPos + oldPosInc,
74908
+ oldPos: path2.oldPos + oldPosInc,
74908
74909
  lastComponent: {
74909
74910
  count: 1,
74910
74911
  added,
@@ -75424,6 +75425,89 @@ var configRolloutStepsToAPI = /* @__PURE__ */ __name$2((rolloutSteps) => {
75424
75425
  return { steps: output };
75425
75426
  }
75426
75427
  }, "configRolloutStepsToAPI");
75428
+ var MAX_NAMED_IMAGE_SLUG_LENGTH = 255 - MF_DEV_CONTAINER_PREFIX.length - 1;
75429
+ var IMAGE_ID_HASH_LENGTH = 12;
75430
+ function getNamedContainerImageTag(className, imageName, containerBuildId) {
75431
+ const identity = `${className}\0${imageName}`;
75432
+ const classSlug = getDockerRepositorySlug(className);
75433
+ const imageSlug = getDockerRepositorySlug(imageName);
75434
+ const identityHash = createHash("sha256").update(identity).digest("hex").slice(0, IMAGE_ID_HASH_LENGTH);
75435
+ return getDevContainerImageName(`${`${classSlug || "container"}-${imageSlug || "image"}`.slice(0, MAX_NAMED_IMAGE_SLUG_LENGTH - identityHash.length - 1).replace(/-+$/g, "")}-${identityHash}`, containerBuildId);
75436
+ }
75437
+ __name$2(getNamedContainerImageTag, "getNamedContainerImageTag");
75438
+ function getDockerRepositorySlug(value) {
75439
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
75440
+ }
75441
+ __name$2(getDockerRepositorySlug, "getDockerRepositorySlug");
75442
+ function requireContainerBuildId(containerBuildId) {
75443
+ if (containerBuildId === void 0) throw new Error("Build ID should be set when a Container image requires preparation");
75444
+ return containerBuildId;
75445
+ }
75446
+ __name$2(requireContainerBuildId, "requireContainerBuildId");
75447
+ function createContainerDevPlan(options) {
75448
+ const { containers, exports: exports$1, containerBuildId, configPath } = options;
75449
+ if (!containers?.length) return;
75450
+ const containerOptions = [];
75451
+ const containerRuntimeOptions = /* @__PURE__ */ new Map();
75452
+ const durableObjectContainerAppsByName = new Map(getResolvedDurableObjectContainerApps(containers, exports$1).map((container) => [container.name, container]));
75453
+ for (const container of containers) {
75454
+ if (isDurableObjectContainerApp(container)) {
75455
+ const resolvedContainer = durableObjectContainerAppsByName.get(container.name);
75456
+ if (resolvedContainer === void 0) throw new Error(`Expected Durable Object-managed Container "${container.name}" to be resolved`);
75457
+ const className2 = resolvedContainer.class_name;
75458
+ const namedOptions = [];
75459
+ const baseDir$1 = configPath ? path__default.dirname(configPath) : process.cwd();
75460
+ for (const [imageName, image] of Object.entries(container.images ?? {})) {
75461
+ const imageTag2 = getNamedContainerImageTag(className2, imageName, requireContainerBuildId(containerBuildId));
75462
+ if (image.dockerfile !== void 0) {
75463
+ const dockerfile = path__default.resolve(baseDir$1, image.dockerfile);
75464
+ namedOptions.push({
75465
+ dockerfile,
75466
+ image_build_context: image.build_context === void 0 ? path__default.dirname(dockerfile) : path__default.resolve(baseDir$1, image.build_context),
75467
+ image_vars: image.build_vars,
75468
+ class_name: className2,
75469
+ image_name: imageName,
75470
+ image_tag: imageTag2
75471
+ });
75472
+ } else namedOptions.push({
75473
+ image_uri: image.image,
75474
+ class_name: className2,
75475
+ image_name: imageName,
75476
+ image_tag: imageTag2
75477
+ });
75478
+ }
75479
+ containerOptions.push(...namedOptions);
75480
+ const images = namedOptions.map(({ image_name, image_tag }) => ({
75481
+ name: image_name,
75482
+ image: image_tag
75483
+ }));
75484
+ containerRuntimeOptions.set(className2, images.length === 0 ? {} : { images });
75485
+ continue;
75486
+ }
75487
+ if (container.image === void 0) continue;
75488
+ const className = resolveContainerClassName(container, exports$1);
75489
+ if (className === void 0) continue;
75490
+ const imageTag = getDevContainerImageName(className, requireContainerBuildId(containerBuildId));
75491
+ containerRuntimeOptions.set(className, { imageName: imageTag });
75492
+ if (isDockerfile(container.image, configPath)) containerOptions.push({
75493
+ dockerfile: container.image,
75494
+ image_build_context: container.image_build_context ?? path__default.dirname(container.image),
75495
+ image_vars: container.image_vars,
75496
+ class_name: className,
75497
+ image_tag: imageTag
75498
+ });
75499
+ else containerOptions.push({
75500
+ image_uri: container.image,
75501
+ class_name: className,
75502
+ image_tag: imageTag
75503
+ });
75504
+ }
75505
+ return containerOptions.length === 0 && containerRuntimeOptions.size === 0 ? void 0 : {
75506
+ containerOptions,
75507
+ containerRuntimeOptions
75508
+ };
75509
+ }
75510
+ __name$2(createContainerDevPlan, "createContainerDevPlan");
75427
75511
 
75428
75512
  //#endregion
75429
75513
  //#region ../workers-shared/asset-worker/src/utils/rules-engine.ts
@@ -75458,6 +75542,54 @@ function configureContainerPull(accountId, apiToken, complianceConfig) {
75458
75542
  configureOpenAPIForContainerPull(accountId, apiToken, getCloudflareApiBaseUrl(complianceConfig ?? COMPLIANCE_REGION_CONFIG_UNKNOWN));
75459
75543
  }
75460
75544
  /**
75545
+ * Qualifies managed-registry image references with the selected Cloudflare
75546
+ * account before Docker pulls them.
75547
+ *
75548
+ * @param containerOptions - Planned Container images.
75549
+ * @param accountId - Cloudflare account ID that owns managed-registry images.
75550
+ * @param complianceConfig - Compliance configuration used to select the managed registry.
75551
+ * @returns Container options with managed-registry image references qualified.
75552
+ */
75553
+ function normalizeContainerImageUris(containerOptions, accountId, complianceConfig) {
75554
+ return containerOptions.map((option) => "image_uri" in option && isCloudflareRegistryImage(option.image_uri, complianceConfig) ? {
75555
+ ...option,
75556
+ image_uri: resolveImageName(accountId, option.image_uri, complianceConfig)
75557
+ } : option);
75558
+ }
75559
+ /**
75560
+ * Prepares each Worker's Container images with that Worker's registry account
75561
+ * and compliance settings.
75562
+ *
75563
+ * @param args - Planned images, Docker executable, and Vite logger.
75564
+ * @returns No value.
75565
+ */
75566
+ async function prepareContainerImagesForVite(args) {
75567
+ const optionsByWorkerConfig = /* @__PURE__ */ new Map();
75568
+ for (const { containerOptions, workerConfig } of args.containerTagToOptionsMap.values()) {
75569
+ const options = optionsByWorkerConfig.get(workerConfig) ?? [];
75570
+ options.push(containerOptions);
75571
+ optionsByWorkerConfig.set(workerConfig, options);
75572
+ }
75573
+ for (const [workerConfig, plannedOptions] of optionsByWorkerConfig) {
75574
+ let containerOptions = plannedOptions;
75575
+ if (containerOptions.some((options) => "image_uri" in options && isCloudflareRegistryImage(options.image_uri, workerConfig))) {
75576
+ const apiToken = process.env.CLOUDFLARE_API_TOKEN;
75577
+ const accountId = workerConfig.account_id ?? process.env.CLOUDFLARE_ACCOUNT_ID;
75578
+ if (!apiToken || !accountId) throw new UserError("To use images from the Cloudflare-managed registry with the Vite plugin, set the CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID environment variables.\nThe API token requires Containers:Edit and Workers Scripts:Edit permissions.\nAlternatively, use a Dockerfile that references the image via FROM.", { telemetryMessage: false });
75579
+ configureContainerPull(accountId, apiToken, workerConfig);
75580
+ containerOptions = normalizeContainerImageUris(containerOptions, accountId, workerConfig);
75581
+ }
75582
+ await prepareContainerImagesForDev({
75583
+ dockerPath: args.dockerPath,
75584
+ containerOptions,
75585
+ onContainerImagePreparationStart: () => {},
75586
+ onContainerImagePreparationEnd: () => {},
75587
+ logger: args.logger,
75588
+ complianceConfig: workerConfig
75589
+ });
75590
+ }
75591
+ }
75592
+ /**
75461
75593
  * Returns the path to the Docker executable as defined by the
75462
75594
  * `WRANGLER_DOCKER_BIN` environment variable, or the default value
75463
75595
  * `"docker"`
@@ -75465,36 +75597,6 @@ function configureContainerPull(accountId, apiToken, complianceConfig) {
75465
75597
  function getDockerPath() {
75466
75598
  return process.env["WRANGLER_DOCKER_BIN"] || "docker";
75467
75599
  }
75468
- /**
75469
- * @returns Container options suitable for building or pulling images,
75470
- * with image tag set to well-known dev format, or undefined if
75471
- * containers are not enabled or not configured. Containers that are
75472
- * configured but resolve to no Durable Object class are dropped, so the
75473
- * result may also be an empty array. Both mean there is nothing to build
75474
- * or pull, and callers treat them alike.
75475
- */
75476
- function getContainerOptions(options) {
75477
- const { containersConfig, exports: exports$1, containerBuildId, configPath } = options;
75478
- if (!containersConfig?.length) return;
75479
- return containersConfig.map((container) => {
75480
- if (isDurableObjectContainerApp(container) || container.image === void 0) return;
75481
- const className = resolveContainerClassName(container, exports$1);
75482
- if (className === void 0) return;
75483
- const image_tag = getDevContainerImageName(className, containerBuildId);
75484
- if (isDockerfile(container.image, configPath)) return {
75485
- dockerfile: container.image,
75486
- image_build_context: container.image_build_context ?? path__default.dirname(container.image),
75487
- image_vars: container.image_vars,
75488
- class_name: className,
75489
- image_tag
75490
- };
75491
- else return {
75492
- image_uri: container.image,
75493
- class_name: className,
75494
- image_tag
75495
- };
75496
- }).filter((container) => container !== void 0);
75497
- }
75498
75600
 
75499
75601
  //#endregion
75500
75602
  //#region ../workers-auth/dist/chunk-O6YSETKJ.mjs
@@ -81056,7 +81158,7 @@ __name(createWorkerUploadForm, "createWorkerUploadForm");
81056
81158
  //#endregion
81057
81159
  //#region ../remote-bindings/dist/index.mjs
81058
81160
  var import_undici = require_undici();
81059
- var version$2 = "0.0.26";
81161
+ var version$2 = "0.0.27";
81060
81162
  var NoDefaultValueProvided = class extends UserError {
81061
81163
  constructor() {
81062
81164
  super("This command cannot be run in a non-interactive context", { telemetryMessage: "remote bindings prompt default missing" });
@@ -84835,14 +84937,13 @@ async function getDevMiniflareOptions(ctx, viteDevServer) {
84835
84937
  if (worker.config.containers?.length && worker.config.dev.enable_containers) {
84836
84938
  containerEngine = resolveDockerHost(getDockerPath());
84837
84939
  containerBuildId = generateContainerBuildId();
84838
- const options = getContainerOptions({
84839
- containersConfig: worker.config.containers,
84840
- exports: worker.config.exports,
84841
- containerBuildId,
84842
- configPath: worker.config.configPath
84843
- });
84844
- for (const option of options ?? []) containerTagToOptionsMap.set(option.image_tag, option);
84845
84940
  }
84941
+ const containerPlan = worker.config.dev.enable_containers ? createContainerDevPlan({
84942
+ containers: worker.config.containers,
84943
+ exports: worker.config.exports,
84944
+ containerBuildId,
84945
+ configPath: worker.config.configPath
84946
+ }) : void 0;
84846
84947
  const miniflareWorkerOptions = wrangler.unstable_getMiniflareWorkerOptions({
84847
84948
  ...worker.config,
84848
84949
  assets: void 0
@@ -84850,6 +84951,10 @@ async function getDevMiniflareOptions(ctx, viteDevServer) {
84850
84951
  remoteProxyConnectionString: remoteProxySessionData?.session?.remoteProxyConnectionString,
84851
84952
  containerBuildId
84852
84953
  });
84954
+ for (const option of containerPlan?.containerOptions ?? []) containerTagToOptionsMap.set(option.image_tag, {
84955
+ containerOptions: option,
84956
+ workerConfig: worker.config
84957
+ });
84853
84958
  const { externalWorkers: externalWorkers$1 } = miniflareWorkerOptions;
84854
84959
  const workerOptions = miniflareWorkerOptions.workerOptions;
84855
84960
  if (workerOptions.browserRendering && getBrowserRenderingHeadfulFromEnv()) workerOptions.browserRendering.headful = true;
@@ -85054,18 +85159,21 @@ async function getPreviewMiniflareOptions(ctx, vitePreviewServer) {
85054
85159
  if (workerConfig.containers?.length && workerConfig.dev.enable_containers) {
85055
85160
  containerEngine = resolveDockerHost(getDockerPath());
85056
85161
  containerBuildId = generateContainerBuildId();
85057
- const options = getContainerOptions({
85058
- containersConfig: workerConfig.containers,
85059
- exports: workerConfig.exports,
85060
- containerBuildId,
85061
- configPath: workerConfig.configPath
85062
- });
85063
- for (const option of options ?? []) containerTagToOptionsMap.set(option.image_tag, option);
85064
85162
  }
85163
+ const containerPlan = workerConfig.dev.enable_containers ? createContainerDevPlan({
85164
+ containers: workerConfig.containers,
85165
+ exports: workerConfig.exports,
85166
+ containerBuildId,
85167
+ configPath: workerConfig.configPath
85168
+ }) : void 0;
85065
85169
  const miniflareWorkerOptions = wrangler.unstable_getMiniflareWorkerOptions(workerConfig, void 0, {
85066
85170
  remoteProxyConnectionString: remoteProxySessionData?.session?.remoteProxyConnectionString,
85067
85171
  containerBuildId
85068
85172
  });
85173
+ for (const option of containerPlan?.containerOptions ?? []) containerTagToOptionsMap.set(option.image_tag, {
85174
+ containerOptions: option,
85175
+ workerConfig
85176
+ });
85069
85177
  const { externalWorkers } = miniflareWorkerOptions;
85070
85178
  const { modulesRules,...sourcelessWorkerOptions } = miniflareWorkerOptions.workerOptions;
85071
85179
  const workerOptions = sourcelessWorkerOptions;
@@ -85338,19 +85446,10 @@ const devPlugin = createPlugin("dev", (ctx) => {
85338
85446
  }
85339
85447
  if (containerTagToOptionsMap.size) {
85340
85448
  viteDevServer.config.logger.info(import_picocolors$2.default.dim(import_picocolors$2.default.yellow("∷ Building container images for local development...\n")));
85341
- if ([...containerTagToOptionsMap.values()].some((opts) => "image_uri" in opts && new URL(`http://${opts.image_uri}`).hostname === getCloudflareContainerRegistry(ctx.entryWorkerConfig))) {
85342
- const apiToken = process.env.CLOUDFLARE_API_TOKEN;
85343
- const accountId = ctx.entryWorkerConfig?.account_id ?? process.env.CLOUDFLARE_ACCOUNT_ID;
85344
- if (!apiToken || !accountId) throw new UserError("To use images from the Cloudflare-managed registry with the Vite plugin, set the CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID environment variables.\nThe API token requires Containers:Edit and Workers Scripts:Edit permissions.\nAlternatively, use a Dockerfile that references the image via FROM.", { telemetryMessage: false });
85345
- configureContainerPull(accountId, apiToken, ctx.entryWorkerConfig);
85346
- }
85347
- await prepareContainerImagesForDev({
85449
+ await prepareContainerImagesForVite({
85348
85450
  dockerPath: getDockerPath(),
85349
- containerOptions: [...containerTagToOptionsMap.values()],
85350
- onContainerImagePreparationStart: () => {},
85351
- onContainerImagePreparationEnd: () => {},
85352
- logger: viteDevServer.config.logger,
85353
- complianceConfig: ctx.entryWorkerConfig
85451
+ containerTagToOptionsMap,
85452
+ logger: viteDevServer.config.logger
85354
85453
  });
85355
85454
  containerImageTags = new Set(containerTagToOptionsMap.keys());
85356
85455
  viteDevServer.config.logger.info(import_picocolors$2.default.dim(import_picocolors$2.default.yellow("\n⚡️ Containers successfully built. To rebuild your containers during development, restart the Vite dev server (r + enter).")));
@@ -85560,6 +85659,7 @@ const outputConfigPlugin = createPlugin("output-config", (ctx) => {
85560
85659
  function getOutputConfig({ inputWorkerConfig, workerOutputDirectory, resolvedViteConfig, entryFileName, includeAssets }) {
85561
85660
  const sourceConfigDirectory = inputWorkerConfig.configPath ? path.dirname(inputWorkerConfig.configPath) : resolvedViteConfig.root;
85562
85661
  const outputDirectory = path.resolve(resolvedViteConfig.root, workerOutputDirectory);
85662
+ const rebasePathToOutput = (sourcePath) => vite.normalizePath(path.relative(outputDirectory, path.resolve(sourceConfigDirectory, sourcePath)) || ".");
85563
85663
  return {
85564
85664
  ...inputWorkerConfig,
85565
85665
  main: entryFileName,
@@ -85572,10 +85672,23 @@ function getOutputConfig({ inputWorkerConfig, workerOutputDirectory, resolvedVit
85572
85672
  ...inputWorkerConfig.assets,
85573
85673
  directory: getAssetsDirectory(workerOutputDirectory, resolvedViteConfig)
85574
85674
  } : void 0,
85675
+ containers: inputWorkerConfig.containers?.map((container) => {
85676
+ if (container.images === void 0) return container;
85677
+ return {
85678
+ ...container,
85679
+ images: Object.fromEntries(Object.entries(container.images).map(([name, image]) => {
85680
+ if (image.dockerfile === void 0) return [name, image];
85681
+ return [name, {
85682
+ dockerfile: rebasePathToOutput(image.dockerfile),
85683
+ ...image.build_context === void 0 ? {} : { build_context: rebasePathToOutput(image.build_context) },
85684
+ ...image.build_vars === void 0 ? {} : { build_vars: image.build_vars }
85685
+ }];
85686
+ }))
85687
+ };
85688
+ }),
85575
85689
  d1_databases: inputWorkerConfig.d1_databases.map((database) => {
85576
85690
  const sourceMigrationsDir = database.migrations_dir ?? "migrations";
85577
- const sourceMigrationsPath = path.resolve(sourceConfigDirectory, sourceMigrationsDir);
85578
- const outputMigrationsDir = vite.normalizePath(path.relative(outputDirectory, sourceMigrationsPath) || ".");
85691
+ const outputMigrationsDir = rebasePathToOutput(sourceMigrationsDir);
85579
85692
  return {
85580
85693
  ...database,
85581
85694
  migrations_dir: outputMigrationsDir,
@@ -85674,19 +85787,10 @@ const previewPlugin = createPlugin("preview", (ctx) => {
85674
85787
  if (containerTagToOptionsMap.size) {
85675
85788
  const dockerPath = getDockerPath();
85676
85789
  vitePreviewServer.config.logger.info(import_picocolors$1.default.dim(import_picocolors$1.default.yellow("∷ Building container images for local preview...\n")));
85677
- if ([...containerTagToOptionsMap.values()].some((opts) => "image_uri" in opts && new URL(`http://${opts.image_uri}`).hostname === getCloudflareContainerRegistry(ctx.allWorkerConfigs[0]))) {
85678
- const apiToken = process.env.CLOUDFLARE_API_TOKEN;
85679
- const accountId = ctx.allWorkerConfigs[0]?.account_id ?? process.env.CLOUDFLARE_ACCOUNT_ID;
85680
- if (!apiToken || !accountId) throw new UserError("To use images from the Cloudflare-managed registry with the Vite plugin, set the CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID environment variables.\nThe API token requires Containers:Edit and Workers Scripts:Edit permissions.\nAlternatively, use a Dockerfile that references the image via FROM.", { telemetryMessage: false });
85681
- configureContainerPull(accountId, apiToken, ctx.allWorkerConfigs[0]);
85682
- }
85683
- await prepareContainerImagesForDev({
85684
- dockerPath: getDockerPath(),
85685
- containerOptions: [...containerTagToOptionsMap.values()],
85686
- onContainerImagePreparationStart: () => {},
85687
- onContainerImagePreparationEnd: () => {},
85688
- logger: vitePreviewServer.config.logger,
85689
- complianceConfig: ctx.allWorkerConfigs[0]
85790
+ await prepareContainerImagesForVite({
85791
+ dockerPath,
85792
+ containerTagToOptionsMap,
85793
+ logger: vitePreviewServer.config.logger
85690
85794
  });
85691
85795
  const containerImageTags = new Set(containerTagToOptionsMap.keys());
85692
85796
  vitePreviewServer.config.logger.info(import_picocolors$1.default.dim(import_picocolors$1.default.yellow("\n⚡️ Containers successfully built.\n")));