@odla-ai/chapter 0.42.2 → 0.42.3

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.
@@ -23,7 +23,7 @@ type TextFields$1<Key extends string> = {
23
23
  [Field in Key]: string;
24
24
  };
25
25
  /** User-visible language for sharing, delivery state, and leader rollups. */
26
- type AdminNetworkCopy = TextFields$1<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "recordTotals" | "noRecordTotals">;
26
+ type AdminNetworkCopy = TextFields$1<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "transportReachable" | "transportUnavailable" | "transportNotChecked" | "bindingTransport" | "urlTransport" | "activeConfiguration" | "noActiveConfiguration" | "publicSiteAvailable" | "publicSiteUnavailable" | "publicSiteNotChecked" | "recordTotals" | "noRecordTotals">;
27
27
 
28
28
  type TextFields<Key extends string> = {
29
29
  [Field in Key]: string;
@@ -23,7 +23,7 @@ type TextFields$1<Key extends string> = {
23
23
  [Field in Key]: string;
24
24
  };
25
25
  /** User-visible language for sharing, delivery state, and leader rollups. */
26
- type AdminNetworkCopy = TextFields$1<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "recordTotals" | "noRecordTotals">;
26
+ type AdminNetworkCopy = TextFields$1<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "transportReachable" | "transportUnavailable" | "transportNotChecked" | "bindingTransport" | "urlTransport" | "activeConfiguration" | "noActiveConfiguration" | "publicSiteAvailable" | "publicSiteUnavailable" | "publicSiteNotChecked" | "recordTotals" | "noRecordTotals">;
27
27
 
28
28
  type TextFields<Key extends string> = {
29
29
  [Field in Key]: string;
@@ -3308,17 +3308,36 @@ async function deliverAdmissionGrants(options) {
3308
3308
  }
3309
3309
 
3310
3310
  // src/worker-network-fetch.ts
3311
- function targetFetcher(env, target) {
3312
- if (!target.binding) return null;
3311
+ var NetworkTargetTransportError = class extends Error {
3312
+ code = "binding_unavailable";
3313
+ binding;
3314
+ constructor(binding) {
3315
+ super(`service binding "${binding}" is unavailable`);
3316
+ this.name = "NetworkTargetTransportError";
3317
+ this.binding = binding;
3318
+ }
3319
+ };
3320
+ function resolveNetworkTargetTransport(env, target) {
3321
+ if (!target.binding) {
3322
+ return {
3323
+ kind: "url",
3324
+ fetch: (destination, init) => globalThis.fetch(destination, init)
3325
+ };
3326
+ }
3313
3327
  const candidate = env[target.binding];
3314
3328
  if (typeof candidate !== "object" || candidate === null || !("fetch" in candidate) || typeof candidate.fetch !== "function") {
3315
- throw new Error(`service binding "${target.binding}" is unavailable`);
3329
+ throw new NetworkTargetTransportError(target.binding);
3316
3330
  }
3317
- return candidate;
3331
+ const binding = candidate;
3332
+ return {
3333
+ kind: "binding",
3334
+ binding: target.binding,
3335
+ // Keep the receiver attached: Cloudflare service bindings require it.
3336
+ fetch: (destination, init) => binding.fetch(new Request(destination, init))
3337
+ };
3318
3338
  }
3319
3339
  function fetchNetworkTarget(env, target, destination, init) {
3320
- const binding = targetFetcher(env, target);
3321
- return binding ? binding.fetch(new Request(destination, init)) : globalThis.fetch(destination, init);
3340
+ return resolveNetworkTargetTransport(env, target).fetch(destination, init);
3322
3341
  }
3323
3342
 
3324
3343
  // src/worker-network-admission-state.ts
@@ -5732,26 +5751,50 @@ var handleNetworkSnapshot = async (req, url, env, ctx) => {
5732
5751
  const types = await Promise.all(
5733
5752
  Object.keys(ctx.chapter.crm.config.types).map((type) => typeSummary({ crm: ctx.chapter.crm, db }, type))
5734
5753
  );
5754
+ const activeConfiguration = ctx.chapter.signupControl ? await loadActiveSignupControl(db, ctx.chapter.id, env.ODLA_ENV) : null;
5735
5755
  const snapshot = {
5736
5756
  version: 1,
5737
5757
  site: { id: ctx.chapter.id, name: ctx.chapter.name, mode: ctx.chapter.mode },
5738
5758
  generatedAt: Date.now(),
5759
+ configuration: {
5760
+ activeRevision: activeConfiguration?.revision ?? null,
5761
+ ...activeConfiguration ? { digest: activeConfiguration.digest } : {}
5762
+ },
5739
5763
  types
5740
5764
  };
5741
5765
  return json(snapshot);
5742
5766
  };
5743
5767
  async function snapshotOne(db, env, ctx, target) {
5768
+ const transportKind = target.binding ? "binding" : "url";
5769
+ const base = {
5770
+ id: target.id,
5771
+ name: target.name,
5772
+ url: target.url,
5773
+ configuration: { activeRevision: null },
5774
+ publicSite: { available: null }
5775
+ };
5744
5776
  const secret = await getVaultSecret(db, target.secretName);
5745
- if (!secret) return { id: target.id, name: target.name, url: target.url, available: false, error: "edge secret is missing" };
5777
+ if (!secret) return {
5778
+ ...base,
5779
+ available: false,
5780
+ transport: {
5781
+ kind: transportKind,
5782
+ ...target.binding ? { binding: target.binding } : {},
5783
+ reachable: null,
5784
+ error: { code: "edge_secret_missing", message: "edge secret is missing" }
5785
+ },
5786
+ error: "edge secret is missing"
5787
+ };
5746
5788
  const destination = new URL("/api/network/snapshot", target.url);
5747
5789
  try {
5790
+ const transport = resolveNetworkTargetTransport(env, target);
5748
5791
  const headers = await signFederatedRequest3({
5749
5792
  secret,
5750
5793
  sender: ctx.chapter.id,
5751
5794
  method: "GET",
5752
5795
  url: destination
5753
5796
  });
5754
- const response = await fetchNetworkTarget(env, target, destination, {
5797
+ const response = await transport.fetch(destination, {
5755
5798
  headers,
5756
5799
  signal: AbortSignal.timeout(1e4)
5757
5800
  });
@@ -5759,28 +5802,47 @@ async function snapshotOne(db, env, ctx, target) {
5759
5802
  if (!response.ok || !body || !("version" in body) || body.version !== 1 || !("site" in body) || body.site.id !== target.id || !Array.isArray(body.types)) {
5760
5803
  const upstream = body && "error" in body && typeof body.error === "string" ? body.error : void 0;
5761
5804
  return {
5762
- id: target.id,
5763
- name: target.name,
5764
- url: target.url,
5805
+ ...base,
5765
5806
  available: false,
5807
+ transport: {
5808
+ kind: transport.kind,
5809
+ ...transport.binding ? { binding: transport.binding } : {},
5810
+ reachable: true
5811
+ },
5812
+ publicSite: { available: transport.kind === "url" ? true : null },
5766
5813
  error: upstream ?? (response.ok ? "invalid follower snapshot" : `follower returned ${response.status}`)
5767
5814
  };
5768
5815
  }
5769
5816
  return {
5770
- id: target.id,
5771
- name: target.name,
5772
- url: target.url,
5817
+ ...base,
5773
5818
  available: true,
5819
+ transport: {
5820
+ kind: transport.kind,
5821
+ ...transport.binding ? { binding: transport.binding } : {},
5822
+ reachable: true
5823
+ },
5824
+ configuration: body.configuration ?? { activeRevision: null },
5825
+ publicSite: { available: transport.kind === "url" ? true : null },
5774
5826
  generatedAt: body.generatedAt,
5775
5827
  types: body.types
5776
5828
  };
5777
5829
  } catch (error) {
5830
+ const bindingError = error instanceof NetworkTargetTransportError;
5831
+ const message = error instanceof Error ? error.message : "snapshot failed";
5778
5832
  return {
5779
- id: target.id,
5780
- name: target.name,
5781
- url: target.url,
5833
+ ...base,
5782
5834
  available: false,
5783
- error: error instanceof Error ? error.message : "snapshot failed"
5835
+ transport: {
5836
+ kind: transportKind,
5837
+ ...target.binding ? { binding: target.binding } : {},
5838
+ reachable: false,
5839
+ error: {
5840
+ code: bindingError ? "binding_unavailable" : target.binding ? "binding_request_failed" : "url_request_failed",
5841
+ message
5842
+ }
5843
+ },
5844
+ publicSite: { available: target.binding ? null : false },
5845
+ error: message
5784
5846
  };
5785
5847
  }
5786
5848
  }