@ohhwells/bridge 0.1.151-next.406 → 0.1.151-next.408

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.cjs CHANGED
@@ -17065,6 +17065,90 @@ function bindPublishedForms(apiUrl, subdomain, content = {}) {
17065
17065
  );
17066
17066
  }
17067
17067
 
17068
+ // src/lib/outage-beacon.ts
17069
+ var DEDUP_MS = 5 * 60 * 1e3;
17070
+ var lastSent = /* @__PURE__ */ new Map();
17071
+ function apiBase() {
17072
+ return process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17073
+ }
17074
+ function bridgeVersion() {
17075
+ try {
17076
+ if (true) {
17077
+ return "0.1.151-next.408";
17078
+ }
17079
+ } catch {
17080
+ }
17081
+ if (typeof document !== "undefined") {
17082
+ return document.documentElement.getAttribute("data-ohw-bridge-version") || void 0;
17083
+ }
17084
+ return void 0;
17085
+ }
17086
+ function stampBridgeVersionOnDocument() {
17087
+ if (typeof document === "undefined") {
17088
+ return;
17089
+ }
17090
+ try {
17091
+ const v = true ? "0.1.151-next.408" : "";
17092
+ if (v) {
17093
+ document.documentElement.setAttribute("data-ohw-bridge-version", v);
17094
+ window.__OHW_BRIDGE_VERSION__ = v;
17095
+ }
17096
+ } catch {
17097
+ }
17098
+ }
17099
+ function reportOutageBeacon(args) {
17100
+ if (typeof window === "undefined" || !args.subdomain) {
17101
+ return;
17102
+ }
17103
+ const key = `${args.subdomain}|${args.reason}`;
17104
+ const now = Date.now();
17105
+ const prev = lastSent.get(key) || 0;
17106
+ if (now - prev < DEDUP_MS) {
17107
+ return;
17108
+ }
17109
+ lastSent.set(key, now);
17110
+ const body = JSON.stringify({
17111
+ subdomain: args.subdomain,
17112
+ reason: args.reason,
17113
+ detail: args.detail?.slice(0, 300),
17114
+ templateId: args.templateId,
17115
+ bridgeVersion: bridgeVersion(),
17116
+ href: typeof location !== "undefined" ? location.href : void 0
17117
+ });
17118
+ const url = `${apiBase()}/api/public/sites/outage-beacon`;
17119
+ try {
17120
+ if (typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function") {
17121
+ const blob = new Blob([body], { type: "application/json" });
17122
+ if (navigator.sendBeacon(url, blob)) {
17123
+ return;
17124
+ }
17125
+ }
17126
+ void fetch(url, {
17127
+ method: "POST",
17128
+ headers: { "Content-Type": "application/json" },
17129
+ body,
17130
+ keepalive: true,
17131
+ cache: "no-store"
17132
+ }).catch(() => {
17133
+ });
17134
+ } catch {
17135
+ }
17136
+ }
17137
+ function armLoaderHangBeacon(subdomain, fetchState, hangMs = 15e3) {
17138
+ if (!subdomain || fetchState !== "loading") {
17139
+ return () => {
17140
+ };
17141
+ }
17142
+ const timer = window.setTimeout(() => {
17143
+ reportOutageBeacon({
17144
+ subdomain,
17145
+ reason: "loader_stuck",
17146
+ detail: `fetchState still loading after ${hangMs}ms`
17147
+ });
17148
+ }, hangMs);
17149
+ return () => window.clearTimeout(timer);
17150
+ }
17151
+
17068
17152
  // src/lib/form-fields.ts
17069
17153
  var FIELD_DEFAULTS = {
17070
17154
  "short-text": { label: "Short text", placeholder: "Type placeholder text..." },
@@ -25472,6 +25556,34 @@ function OhhwellsBridge() {
25472
25556
  const [fetchState, setFetchState] = (0, import_react21.useState)("idle");
25473
25557
  const [showBranding, setShowBranding] = (0, import_react21.useState)(false);
25474
25558
  const autoSaveTimers = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
25559
+ (0, import_react21.useEffect)(() => {
25560
+ stampBridgeVersionOnDocument();
25561
+ }, []);
25562
+ (0, import_react21.useEffect)(() => {
25563
+ if (isEditMode) return;
25564
+ return armLoaderHangBeacon(subdomain, fetchState);
25565
+ }, [isEditMode, subdomain, fetchState]);
25566
+ (0, import_react21.useEffect)(() => {
25567
+ if (isEditMode || !subdomain) return;
25568
+ const onError = (event) => {
25569
+ reportOutageBeacon({
25570
+ subdomain,
25571
+ reason: "page_error",
25572
+ detail: event.message || "window error"
25573
+ });
25574
+ };
25575
+ const onRejection = (event) => {
25576
+ const reason = event.reason;
25577
+ const detail = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "unhandledrejection";
25578
+ reportOutageBeacon({ subdomain, reason: "page_error", detail });
25579
+ };
25580
+ window.addEventListener("error", onError);
25581
+ window.addEventListener("unhandledrejection", onRejection);
25582
+ return () => {
25583
+ window.removeEventListener("error", onError);
25584
+ window.removeEventListener("unhandledrejection", onRejection);
25585
+ };
25586
+ }, [isEditMode, subdomain]);
25475
25587
  const activeElRef = (0, import_react21.useRef)(null);
25476
25588
  const pointerHeldRef = (0, import_react21.useRef)(false);
25477
25589
  const selectedElRef = (0, import_react21.useRef)(null);
@@ -27740,7 +27852,17 @@ function OhhwellsBridge() {
27740
27852
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
27741
27853
  const initialPath = pathname;
27742
27854
  fetchedContentPaths.add(`${subdomain}::${initialPath}`);
27743
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
27855
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => {
27856
+ if (!r2.ok) {
27857
+ reportOutageBeacon({
27858
+ subdomain,
27859
+ reason: "content_fetch_failed",
27860
+ detail: `HTTP ${r2.status}`
27861
+ });
27862
+ return null;
27863
+ }
27864
+ return r2.json();
27865
+ }).then((data) => {
27744
27866
  if (cancelled) return;
27745
27867
  const content = data?.content ?? {};
27746
27868
  const branding = Boolean(data?.showBranding);
@@ -27749,7 +27871,12 @@ function OhhwellsBridge() {
27749
27871
  recordOverriddenPaths(subdomain, data?.overriddenPaths);
27750
27872
  setShowBranding(branding);
27751
27873
  return applyContent(content);
27752
- }).catch(() => {
27874
+ }).catch((err) => {
27875
+ reportOutageBeacon({
27876
+ subdomain,
27877
+ reason: "content_fetch_failed",
27878
+ detail: err instanceof Error ? err.message : "fetch failed"
27879
+ });
27753
27880
  }).finally(() => {
27754
27881
  if (!cancelled) setFetchState("done");
27755
27882
  });
@@ -31922,7 +32049,7 @@ function OhhwellsBridge() {
31922
32049
  postToParent2({
31923
32050
  type: "ow:ready",
31924
32051
  version: "1",
31925
- bridgeVersion: "0.1.151-next.406",
32052
+ bridgeVersion: "0.1.151-next.408",
31926
32053
  path: pathname,
31927
32054
  nodes: collectEditableNodes(editContentRef.current),
31928
32055
  sections