@cloudflare/config 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as triggers, i as exports$1, n as defineWorker, o as bindings, r as defineContainer, t as defineSettings } from "./public-Dyr8BJqf.mjs";
1
+ import { a as triggers, i as exports$1, n as defineContainer, o as bindings, r as defineWorker, t as defineConfig } from "./public-BMg6-Hxh.mjs";
2
2
  import * as nodeModule from "node:module";
3
3
  import * as z from "zod";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -322,14 +322,13 @@ const ContainerObservabilityBaseSchema = z.strictObject({
322
322
  enabled: z.boolean().optional(),
323
323
  logs: z.strictObject({ enabled: z.boolean().optional() }).optional()
324
324
  });
325
- const ContainerObservabilitySchema = z.union([ContainerObservabilityBaseSchema.extend({ targetInstancePercentage: z.number().min(0).max(100).optional() }), ContainerObservabilityBaseSchema.extend({ targetInstanceCount: z.number().int().nonnegative().optional() })]);
325
+ const StandardContainerObservabilitySchema = z.union([ContainerObservabilityBaseSchema.extend({ targetInstancePercentage: z.number().min(0).max(100).optional() }), ContainerObservabilityBaseSchema.extend({ targetInstanceCount: z.number().int().nonnegative().optional() })]);
326
326
  const BaseContainerSchema = z.strictObject({
327
- type: z.literal("container"),
328
327
  name: z.string().min(1),
329
- observability: ContainerObservabilitySchema.optional(),
330
328
  unsafe: z.record(z.string(), z.unknown()).optional()
331
329
  });
332
330
  const StandardContainerBaseSchema = BaseContainerSchema.extend({
331
+ observability: StandardContainerObservabilitySchema.optional(),
333
332
  maxInstances: z.number().int().nonnegative().default(20),
334
333
  instanceType: z.union([z.enum([
335
334
  "basic",
@@ -376,16 +375,18 @@ const StandardContainerBaseSchema = BaseContainerSchema.extend({
376
375
  activeGracePeriod: z.number().nonnegative().optional()
377
376
  }).optional()
378
377
  });
379
- const DurableObjectContainerBaseSchema = BaseContainerSchema.extend({ schedulingPolicy: z.literal("durable-object") });
378
+ const DurableObjectContainerBaseSchema = BaseContainerSchema.extend({
379
+ schedulingPolicy: z.literal("durable-object"),
380
+ observability: ContainerObservabilityBaseSchema.optional()
381
+ });
380
382
  /**
381
- * Input Container schema — validates user-authored `cloudflare.config.ts`
382
- * Container exports. Dockerfiles are built by the consuming build tool.
383
+ * Input Container schema — parses user-authored `cloudflare.config.ts`
384
+ * Container objects. Dockerfiles are built by the consuming build tool.
383
385
  */
384
386
  const InputContainerSchema = z.union([StandardContainerBaseSchema.extend({ image: InputContainerImageSchema }).superRefine(validateContainerRelationships), DurableObjectContainerBaseSchema.extend({ images: z.record(z.string(), InputContainerImageSchema).optional() })]);
385
387
  /**
386
- * Output Container schema — validates Container configs in the Build Output
387
- * Specification, after any Dockerfile has been built into a local or remote
388
- * image reference.
388
+ * Output Container schema — parses `container.config.json` files in the Build
389
+ * Output Specification, after any Dockerfile has been built into a local image reference.
389
390
  */
390
391
  const OutputContainerSchema = z.union([StandardContainerBaseSchema.extend({ image: OutputContainerImageSchema }).superRefine(validateContainerRelationships), DurableObjectContainerBaseSchema.extend({ images: z.record(z.string(), OutputContainerImageSchema).optional() })]);
391
392
  const DurableObjectCreatedExportSchema = z.strictObject({
@@ -527,7 +528,6 @@ const UnsafeSchema = z.strictObject({
527
528
  * (user-authored) and output (on-disk) Worker configs.
528
529
  */
529
530
  const BaseWorkerSchema = z.strictObject({
530
- type: z.literal("worker"),
531
531
  name: z.string(),
532
532
  compatibilityDate: z.string(),
533
533
  compatibilityFlags: z.array(z.string()).optional(),
@@ -548,72 +548,37 @@ const BaseWorkerSchema = z.strictObject({
548
548
  exports: z.record(z.string(), ExportSchema).optional()
549
549
  });
550
550
  /**
551
- * Input Worker schema — the shape that user-authored `cloudflare.config.ts`
552
- * files are validated against. Adds an optional `entrypoint` field to the
553
- * base schema.
551
+ * Input Worker schema — parses Worker definitions from user-authored
552
+ * `cloudflare.config.ts` files. Adds an optional `entrypoint` field to the base
553
+ * schema.
554
554
  */
555
555
  const InputWorkerSchema = BaseWorkerSchema.extend({ entrypoint: z.union([z.string(), z.strictObject({ default: z.string() })]).transform((value) => typeof value === "string" ? value : value.default).optional() });
556
556
  /**
557
- * Input settings schema — validates the named `settings` export of a
558
- * `cloudflare.config.ts`. Holds account/deployment settings shared by the other exports.
557
+ * Input settings schema — parses the account settings at the top level of
558
+ * `cloudflare.config.ts`.
559
559
  */
560
- const InputSettingsSchema = z.strictObject({
561
- type: z.literal("settings"),
560
+ const InputSettingsSchema = z.object({
562
561
  accountId: z.string().optional(),
563
562
  complianceRegion: z.enum(["public", "fedramp-high"]).optional()
564
563
  });
564
+ /** The resolved, user-authored project configuration. */
565
+ const InputConfigSchema = z.strictObject({
566
+ ...InputSettingsSchema.shape,
567
+ worker: InputWorkerSchema.optional(),
568
+ containers: z.array(InputContainerSchema).default([])
569
+ });
570
+ const BuildContextSchema = z.strictObject({
571
+ isPreview: z.boolean(),
572
+ mode: z.string().optional()
573
+ });
565
574
  /**
566
- * Output settings schema — the shape of the top-level `config.json` in the
567
- * Build Output Specification. Adds the `mode` the build was produced in.
575
+ * The shape of the root `config.json` in the Build Output Specification.
576
+ * Account settings remain at the top level while build context is grouped
577
+ * under `buildContext`.
568
578
  */
569
- const OutputSettingsSchema = InputSettingsSchema.extend({ mode: z.string().optional() });
570
- const DEFAULT_EXPORT_NAME = "default";
571
- const SETTINGS_EXPORT_NAME = "settings";
572
- const SUPPORTED_EXPORT_TYPES = new Set([
573
- "container",
574
- "worker",
575
- "settings"
576
- ]);
577
- function invalidConfigExportMessage(exportName) {
578
- return `The \`${exportName}\` export is not a supported export type. Move constants, helper functions, and other unsupported exports to a separate module.`;
579
- }
580
- const ConfigExportsTypeSchema = z.record(z.string(), z.unknown()).check((ctx) => {
581
- for (const [key, value] of Object.entries(ctx.value)) {
582
- const isObject = typeof value === "object" && value !== null;
583
- const type = isObject && "type" in value ? value.type : void 0;
584
- if (typeof type !== "string" || !SUPPORTED_EXPORT_TYPES.has(type)) {
585
- ctx.issues.push({
586
- code: "custom",
587
- input: value,
588
- path: isObject ? [key, "type"] : [key],
589
- message: invalidConfigExportMessage(key)
590
- });
591
- continue;
592
- }
593
- if (key === DEFAULT_EXPORT_NAME && type !== "worker") {
594
- ctx.issues.push({
595
- code: "custom",
596
- input: value,
597
- path: [key],
598
- message: `The \`${DEFAULT_EXPORT_NAME}\` export is reserved for a \`worker\` config; found a \`${type}\` config.`
599
- });
600
- continue;
601
- }
602
- const isSettingsName = key === SETTINGS_EXPORT_NAME;
603
- const isSettingsType = type === "settings";
604
- if (isSettingsType && !isSettingsName) ctx.issues.push({
605
- code: "custom",
606
- input: value,
607
- path: [key],
608
- message: `A \`settings\` config is only allowed on the \`${SETTINGS_EXPORT_NAME}\` export; found one on the \`${key}\` export.`
609
- });
610
- else if (isSettingsName && !isSettingsType) ctx.issues.push({
611
- code: "custom",
612
- input: value,
613
- path: [key],
614
- message: `The \`${SETTINGS_EXPORT_NAME}\` export is reserved for a \`settings\` config; found a \`${type}\` config.`
615
- });
616
- }
579
+ const OutputRootConfigSchema = z.strictObject({
580
+ ...InputSettingsSchema.shape,
581
+ buildContext: BuildContextSchema
617
582
  });
618
583
  const ModuleTypeSchema = z.enum([
619
584
  "esm",
@@ -645,9 +610,9 @@ const ManifestSchema = z.strictObject({
645
610
  });
646
611
  });
647
612
  /**
648
- * Output Worker schema — the shape of the Worker's `config.json` in the
649
- * Build Output Specification. Adds an optional `manifest` field to the
650
- * base schema.
613
+ * Output Worker schema — the shape of the Worker's `worker.config.json` in the
614
+ * Build Output Specification. Adds an optional `manifest` field to the base
615
+ * schema.
651
616
  */
652
617
  const OutputWorkerSchema = BaseWorkerSchema.extend({ manifest: ManifestSchema.optional() });
653
618
 
@@ -713,7 +678,8 @@ function generateTypes({ configPath, packageName = "@cloudflare/config" }) {
713
678
  return import_dist.dedent`
714
679
  /* eslint-disable */
715
680
  // Generated by @cloudflare/config
716
- type __WorkerConfig = import("${packageName}").UnwrapConfig<typeof import("${configPath.replace(/\.(ts|js|mts|mjs)$/, "")}").default>;
681
+ type __Config = import("${packageName}").UnwrapConfig<typeof import("${configPath.replace(/\.(ts|js|mts|mjs)$/, "")}").default>;
682
+ type __WorkerConfig = import("${packageName}").UnwrapConfig<__Config["worker"]>;
717
683
  type __Env = import("${packageName}").InferEnv<__WorkerConfig>;
718
684
 
719
685
  declare namespace Cloudflare {
@@ -804,34 +770,36 @@ const ROLLOUT_KIND_MAP = {
804
770
  /**
805
771
  * Convert a parsed `@cloudflare/config` config into a Wrangler `RawConfig`.
806
772
  *
807
- * The caller is responsible for unwrapping any function/promise wrappers and
808
- * validating the configs against their corresponding input schemas before
809
- * passing them in.
773
+ * The caller is responsible for resolving any function/promise wrappers and
774
+ * parsing the configuration before passing it in.
810
775
  *
811
- * @param workerConfig The parsed (post-validation) Worker config.
812
- * @param settingsConfig The optional parsed settings config, whose fields
813
- * are merged onto the result.
814
- * @param containerExports The parsed Container exports to include in the
815
- * result.
776
+ * @param config The parsed configuration.
816
777
  * @returns The corresponding Wrangler `RawConfig`.
817
778
  */
818
- function convertToWranglerConfig(workerConfig, settingsConfig, containerExports = []) {
779
+ function convertToWranglerConfig(config) {
819
780
  const result = {};
820
- convertTopLevel(workerConfig, result);
821
- convertBindingsAndAssets(workerConfig, result);
822
- convertExports(workerConfig, result);
823
- convertDomains(workerConfig, result);
824
- convertTriggers(workerConfig, result);
825
- convertTailConsumers(workerConfig, result);
826
- if (settingsConfig !== void 0) convertSettings(settingsConfig, result);
827
- if (containerExports.length > 0) result.containers = containerExports.map((container) => convertContainer(container));
781
+ const { worker, containers } = config;
782
+ if (worker !== void 0) {
783
+ convertTopLevel(worker, result);
784
+ convertBindingsAndAssets(worker, result);
785
+ convertExports(worker, result);
786
+ convertDomains(worker, result);
787
+ convertTriggers(worker, result);
788
+ convertTailConsumers(worker, result);
789
+ }
790
+ convertSettings(config, result);
791
+ if (containers.length > 0) result.containers = containers.map((container) => convertContainer(container));
828
792
  return result;
829
793
  }
830
794
  function convertContainer(container) {
831
- if (container.schedulingPolicy === "durable-object") throw new UserError("Durable Object-managed Containers are not currently supported by `convertToWranglerConfig()`.", { telemetryMessage: false });
832
795
  const converted = { name: container.name };
833
796
  if (container.observability !== void 0) converted.observability = convertContainerObservability(container.observability);
834
797
  if (container.unsafe !== void 0) converted.unsafe = container.unsafe;
798
+ if (container.schedulingPolicy === "durable-object") {
799
+ converted.scheduling_policy = "durable_object";
800
+ if (container.images !== void 0) converted.images = Object.fromEntries(Object.entries(container.images).map(([name, image]) => [name, convertDurableObjectContainerImage(image)]));
801
+ return converted;
802
+ }
835
803
  converted.image = "dockerfile" in container.image ? container.image.dockerfile : container.image.reference;
836
804
  converted.max_instances = container.maxInstances;
837
805
  if ("dockerfile" in container.image) {
@@ -860,6 +828,13 @@ function convertContainer(container) {
860
828
  }
861
829
  return converted;
862
830
  }
831
+ function convertDurableObjectContainerImage(image) {
832
+ if ("reference" in image) return { image: image.reference };
833
+ const converted = { dockerfile: image.dockerfile };
834
+ if (image.buildContext !== void 0) converted.build_context = image.buildContext;
835
+ if (image.buildVars !== void 0) converted.build_vars = image.buildVars;
836
+ return converted;
837
+ }
863
838
  function convertContainerObservability(observability) {
864
839
  const converted = {};
865
840
  if (observability.enabled !== void 0) converted.enabled = observability.enabled;
@@ -1414,31 +1389,22 @@ const CF_NO_CACHE_QUERY_KEY = "cf-no-cache";
1414
1389
  const RE_NODE_MODULES = /[/\\]node_modules[/\\]/;
1415
1390
  const depsStore = new AsyncLocalStorage();
1416
1391
  /**
1417
- * Dynamically import a worker config file from disk.
1392
+ * Dynamically import a Cloudflare config file from disk.
1418
1393
  *
1419
- * Returns all of the module's exports (keyed by export name, including
1420
- * `default`), plus the set of file paths imported during resolution. Callers
1421
- * are responsible for unwrapping function/promise/definition wrappers around
1422
- * each export and validating them.
1394
+ * Returns the module's default export plus the set of file paths imported
1395
+ * during resolution.
1423
1396
  *
1424
1397
  * @param configPath Filesystem path to the config file. Relative paths are
1425
1398
  * resolved against `process.cwd()`.
1426
- * @param options.include When provided, only exports whose names are listed
1427
- * survive into the returned `exports` map. Filtering happens before any
1428
- * resolution or validation.
1429
1399
  */
1430
- async function loadConfig(configPath, options) {
1400
+ async function loadConfig(configPath) {
1431
1401
  registerConfigHooks();
1432
1402
  const url = pathToFileURL(configPath).href;
1433
1403
  const dependencies = /* @__PURE__ */ new Set();
1434
1404
  const mod = await depsStore.run(dependencies, () => import(url, { with: { [CF_ATTR]: CF_NO_CACHE_VALUE } }));
1435
- const exports$2 = {};
1436
- for (const [name, value] of Object.entries(mod)) {
1437
- if (options?.include && !options.include.includes(name)) continue;
1438
- exports$2[name] = value;
1439
- }
1405
+ if (!("default" in mod)) throw new Error(`The config file "${configPath}" does not have a default export. Export your configuration with \`export default defineConfig({ ... })\`.`);
1440
1406
  return {
1441
- exports: exports$2,
1407
+ config: mod.default,
1442
1408
  dependencies
1443
1409
  };
1444
1410
  }
@@ -1533,11 +1499,8 @@ const CROSS_WORKER_BINDING_TYPES = new Set([
1533
1499
  function isRecord(value) {
1534
1500
  return typeof value === "object" && value !== null;
1535
1501
  }
1536
- function isConfigReference(value) {
1537
- return typeof value === "function" || isRecord(value);
1538
- }
1539
- function normalizeConfigReference(reference, resolved, expectedType) {
1540
- return isRecord(resolved) && resolved.type === expectedType && typeof resolved.name === "string" ? resolved.name : reference;
1502
+ function normalizeConfigReference(reference, resolved) {
1503
+ return isRecord(resolved) && typeof resolved.name === "string" ? resolved.name : reference;
1541
1504
  }
1542
1505
  function createDefinitionResolver(ctx) {
1543
1506
  const resolvedDefinitions = /* @__PURE__ */ new Map();
@@ -1555,11 +1518,11 @@ async function normalizeWorkerReferences(resolved, resolveDefinition) {
1555
1518
  if (!isRecord(resolved) || !isRecord(resolved.env)) return resolved;
1556
1519
  const env = { ...resolved.env };
1557
1520
  for (const [bindingName, binding] of Object.entries(env)) {
1558
- if (!isRecord(binding) || typeof binding.type !== "string" || !CROSS_WORKER_BINDING_TYPES.has(binding.type) || !isConfigReference(binding.worker)) continue;
1521
+ if (!isRecord(binding) || typeof binding.type !== "string" || !CROSS_WORKER_BINDING_TYPES.has(binding.type) || typeof binding.worker === "string") continue;
1559
1522
  const target = await resolveDefinition(binding.worker);
1560
1523
  env[bindingName] = {
1561
1524
  ...binding,
1562
- worker: normalizeConfigReference(binding.worker, target, "worker")
1525
+ worker: normalizeConfigReference(binding.worker, target)
1563
1526
  };
1564
1527
  }
1565
1528
  return {
@@ -1567,7 +1530,7 @@ async function normalizeWorkerReferences(resolved, resolveDefinition) {
1567
1530
  env
1568
1531
  };
1569
1532
  }
1570
- async function normalizeContainerReferences(resolved, resolveDefinition, resolvedExports) {
1533
+ async function normalizeContainerReferences(resolved, resolveDefinition, containers) {
1571
1534
  const issues = [];
1572
1535
  if (!isRecord(resolved) || !isRecord(resolved.exports)) return {
1573
1536
  value: resolved,
@@ -1586,7 +1549,7 @@ async function normalizeContainerReferences(resolved, resolveDefinition, resolve
1586
1549
  exportName,
1587
1550
  "container"
1588
1551
  ],
1589
- message: "Container provided as a string. Reference an exported Container definition instead."
1552
+ message: "Container provided as a string. Reference a Container definition instead, for example `container: myContainer`."
1590
1553
  });
1591
1554
  workerExports[exportName] = {
1592
1555
  ...workerExport,
@@ -1595,7 +1558,7 @@ async function normalizeContainerReferences(resolved, resolveDefinition, resolve
1595
1558
  continue;
1596
1559
  }
1597
1560
  const target = await resolveDefinition(reference);
1598
- if (isRecord(target) && target.type === "container" && typeof target.name === "string" && !Object.values(resolvedExports).includes(target)) {
1561
+ if (isRecord(target) && typeof target.name === "string" && !containers.includes(target)) {
1599
1562
  issues.push({
1600
1563
  code: "custom",
1601
1564
  input: reference,
@@ -1604,7 +1567,7 @@ async function normalizeContainerReferences(resolved, resolveDefinition, resolve
1604
1567
  exportName,
1605
1568
  "container"
1606
1569
  ],
1607
- message: `The referenced Container "${target.name}" is not exported.`
1570
+ message: `The referenced Container "${target.name}" is not included in the \`containers\` array.`
1608
1571
  });
1609
1572
  workerExports[exportName] = {
1610
1573
  ...workerExport,
@@ -1614,7 +1577,7 @@ async function normalizeContainerReferences(resolved, resolveDefinition, resolve
1614
1577
  }
1615
1578
  workerExports[exportName] = {
1616
1579
  ...workerExport,
1617
- container: normalizeConfigReference(reference, target, "container")
1580
+ container: normalizeConfigReference(reference, target)
1618
1581
  };
1619
1582
  }
1620
1583
  return {
@@ -1625,8 +1588,8 @@ async function normalizeContainerReferences(resolved, resolveDefinition, resolve
1625
1588
  issues
1626
1589
  };
1627
1590
  }
1628
- async function normalizeConfigReferences(resolved, resolveDefinition, resolvedExports) {
1629
- return normalizeContainerReferences(await normalizeWorkerReferences(resolved, resolveDefinition), resolveDefinition, resolvedExports);
1591
+ async function normalizeWorkerConfig(resolved, resolveDefinition, containers) {
1592
+ return normalizeContainerReferences(await normalizeWorkerReferences(resolved, resolveDefinition), resolveDefinition, containers);
1630
1593
  }
1631
1594
  function prefixIssues(issues, prefix) {
1632
1595
  return issues.map((issue) => ({
@@ -1634,129 +1597,99 @@ function prefixIssues(issues, prefix) {
1634
1597
  path: [prefix, ...issue.path]
1635
1598
  }));
1636
1599
  }
1637
- function validateUniqueResourceNames(configExports) {
1600
+ function validateUniqueContainerNames(config) {
1638
1601
  const issues = [];
1639
- const exportNameByResourceName = {
1640
- container: /* @__PURE__ */ new Map(),
1641
- worker: /* @__PURE__ */ new Map()
1642
- };
1643
- for (const [exportName, config] of Object.entries(configExports)) {
1644
- if (config.type !== "container" && config.type !== "worker") continue;
1645
- const resourceType = config.type === "container" ? "Container" : "Worker";
1646
- const exportNames = exportNameByResourceName[config.type];
1647
- const previousExportName = exportNames.get(config.name);
1648
- if (previousExportName !== void 0) {
1602
+ const firstIndexByName = /* @__PURE__ */ new Map();
1603
+ for (const [index, container] of config.containers.entries()) {
1604
+ const firstIndex = firstIndexByName.get(container.name);
1605
+ if (firstIndex !== void 0) {
1649
1606
  issues.push({
1650
1607
  code: "custom",
1651
- input: config.name,
1652
- path: [exportName, "name"],
1653
- message: `The ${resourceType} name "${config.name}" is also used by the "${previousExportName}" export. ${resourceType} names must be unique.`
1608
+ input: container.name,
1609
+ path: [
1610
+ "containers",
1611
+ index,
1612
+ "name"
1613
+ ],
1614
+ message: `The Container name "${container.name}" is also used by \`containers[${firstIndex}]\`. Container names must be unique.`
1654
1615
  });
1655
1616
  continue;
1656
1617
  }
1657
- exportNames.set(config.name, exportName);
1618
+ firstIndexByName.set(container.name, index);
1658
1619
  }
1659
1620
  return issues;
1660
1621
  }
1661
- function validateContainerExportLinks(configExports) {
1622
+ function validateContainerLinks(config) {
1662
1623
  const issues = [];
1663
- const containerNames = /* @__PURE__ */ new Set();
1664
- for (const config of Object.values(configExports)) if (config.type === "container") containerNames.add(config.name);
1665
- const firstReferenceByContainerName = /* @__PURE__ */ new Map();
1666
- for (const [workerExportName, config] of Object.entries(configExports)) {
1667
- if (config.type !== "worker") continue;
1668
- for (const [durableObjectExportName, workerExport] of Object.entries(config.exports ?? {})) {
1669
- if (workerExport.type !== "durable-object" || !("container" in workerExport) || workerExport.container === void 0) continue;
1670
- const containerName = workerExport.container;
1671
- const path = [
1672
- workerExportName,
1673
- "exports",
1674
- durableObjectExportName,
1675
- "container"
1676
- ];
1677
- if (!containerNames.has(containerName)) {
1678
- issues.push({
1679
- code: "custom",
1680
- input: containerName,
1681
- path,
1682
- message: `The Container "${containerName}" is not exported from this configuration.`
1683
- });
1684
- continue;
1685
- }
1686
- const firstReference = firstReferenceByContainerName.get(containerName);
1687
- if (firstReference !== void 0) {
1688
- issues.push({
1689
- code: "custom",
1690
- input: containerName,
1691
- path,
1692
- message: `The Container "${containerName}" is already referenced by "${firstReference.workerExportName}.exports.${firstReference.durableObjectExportName}". A Container can only be linked to one Durable Object.`
1693
- });
1694
- continue;
1695
- }
1696
- firstReferenceByContainerName.set(containerName, {
1697
- workerExportName,
1698
- durableObjectExportName
1624
+ const firstExportByContainerName = /* @__PURE__ */ new Map();
1625
+ for (const [exportName, workerExport] of Object.entries(config.worker?.exports ?? {})) {
1626
+ if (workerExport.type !== "durable-object" || !("container" in workerExport) || workerExport.container === void 0) continue;
1627
+ const containerName = workerExport.container;
1628
+ const firstExportName = firstExportByContainerName.get(containerName);
1629
+ if (firstExportName !== void 0) {
1630
+ issues.push({
1631
+ code: "custom",
1632
+ input: containerName,
1633
+ path: [
1634
+ "worker",
1635
+ "exports",
1636
+ exportName,
1637
+ "container"
1638
+ ],
1639
+ message: `The Container "${containerName}" is already referenced by \`worker.exports.${firstExportName}\`. A Container can only be linked to one Durable Object.`
1699
1640
  });
1641
+ continue;
1700
1642
  }
1643
+ firstExportByContainerName.set(containerName, exportName);
1701
1644
  }
1702
1645
  return issues;
1703
1646
  }
1704
- /**
1705
- * Resolve and validate loaded `cloudflare.config.ts` exports.
1706
- *
1707
- * Config inputs are resolved once by identity. Top-level Worker and Container
1708
- * exports are also parsed once by identity. References are resolved only far
1709
- * enough to replace them with resource names, then Container links are
1710
- * validated across the exported resources.
1711
- */
1712
- async function resolveAndValidateConfigExports(exports$2, ctx) {
1647
+ /** Resolve and parse the default configuration export. */
1648
+ async function resolveAndParseConfig(input, ctx) {
1713
1649
  const resolveDefinition = createDefinitionResolver(ctx);
1714
- const parsedResources = /* @__PURE__ */ new Map();
1715
- const resolvedExports = {};
1716
- for (const [name, input] of Object.entries(exports$2)) resolvedExports[name] = await resolveDefinition(input);
1717
- const typeResult = ConfigExportsTypeSchema.safeParse(resolvedExports);
1718
- if (!typeResult.success) return typeResult;
1719
- const issues = [];
1720
- const data = {};
1721
- const resolvedSettings = resolvedExports.settings;
1722
- const settingsResult = resolvedSettings ? InputSettingsSchema.safeParse(resolvedSettings) : void 0;
1723
- if (settingsResult) if (settingsResult.success) data.settings = settingsResult.data;
1724
- else issues.push(...prefixIssues(settingsResult.error.issues, "settings"));
1725
- for (const [name, input] of Object.entries(exports$2)) {
1726
- const resolved = resolvedExports[name];
1727
- if (!isRecord(resolved)) continue;
1728
- if (resolved.type !== "worker" && resolved.type !== "container") continue;
1729
- let result = parsedResources.get(input);
1730
- if (!result) {
1731
- if (resolved.type === "worker") {
1732
- const normalized = await normalizeConfigReferences(resolved, resolveDefinition, resolvedExports);
1733
- issues.push(...prefixIssues(normalized.issues, name));
1734
- result = InputWorkerSchema.safeParse(normalized.value);
1735
- } else result = InputContainerSchema.safeParse(resolved);
1736
- parsedResources.set(input, result);
1737
- if (!result.success) issues.push(...prefixIssues(result.error.issues, name));
1738
- }
1739
- if (result.success) data[name] = result.data;
1740
- }
1741
- issues.push(...validateUniqueResourceNames(data), ...validateContainerExportLinks(data));
1650
+ const resolved = await resolveDefinition(input);
1651
+ if (!isRecord(resolved)) return InputConfigSchema.safeParse(resolved);
1652
+ const containerInputs = Array.isArray(resolved.containers) ? resolved.containers : [];
1653
+ const containers = await Promise.all(containerInputs.map((container) => resolveDefinition(container)));
1654
+ const normalizedWorker = resolved.worker === void 0 ? {
1655
+ value: void 0,
1656
+ issues: []
1657
+ } : await normalizeWorkerConfig(await resolveDefinition(resolved.worker), resolveDefinition, containers);
1658
+ const candidate = {
1659
+ ...resolved,
1660
+ ...resolved.worker === void 0 ? {} : { worker: normalizedWorker.value },
1661
+ ...Array.isArray(resolved.containers) ? { containers } : {}
1662
+ };
1663
+ const result = InputConfigSchema.safeParse(candidate);
1664
+ const issues = [...prefixIssues(normalizedWorker.issues, "worker")];
1665
+ if (!result.success) issues.push(...result.error.issues);
1666
+ else issues.push(...validateUniqueContainerNames(result.data), ...validateContainerLinks(result.data));
1742
1667
  return issues.length > 0 ? {
1743
1668
  success: false,
1744
1669
  error: new z.ZodError(issues)
1745
- } : {
1746
- success: true,
1747
- data
1670
+ } : result;
1671
+ }
1672
+ /** Resolve and parse only the account settings in a configuration definition. */
1673
+ async function resolveAndParseConfigSettings(input, ctx) {
1674
+ const resolved = await createDefinitionResolver(ctx)(input);
1675
+ return InputSettingsSchema.safeParse(resolved);
1676
+ }
1677
+ /** Load and parse `cloudflare.config.ts`'s default export. */
1678
+ async function loadAndParseConfig(configPath, ctx) {
1679
+ const { config, dependencies } = await loadConfig(configPath);
1680
+ return {
1681
+ result: await resolveAndParseConfig(config, ctx),
1682
+ dependencies
1748
1683
  };
1749
1684
  }
1750
- /**
1751
- * Load a `cloudflare.config.ts`, resolve all exports, and validate them.
1752
- */
1753
- async function loadAndValidateConfig(configPath, ctx, options) {
1754
- const { exports: exports$2, dependencies } = await loadConfig(configPath, options);
1685
+ /** Load and parse only account settings from the default export. */
1686
+ async function loadAndParseConfigSettings(configPath, ctx) {
1687
+ const { config, dependencies } = await loadConfig(configPath);
1755
1688
  return {
1756
- result: await resolveAndValidateConfigExports(exports$2, ctx),
1689
+ result: await resolveAndParseConfigSettings(config, ctx),
1757
1690
  dependencies
1758
1691
  };
1759
1692
  }
1760
1693
 
1761
1694
  //#endregion
1762
- export { AnalyticsEngineDatasetBindingSchema, AssetsSchema, BindingSchema, BrowserBindingSchema, D1BindingSchema, DurableObjectCreatedExportSchema, DurableObjectDeletedExportSchema, DurableObjectExpectingTransferExportSchema, DurableObjectRenamedExportSchema, DurableObjectTransferredExportSchema, ExportSchema, FlagshipBindingSchema, HyperdriveBindingSchema, InputContainerSchema, InputSettingsSchema, InputWorkerSchema, KVBindingSchema, KnownBindingSchema, ModuleTypeSchema, OutputContainerSchema, OutputSettingsSchema, OutputWorkerSchema, QueueBindingSchema, R2BindingSchema, TailConsumerSchema, UnsafeBindingSchema, WorkerBindingSchema, WorkerEntrypointExportSchema, bindings, convertToWranglerConfig, defineContainer, defineSettings, defineWorker, exports$1 as exports, generateTypes, loadAndValidateConfig, loadConfig, registerConfigHooks, resolveAndValidateConfigExports, triggers, validateSingletonBindings };
1695
+ export { AnalyticsEngineDatasetBindingSchema, AssetsSchema, BindingSchema, BrowserBindingSchema, D1BindingSchema, DurableObjectCreatedExportSchema, DurableObjectDeletedExportSchema, DurableObjectExpectingTransferExportSchema, DurableObjectRenamedExportSchema, DurableObjectTransferredExportSchema, ExportSchema, FlagshipBindingSchema, HyperdriveBindingSchema, InputConfigSchema, InputContainerSchema, InputSettingsSchema, InputWorkerSchema, KVBindingSchema, KnownBindingSchema, ModuleTypeSchema, OutputContainerSchema, OutputRootConfigSchema, OutputWorkerSchema, QueueBindingSchema, R2BindingSchema, TailConsumerSchema, UnsafeBindingSchema, WorkerBindingSchema, WorkerEntrypointExportSchema, bindings, convertToWranglerConfig, defineConfig, defineContainer, defineWorker, exports$1 as exports, generateTypes, loadAndParseConfig, loadAndParseConfigSettings, loadConfig, registerConfigHooks, resolveAndParseConfig, resolveAndParseConfigSettings, triggers, validateSingletonBindings };