@aforoai/storefront-widgets 1.0.2 → 1.0.4

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.
@@ -1,4 +1,4 @@
1
- import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-Dm6cp_Cc.js';
1
+ import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-BbQw2_32.js';
2
2
 
3
3
  /**
4
4
  * AforoEmbed — vanilla-JS + script-tag mount API.
@@ -1,4 +1,4 @@
1
- import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-Dm6cp_Cc.cjs';
1
+ import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-BbQw2_32.cjs';
2
2
 
3
3
  /**
4
4
  * AforoEmbed — vanilla-JS + script-tag mount API.
package/dist/index.cjs CHANGED
@@ -35,7 +35,7 @@ var BridgeClientError = class extends Error {
35
35
  this.retryable = retryable;
36
36
  }
37
37
  };
38
- var DEFAULT_BASE = "https://embed.aforo.ai";
38
+ var DEFAULT_BASE = "https://storefront.aforo.ai";
39
39
  var DEFAULT_TIMEOUT_MS = 15e3;
40
40
  function uuidv4() {
41
41
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
@@ -223,10 +223,23 @@ var _BridgeClient = class _BridgeClient {
223
223
  /**
224
224
  * Headless config — the PricingCard widget's primary read path.
225
225
  *
226
- * Mirrors `GET /api/v1/portal/headless/config` which returns
227
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
228
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
229
- * cache once per widget instance on the client.
226
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
227
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
228
+ * extended server-side with `offerings` + `embeddableWidget`. This was
229
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
230
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
231
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
232
+ * embed-tier fetch against that URL failed 400 "Missing tenant
233
+ * identification" by construction; this endpoint is scoped to the same
234
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
235
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
236
+ * sends is sufficient.
237
+ *
238
+ * The backend response is still a flat record (`tenantSlug,
239
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
240
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
241
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
242
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
230
243
  *
231
244
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
232
245
  * malformed JSON. Widgets fall through to their empty / error state and
@@ -241,7 +254,7 @@ var _BridgeClient = class _BridgeClient {
241
254
  }
242
255
  const target = slug || this.tenantSlug;
243
256
  if (!target) return null;
244
- const url = `${this.baseUrl}/api/v1/portal/headless/config?tenantSlug=${encodeURIComponent(target)}`;
257
+ const url = `${this.baseUrl}/api/v1/portal/embed/tenant-config/${encodeURIComponent(target)}`;
245
258
  let resp;
246
259
  try {
247
260
  resp = await this.send(url, {
@@ -254,7 +267,18 @@ var _BridgeClient = class _BridgeClient {
254
267
  if (!resp.ok) return null;
255
268
  try {
256
269
  const body = await resp.json();
257
- return body && typeof body === "object" ? body : null;
270
+ if (!body || typeof body !== "object") return null;
271
+ return {
272
+ tenantSlug: body.tenantSlug,
273
+ branding: {
274
+ primaryColor: body.primaryColor ?? null,
275
+ secondaryColor: body.secondaryColor ?? null,
276
+ logoUrl: body.logoUrl ?? null,
277
+ fontFamily: body.fontFamily ?? null
278
+ },
279
+ offerings: Array.isArray(body.offerings) ? body.offerings : [],
280
+ embeddableWidget: body.embeddableWidget ?? null
281
+ };
258
282
  } catch {
259
283
  return null;
260
284
  }
@@ -1759,9 +1783,10 @@ var AforoSession = {
1759
1783
  };
1760
1784
  sessions.set(k, entry);
1761
1785
  if (config.bridgeToken) {
1762
- entry.pendingExchange = refreshSession(entry).catch((err) => {
1763
- throw err;
1786
+ const exchangePromise = refreshSession(entry);
1787
+ exchangePromise.catch(() => {
1764
1788
  });
1789
+ entry.pendingExchange = exchangePromise;
1765
1790
  } else if (config.magicLinkMode) {
1766
1791
  const tokenInUrl = readMagicTokenFromUrl();
1767
1792
  if (tokenInUrl) {
@@ -1771,6 +1796,8 @@ var AforoSession = {
1771
1796
  pending = runMagicLinkVerify(entry, tokenInUrl).finally(() => {
1772
1797
  pendingMagicLinkVerifies.delete(dedupKey);
1773
1798
  });
1799
+ pending.catch(() => {
1800
+ });
1774
1801
  pendingMagicLinkVerifies.set(dedupKey, pending);
1775
1802
  }
1776
1803
  entry.pendingExchange = pending;
@@ -12148,7 +12175,7 @@ function ResultPanel({
12148
12175
  }
12149
12176
 
12150
12177
  // src/core/version.ts
12151
- var VERSION = "1.0.2";
12178
+ var VERSION = "1.0.4";
12152
12179
 
12153
12180
  // src/core/AforoEmbed.ts
12154
12181
  var mountedElements = /* @__PURE__ */ new WeakMap();
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-Dm6cp_Cc.cjs';
3
- export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-Dm6cp_Cc.cjs';
4
- export { A as AforoEmbed } from './AforoEmbed-BqQOFsl3.cjs';
2
+ import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-BbQw2_32.cjs';
3
+ export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-BbQw2_32.cjs';
4
+ export { A as AforoEmbed } from './AforoEmbed-VYb6_GXB.cjs';
5
5
  export { EmbedEnvironment, EmbedKey } from '@aforoai/types';
6
6
 
7
7
  /**
@@ -639,7 +639,7 @@ declare function AforoUpgradeCancel(props: AforoUpgradeCancelProps): React.React
639
639
  * POST /api/v1/portal/embed/bridge/exchange — bridge JWT → session JWT
640
640
  * POST /api/v1/portal/embed/bridge/refresh — session JWT refresh (Prompt 8)
641
641
  * POST /api/v1/portal/embed/telemetry — telemetry batch sink
642
- * GET /api/v1/portal/embed/tenant-config/{slug} — brand kit (this Prompt)
642
+ * GET /api/v1/portal/embed/tenant-config/{slug} — brand kit + offerings + embeddableWidget
643
643
  * GET /api/v1/portal/embed/health — public liveness
644
644
  *
645
645
  * Headers:
@@ -657,7 +657,7 @@ declare function AforoUpgradeCancel(props: AforoUpgradeCancelProps): React.React
657
657
 
658
658
  type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
659
659
  interface BridgeClientOptions {
660
- /** Default `https://embed.aforo.ai`. Override for tests / dev. */
660
+ /** Default `https://storefront.aforo.ai` (the storefront-service BFF, not the embed.aforo.ai CDN). Override for tests / dev. */
661
661
  embedBaseUrl?: string;
662
662
  /** Embed key (Bearer token for all embed-key-gated endpoints). */
663
663
  embedKey: string;
@@ -707,10 +707,23 @@ declare class BridgeClient {
707
707
  /**
708
708
  * Headless config — the PricingCard widget's primary read path.
709
709
  *
710
- * Mirrors `GET /api/v1/portal/headless/config` which returns
711
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
712
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
713
- * cache once per widget instance on the client.
710
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
711
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
712
+ * extended server-side with `offerings` + `embeddableWidget`. This was
713
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
714
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
715
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
716
+ * embed-tier fetch against that URL failed 400 "Missing tenant
717
+ * identification" by construction; this endpoint is scoped to the same
718
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
719
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
720
+ * sends is sufficient.
721
+ *
722
+ * The backend response is still a flat record (`tenantSlug,
723
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
724
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
725
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
726
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
714
727
  *
715
728
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
716
729
  * malformed JSON. Widgets fall through to their empty / error state and
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-Dm6cp_Cc.js';
3
- export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-Dm6cp_Cc.js';
4
- export { A as AforoEmbed } from './AforoEmbed-CmqjlYlt.js';
2
+ import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-BbQw2_32.js';
3
+ export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-BbQw2_32.js';
4
+ export { A as AforoEmbed } from './AforoEmbed-BkJF1hAN.js';
5
5
  export { EmbedEnvironment, EmbedKey } from '@aforoai/types';
6
6
 
7
7
  /**
@@ -639,7 +639,7 @@ declare function AforoUpgradeCancel(props: AforoUpgradeCancelProps): React.React
639
639
  * POST /api/v1/portal/embed/bridge/exchange — bridge JWT → session JWT
640
640
  * POST /api/v1/portal/embed/bridge/refresh — session JWT refresh (Prompt 8)
641
641
  * POST /api/v1/portal/embed/telemetry — telemetry batch sink
642
- * GET /api/v1/portal/embed/tenant-config/{slug} — brand kit (this Prompt)
642
+ * GET /api/v1/portal/embed/tenant-config/{slug} — brand kit + offerings + embeddableWidget
643
643
  * GET /api/v1/portal/embed/health — public liveness
644
644
  *
645
645
  * Headers:
@@ -657,7 +657,7 @@ declare function AforoUpgradeCancel(props: AforoUpgradeCancelProps): React.React
657
657
 
658
658
  type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
659
659
  interface BridgeClientOptions {
660
- /** Default `https://embed.aforo.ai`. Override for tests / dev. */
660
+ /** Default `https://storefront.aforo.ai` (the storefront-service BFF, not the embed.aforo.ai CDN). Override for tests / dev. */
661
661
  embedBaseUrl?: string;
662
662
  /** Embed key (Bearer token for all embed-key-gated endpoints). */
663
663
  embedKey: string;
@@ -707,10 +707,23 @@ declare class BridgeClient {
707
707
  /**
708
708
  * Headless config — the PricingCard widget's primary read path.
709
709
  *
710
- * Mirrors `GET /api/v1/portal/headless/config` which returns
711
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
712
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
713
- * cache once per widget instance on the client.
710
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
711
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
712
+ * extended server-side with `offerings` + `embeddableWidget`. This was
713
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
714
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
715
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
716
+ * embed-tier fetch against that URL failed 400 "Missing tenant
717
+ * identification" by construction; this endpoint is scoped to the same
718
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
719
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
720
+ * sends is sufficient.
721
+ *
722
+ * The backend response is still a flat record (`tenantSlug,
723
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
724
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
725
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
726
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
714
727
  *
715
728
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
716
729
  * malformed JSON. Widgets fall through to their empty / error state and
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ var BridgeClientError = class extends Error {
13
13
  this.retryable = retryable;
14
14
  }
15
15
  };
16
- var DEFAULT_BASE = "https://embed.aforo.ai";
16
+ var DEFAULT_BASE = "https://storefront.aforo.ai";
17
17
  var DEFAULT_TIMEOUT_MS = 15e3;
18
18
  function uuidv4() {
19
19
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
@@ -201,10 +201,23 @@ var _BridgeClient = class _BridgeClient {
201
201
  /**
202
202
  * Headless config — the PricingCard widget's primary read path.
203
203
  *
204
- * Mirrors `GET /api/v1/portal/headless/config` which returns
205
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
206
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
207
- * cache once per widget instance on the client.
204
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
205
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
206
+ * extended server-side with `offerings` + `embeddableWidget`. This was
207
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
208
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
209
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
210
+ * embed-tier fetch against that URL failed 400 "Missing tenant
211
+ * identification" by construction; this endpoint is scoped to the same
212
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
213
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
214
+ * sends is sufficient.
215
+ *
216
+ * The backend response is still a flat record (`tenantSlug,
217
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
218
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
219
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
220
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
208
221
  *
209
222
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
210
223
  * malformed JSON. Widgets fall through to their empty / error state and
@@ -219,7 +232,7 @@ var _BridgeClient = class _BridgeClient {
219
232
  }
220
233
  const target = slug || this.tenantSlug;
221
234
  if (!target) return null;
222
- const url = `${this.baseUrl}/api/v1/portal/headless/config?tenantSlug=${encodeURIComponent(target)}`;
235
+ const url = `${this.baseUrl}/api/v1/portal/embed/tenant-config/${encodeURIComponent(target)}`;
223
236
  let resp;
224
237
  try {
225
238
  resp = await this.send(url, {
@@ -232,7 +245,18 @@ var _BridgeClient = class _BridgeClient {
232
245
  if (!resp.ok) return null;
233
246
  try {
234
247
  const body = await resp.json();
235
- return body && typeof body === "object" ? body : null;
248
+ if (!body || typeof body !== "object") return null;
249
+ return {
250
+ tenantSlug: body.tenantSlug,
251
+ branding: {
252
+ primaryColor: body.primaryColor ?? null,
253
+ secondaryColor: body.secondaryColor ?? null,
254
+ logoUrl: body.logoUrl ?? null,
255
+ fontFamily: body.fontFamily ?? null
256
+ },
257
+ offerings: Array.isArray(body.offerings) ? body.offerings : [],
258
+ embeddableWidget: body.embeddableWidget ?? null
259
+ };
236
260
  } catch {
237
261
  return null;
238
262
  }
@@ -1737,9 +1761,10 @@ var AforoSession = {
1737
1761
  };
1738
1762
  sessions.set(k, entry);
1739
1763
  if (config.bridgeToken) {
1740
- entry.pendingExchange = refreshSession(entry).catch((err) => {
1741
- throw err;
1764
+ const exchangePromise = refreshSession(entry);
1765
+ exchangePromise.catch(() => {
1742
1766
  });
1767
+ entry.pendingExchange = exchangePromise;
1743
1768
  } else if (config.magicLinkMode) {
1744
1769
  const tokenInUrl = readMagicTokenFromUrl();
1745
1770
  if (tokenInUrl) {
@@ -1749,6 +1774,8 @@ var AforoSession = {
1749
1774
  pending = runMagicLinkVerify(entry, tokenInUrl).finally(() => {
1750
1775
  pendingMagicLinkVerifies.delete(dedupKey);
1751
1776
  });
1777
+ pending.catch(() => {
1778
+ });
1752
1779
  pendingMagicLinkVerifies.set(dedupKey, pending);
1753
1780
  }
1754
1781
  entry.pendingExchange = pending;
@@ -12126,7 +12153,7 @@ function ResultPanel({
12126
12153
  }
12127
12154
 
12128
12155
  // src/core/version.ts
12129
- var VERSION = "1.0.2";
12156
+ var VERSION = "1.0.4";
12130
12157
 
12131
12158
  // src/core/AforoEmbed.ts
12132
12159
  var mountedElements = /* @__PURE__ */ new WeakMap();
package/dist/loader.js CHANGED
@@ -1,3 +1,3 @@
1
- var AforoEmbedLoader=(function(exports){'use strict';var T="1.0.2";var y=new WeakMap,c=new Map,f={},A=false;function h(){A||typeof window!="undefined"&&(window.addEventListener("message",e=>{let t=e.data;!t||typeof t!="object"||typeof t.type!="string"||t.type.startsWith("aforo.")&&$(t);}),A=true);}function $(e){let t=c.get(e.type);if(t)for(let o of t)try{o(e);}catch(i){}let n=c.get("*");if(n)for(let o of n)try{o(e);}catch(i){}}var p=new Map;function N(e,t){p.set(e,t);}function w(e){return typeof e=="object"&&e!==null&&typeof e.tagName=="string"}var b={version:T,configure(e){f={...f,...e};},getConfig(){return {...f}},mount(e,t){var r,l,u,s,d;if(!w(e)||y.has(e))return false;let n=t.widget,o=p.get(n);if(!o)return typeof console!="undefined"&&console.warn(`[aforo:embed] No mount handler registered for widget "${n}". Loader bundle may not have finished loading.`),false;let i={widget:n,tenantSlug:(l=(r=t.tenantSlug)!=null?r:f.tenantSlug)!=null?l:"",embedKey:(s=(u=t.embedKey)!=null?u:f.embedKey)!=null?s:"",bridgeToken:(d=t.bridgeToken)!=null?d:f.bridgeToken,layout:t.layout,themeOverrides:t.themeOverrides,config:t.config};if(!i.tenantSlug||!i.embedKey)return typeof console!="undefined"&&console.error(`[aforo:embed] Widget "${n}" requires tenantSlug + embedKey. Provide via AforoEmbed.configure() or data-* attributes.`),false;h();let a=o(e,i);return y.set(e,{element:e,widget:n,teardown:a}),true},unmount(e){if(!w(e))return false;let t=y.get(e);if(!t)return false;try{t.teardown();}catch(n){}return y.delete(e),true},on(e,t){h();let n=c.get(e);return n||(n=new Set,c.set(e,n)),n.add(t),()=>{let o=c.get(e);o&&(o.delete(t),o.size===0&&c.delete(e));}},_registerWidget:N,_registeredWidgetsForTesting(){return Array.from(p.keys())},_resetForTesting(){p.clear(),c.clear(),f={};}};function k(e){if(!e)return {};try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n={},o=["primary","primaryContrast","text","textMuted","bg","border","radius","fontFamily"],i=t;for(let a of o){let r=i[a];typeof r=="string"&&r.length>0&&(n[a]=r);}return n}}catch(t){}return {}}var U=new Set(["pricing-card","subscribe-button","checkout-flow","subscription-manager","invoice-list","usage-meter","payment-method","upgrade-cancel"]),B="https://embed.aforo.ai/v1/widgets",g="[aforo:loader]";function D(){let e=typeof document!="undefined"?document.currentScript:null;if(e&&e.tagName==="SCRIPT")return e;if(typeof document!="undefined"){let t=document.getElementsByTagName("script");for(let n=t.length-1;n>=0;n--){let o=t[n];if(!o)continue;let i=o.getAttribute("src")||"";if(/(\/v1)?\/loader(\.umd)?\.js$/.test(i))return o}}return null}function G(e){let t=e==null?void 0:e.getAttribute("src");if(!t)return null;try{let n=typeof location!="undefined"?location.href:void 0,o=new URL(t,n),i=o.pathname.replace(/\/loader(\.umd)?\.js$/,"");return `${o.origin}${i}/widgets`}catch(n){return null}}function v(e,t){let n=e.getAttribute(t);if(n==null||n.trim()==="")return;let o=Number(n);return Number.isFinite(o)?o:void 0}function j(e,t){let n=e.getAttribute(t);if(n==null)return;let o=n.trim().toLowerCase();if(o==="true")return true;if(o==="false")return false}function V(e){let t=(e.getAttribute("data-aforo-widget")||"").trim(),n=e.getAttribute("data-tenant-slug")||e.getAttribute("data-tenant")||"",o=e.getAttribute("data-embed-key")||"",i=e.getAttribute("data-bridge-token")||void 0,a=e.getAttribute("data-layout")||void 0,r=k(e.getAttribute("data-theme-overrides")),l=e.getAttribute("data-offering-id")||void 0,u=e.getAttribute("data-subscription-id")||void 0,s=e.getAttribute("data-metric")||void 0,d=e.getAttribute("data-featured-offering-id")||void 0,m=e.getAttribute("data-mode")||void 0,M=e.getAttribute("data-return-url")||void 0,S=e.getAttribute("data-default-status")||void 0,F=e.getAttribute("data-render-mode")||void 0,_=e.getAttribute("data-locale")||void 0,C=v(e,"data-page-size"),O=v(e,"data-poll-interval-ms"),I=e.getAttribute("data-theme")||void 0,R=e.getAttribute("data-cart-type")||void 0,W=e.getAttribute("data-target-id")||void 0,H=e.getAttribute("data-cta-text")||void 0,x=e.getAttribute("data-cta-url")||void 0,P=v(e,"data-max-plans"),K=j(e,"data-show-features");return {widget:t,tenantSlug:n,embedKey:o,bridgeToken:i,layout:a,themeOverrides:r,config:{offeringId:l,subscriptionId:u,metricName:s,featuredOfferingId:d,mode:m,returnUrl:M,defaultStatus:S,renderMode:F,locale:_,pageSize:C,pollIntervalMs:O,theme:I,cartType:R,targetId:W,ctaText:H,ctaUrl:x,maxPlans:P,showFeatures:K}}}function z(e,t,n){return new Promise((o,i)=>{if(typeof document=="undefined")return i(new Error("no document"));let a=document.querySelector(`script[data-aforo-bundle="${e}"]`);if(a){if(a.dataset.aforoLoaded==="1")return o();a.addEventListener("load",()=>o()),a.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`)));return}let r=document.createElement("script");r.src=`${t}/${e}.js`,r.async=true,r.crossOrigin="anonymous",r.dataset.aforoBundle=e,n&&r.setAttribute("nonce",n),r.addEventListener("load",()=>{r.dataset.aforoLoaded="1",o();}),r.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`))),document.head.appendChild(r);})}function L(e){if(!e.__aforoEmbedReadyFired){e.__aforoEmbedReadyFired=true;try{typeof e.aforoEmbedReady=="function"&&e.aforoEmbedReady();}catch(t){typeof console!="undefined"&&console.error(`${g} aforoEmbedReady callback threw`,t);}if(typeof document!="undefined"&&typeof CustomEvent!="undefined")try{document.dispatchEvent(new CustomEvent("aforoEmbedReady"));}catch(t){}}}async function E(e){if(typeof window=="undefined"||typeof document=="undefined")return;let t=window;if(window.location.protocol!=="https:"&&window.location.hostname!=="localhost"){typeof console!="undefined"&&console.error(`${g} Refusing to mount Aforo widgets on a non-HTTPS page. Embed Plugin requires HTTPS (FR-TIER-12). Current origin: ${window.location.origin}`);return}if(t.__aforoEmbedLoaderInitialized){typeof console!="undefined"&&console.warn(`${g} Loader already initialised on this page \u2014 skipping duplicate run.`);return}t.__aforoEmbedLoaderInitialized=true,t.aforoEmbed||(t.aforoEmbed=b);let n=D(),o=(n==null?void 0:n.getAttribute("nonce"))||null,i=(e==null?void 0:e.bundleBaseUrl)||G(n)||B,a=Array.from(document.querySelectorAll("[data-aforo-widget]"));if(a.length===0){L(t);return}let r=new Map;for(let u of a){let s=(u.getAttribute("data-aforo-widget")||"").trim();if(!U.has(s)){typeof console!="undefined"&&console.warn(`${g} Unknown widget id "${s}" \u2014 skipping`);continue}let d=r.get(s);d||(d=[],r.set(s,d)),d.push(u);}let l=Array.from(r.entries()).map(async([u,s])=>{try{await z(u,i,o);for(let d of s){let m=V(d);if(!m.widget||!m.tenantSlug||!m.embedKey){typeof console!="undefined"&&console.error(`${g} Placeholder missing required attributes (data-tenant-slug + data-embed-key). Skipping element.`,d);continue}b.mount(d,m);}}catch(d){typeof console!="undefined"&&console.error(`${g} Failed to load bundle for "${u}"`,d);}});await Promise.all(l).catch(()=>{}),L(t);}typeof document!="undefined"&&document.readyState!=="loading"?Promise.resolve().then(()=>{E();}):typeof document!="undefined"&&document.addEventListener("DOMContentLoaded",()=>{E();});b._loader={bootstrap:E};
1
+ var AforoEmbedLoader=(function(exports){'use strict';var T="1.0.4";var y=new WeakMap,c=new Map,f={},A=false;function h(){A||typeof window!="undefined"&&(window.addEventListener("message",e=>{let t=e.data;!t||typeof t!="object"||typeof t.type!="string"||t.type.startsWith("aforo.")&&$(t);}),A=true);}function $(e){let t=c.get(e.type);if(t)for(let o of t)try{o(e);}catch(i){}let n=c.get("*");if(n)for(let o of n)try{o(e);}catch(i){}}var p=new Map;function N(e,t){p.set(e,t);}function w(e){return typeof e=="object"&&e!==null&&typeof e.tagName=="string"}var b={version:T,configure(e){f={...f,...e};},getConfig(){return {...f}},mount(e,t){var r,l,u,s,d;if(!w(e)||y.has(e))return false;let n=t.widget,o=p.get(n);if(!o)return typeof console!="undefined"&&console.warn(`[aforo:embed] No mount handler registered for widget "${n}". Loader bundle may not have finished loading.`),false;let i={widget:n,tenantSlug:(l=(r=t.tenantSlug)!=null?r:f.tenantSlug)!=null?l:"",embedKey:(s=(u=t.embedKey)!=null?u:f.embedKey)!=null?s:"",bridgeToken:(d=t.bridgeToken)!=null?d:f.bridgeToken,layout:t.layout,themeOverrides:t.themeOverrides,config:t.config};if(!i.tenantSlug||!i.embedKey)return typeof console!="undefined"&&console.error(`[aforo:embed] Widget "${n}" requires tenantSlug + embedKey. Provide via AforoEmbed.configure() or data-* attributes.`),false;h();let a=o(e,i);return y.set(e,{element:e,widget:n,teardown:a}),true},unmount(e){if(!w(e))return false;let t=y.get(e);if(!t)return false;try{t.teardown();}catch(n){}return y.delete(e),true},on(e,t){h();let n=c.get(e);return n||(n=new Set,c.set(e,n)),n.add(t),()=>{let o=c.get(e);o&&(o.delete(t),o.size===0&&c.delete(e));}},_registerWidget:N,_registeredWidgetsForTesting(){return Array.from(p.keys())},_resetForTesting(){p.clear(),c.clear(),f={};}};function k(e){if(!e)return {};try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n={},o=["primary","primaryContrast","text","textMuted","bg","border","radius","fontFamily"],i=t;for(let a of o){let r=i[a];typeof r=="string"&&r.length>0&&(n[a]=r);}return n}}catch(t){}return {}}var U=new Set(["pricing-card","subscribe-button","checkout-flow","subscription-manager","invoice-list","usage-meter","payment-method","upgrade-cancel"]),B="https://embed.aforo.ai/v1/widgets",g="[aforo:loader]";function D(){let e=typeof document!="undefined"?document.currentScript:null;if(e&&e.tagName==="SCRIPT")return e;if(typeof document!="undefined"){let t=document.getElementsByTagName("script");for(let n=t.length-1;n>=0;n--){let o=t[n];if(!o)continue;let i=o.getAttribute("src")||"";if(/(\/v1)?\/loader(\.umd)?\.js$/.test(i))return o}}return null}function G(e){let t=e==null?void 0:e.getAttribute("src");if(!t)return null;try{let n=typeof location!="undefined"?location.href:void 0,o=new URL(t,n),i=o.pathname.replace(/\/loader(\.umd)?\.js$/,"");return `${o.origin}${i}/widgets`}catch(n){return null}}function v(e,t){let n=e.getAttribute(t);if(n==null||n.trim()==="")return;let o=Number(n);return Number.isFinite(o)?o:void 0}function j(e,t){let n=e.getAttribute(t);if(n==null)return;let o=n.trim().toLowerCase();if(o==="true")return true;if(o==="false")return false}function V(e){let t=(e.getAttribute("data-aforo-widget")||"").trim(),n=e.getAttribute("data-tenant-slug")||e.getAttribute("data-tenant")||"",o=e.getAttribute("data-embed-key")||"",i=e.getAttribute("data-bridge-token")||void 0,a=e.getAttribute("data-layout")||void 0,r=k(e.getAttribute("data-theme-overrides")),l=e.getAttribute("data-offering-id")||void 0,u=e.getAttribute("data-subscription-id")||void 0,s=e.getAttribute("data-metric")||void 0,d=e.getAttribute("data-featured-offering-id")||void 0,m=e.getAttribute("data-mode")||void 0,M=e.getAttribute("data-return-url")||void 0,S=e.getAttribute("data-default-status")||void 0,F=e.getAttribute("data-render-mode")||void 0,_=e.getAttribute("data-locale")||void 0,C=v(e,"data-page-size"),O=v(e,"data-poll-interval-ms"),I=e.getAttribute("data-theme")||void 0,R=e.getAttribute("data-cart-type")||void 0,W=e.getAttribute("data-target-id")||void 0,H=e.getAttribute("data-cta-text")||void 0,x=e.getAttribute("data-cta-url")||void 0,P=v(e,"data-max-plans"),K=j(e,"data-show-features");return {widget:t,tenantSlug:n,embedKey:o,bridgeToken:i,layout:a,themeOverrides:r,config:{offeringId:l,subscriptionId:u,metricName:s,featuredOfferingId:d,mode:m,returnUrl:M,defaultStatus:S,renderMode:F,locale:_,pageSize:C,pollIntervalMs:O,theme:I,cartType:R,targetId:W,ctaText:H,ctaUrl:x,maxPlans:P,showFeatures:K}}}function z(e,t,n){return new Promise((o,i)=>{if(typeof document=="undefined")return i(new Error("no document"));let a=document.querySelector(`script[data-aforo-bundle="${e}"]`);if(a){if(a.dataset.aforoLoaded==="1")return o();a.addEventListener("load",()=>o()),a.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`)));return}let r=document.createElement("script");r.src=`${t}/${e}.js`,r.async=true,r.crossOrigin="anonymous",r.dataset.aforoBundle=e,n&&r.setAttribute("nonce",n),r.addEventListener("load",()=>{r.dataset.aforoLoaded="1",o();}),r.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`))),document.head.appendChild(r);})}function L(e){if(!e.__aforoEmbedReadyFired){e.__aforoEmbedReadyFired=true;try{typeof e.aforoEmbedReady=="function"&&e.aforoEmbedReady();}catch(t){typeof console!="undefined"&&console.error(`${g} aforoEmbedReady callback threw`,t);}if(typeof document!="undefined"&&typeof CustomEvent!="undefined")try{document.dispatchEvent(new CustomEvent("aforoEmbedReady"));}catch(t){}}}async function E(e){if(typeof window=="undefined"||typeof document=="undefined")return;let t=window;if(window.location.protocol!=="https:"&&window.location.hostname!=="localhost"){typeof console!="undefined"&&console.error(`${g} Refusing to mount Aforo widgets on a non-HTTPS page. Embed Plugin requires HTTPS (FR-TIER-12). Current origin: ${window.location.origin}`);return}if(t.__aforoEmbedLoaderInitialized){typeof console!="undefined"&&console.warn(`${g} Loader already initialised on this page \u2014 skipping duplicate run.`);return}t.__aforoEmbedLoaderInitialized=true,t.aforoEmbed||(t.aforoEmbed=b);let n=D(),o=(n==null?void 0:n.getAttribute("nonce"))||null,i=(e==null?void 0:e.bundleBaseUrl)||G(n)||B,a=Array.from(document.querySelectorAll("[data-aforo-widget]"));if(a.length===0){L(t);return}let r=new Map;for(let u of a){let s=(u.getAttribute("data-aforo-widget")||"").trim();if(!U.has(s)){typeof console!="undefined"&&console.warn(`${g} Unknown widget id "${s}" \u2014 skipping`);continue}let d=r.get(s);d||(d=[],r.set(s,d)),d.push(u);}let l=Array.from(r.entries()).map(async([u,s])=>{try{await z(u,i,o);for(let d of s){let m=V(d);if(!m.widget||!m.tenantSlug||!m.embedKey){typeof console!="undefined"&&console.error(`${g} Placeholder missing required attributes (data-tenant-slug + data-embed-key). Skipping element.`,d);continue}b.mount(d,m);}}catch(d){typeof console!="undefined"&&console.error(`${g} Failed to load bundle for "${u}"`,d);}});await Promise.all(l).catch(()=>{}),L(t);}typeof document!="undefined"&&document.readyState!=="loading"?Promise.resolve().then(()=>{E();}):typeof document!="undefined"&&document.addEventListener("DOMContentLoaded",()=>{E();});b._loader={bootstrap:E};
2
2
  exports.AforoEmbed=b;exports.bootstrap=E;return exports;})({});//# sourceMappingURL=loader.js.map
3
3
  //# sourceMappingURL=loader.js.map
package/dist/loader.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var T="1.0.2";var y=new WeakMap,c=new Map,f={},A=false;function h(){A||typeof window!="undefined"&&(window.addEventListener("message",e=>{let t=e.data;!t||typeof t!="object"||typeof t.type!="string"||t.type.startsWith("aforo.")&&$(t);}),A=true);}function $(e){let t=c.get(e.type);if(t)for(let o of t)try{o(e);}catch(i){}let n=c.get("*");if(n)for(let o of n)try{o(e);}catch(i){}}var p=new Map;function N(e,t){p.set(e,t);}function w(e){return typeof e=="object"&&e!==null&&typeof e.tagName=="string"}var b={version:T,configure(e){f={...f,...e};},getConfig(){return {...f}},mount(e,t){var r,l,u,s,d;if(!w(e)||y.has(e))return false;let n=t.widget,o=p.get(n);if(!o)return typeof console!="undefined"&&console.warn(`[aforo:embed] No mount handler registered for widget "${n}". Loader bundle may not have finished loading.`),false;let i={widget:n,tenantSlug:(l=(r=t.tenantSlug)!=null?r:f.tenantSlug)!=null?l:"",embedKey:(s=(u=t.embedKey)!=null?u:f.embedKey)!=null?s:"",bridgeToken:(d=t.bridgeToken)!=null?d:f.bridgeToken,layout:t.layout,themeOverrides:t.themeOverrides,config:t.config};if(!i.tenantSlug||!i.embedKey)return typeof console!="undefined"&&console.error(`[aforo:embed] Widget "${n}" requires tenantSlug + embedKey. Provide via AforoEmbed.configure() or data-* attributes.`),false;h();let a=o(e,i);return y.set(e,{element:e,widget:n,teardown:a}),true},unmount(e){if(!w(e))return false;let t=y.get(e);if(!t)return false;try{t.teardown();}catch(n){}return y.delete(e),true},on(e,t){h();let n=c.get(e);return n||(n=new Set,c.set(e,n)),n.add(t),()=>{let o=c.get(e);o&&(o.delete(t),o.size===0&&c.delete(e));}},_registerWidget:N,_registeredWidgetsForTesting(){return Array.from(p.keys())},_resetForTesting(){p.clear(),c.clear(),f={};}};function k(e){if(!e)return {};try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n={},o=["primary","primaryContrast","text","textMuted","bg","border","radius","fontFamily"],i=t;for(let a of o){let r=i[a];typeof r=="string"&&r.length>0&&(n[a]=r);}return n}}catch(t){}return {}}var U=new Set(["pricing-card","subscribe-button","checkout-flow","subscription-manager","invoice-list","usage-meter","payment-method","upgrade-cancel"]),B="https://embed.aforo.ai/v1/widgets",g="[aforo:loader]";function D(){let e=typeof document!="undefined"?document.currentScript:null;if(e&&e.tagName==="SCRIPT")return e;if(typeof document!="undefined"){let t=document.getElementsByTagName("script");for(let n=t.length-1;n>=0;n--){let o=t[n];if(!o)continue;let i=o.getAttribute("src")||"";if(/(\/v1)?\/loader(\.umd)?\.js$/.test(i))return o}}return null}function G(e){let t=e==null?void 0:e.getAttribute("src");if(!t)return null;try{let n=typeof location!="undefined"?location.href:void 0,o=new URL(t,n),i=o.pathname.replace(/\/loader(\.umd)?\.js$/,"");return `${o.origin}${i}/widgets`}catch(n){return null}}function v(e,t){let n=e.getAttribute(t);if(n==null||n.trim()==="")return;let o=Number(n);return Number.isFinite(o)?o:void 0}function j(e,t){let n=e.getAttribute(t);if(n==null)return;let o=n.trim().toLowerCase();if(o==="true")return true;if(o==="false")return false}function V(e){let t=(e.getAttribute("data-aforo-widget")||"").trim(),n=e.getAttribute("data-tenant-slug")||e.getAttribute("data-tenant")||"",o=e.getAttribute("data-embed-key")||"",i=e.getAttribute("data-bridge-token")||void 0,a=e.getAttribute("data-layout")||void 0,r=k(e.getAttribute("data-theme-overrides")),l=e.getAttribute("data-offering-id")||void 0,u=e.getAttribute("data-subscription-id")||void 0,s=e.getAttribute("data-metric")||void 0,d=e.getAttribute("data-featured-offering-id")||void 0,m=e.getAttribute("data-mode")||void 0,M=e.getAttribute("data-return-url")||void 0,S=e.getAttribute("data-default-status")||void 0,F=e.getAttribute("data-render-mode")||void 0,_=e.getAttribute("data-locale")||void 0,C=v(e,"data-page-size"),O=v(e,"data-poll-interval-ms"),I=e.getAttribute("data-theme")||void 0,R=e.getAttribute("data-cart-type")||void 0,W=e.getAttribute("data-target-id")||void 0,H=e.getAttribute("data-cta-text")||void 0,x=e.getAttribute("data-cta-url")||void 0,P=v(e,"data-max-plans"),K=j(e,"data-show-features");return {widget:t,tenantSlug:n,embedKey:o,bridgeToken:i,layout:a,themeOverrides:r,config:{offeringId:l,subscriptionId:u,metricName:s,featuredOfferingId:d,mode:m,returnUrl:M,defaultStatus:S,renderMode:F,locale:_,pageSize:C,pollIntervalMs:O,theme:I,cartType:R,targetId:W,ctaText:H,ctaUrl:x,maxPlans:P,showFeatures:K}}}function z(e,t,n){return new Promise((o,i)=>{if(typeof document=="undefined")return i(new Error("no document"));let a=document.querySelector(`script[data-aforo-bundle="${e}"]`);if(a){if(a.dataset.aforoLoaded==="1")return o();a.addEventListener("load",()=>o()),a.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`)));return}let r=document.createElement("script");r.src=`${t}/${e}.js`,r.async=true,r.crossOrigin="anonymous",r.dataset.aforoBundle=e,n&&r.setAttribute("nonce",n),r.addEventListener("load",()=>{r.dataset.aforoLoaded="1",o();}),r.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`))),document.head.appendChild(r);})}function L(e){if(!e.__aforoEmbedReadyFired){e.__aforoEmbedReadyFired=true;try{typeof e.aforoEmbedReady=="function"&&e.aforoEmbedReady();}catch(t){typeof console!="undefined"&&console.error(`${g} aforoEmbedReady callback threw`,t);}if(typeof document!="undefined"&&typeof CustomEvent!="undefined")try{document.dispatchEvent(new CustomEvent("aforoEmbedReady"));}catch(t){}}}async function E(e){if(typeof window=="undefined"||typeof document=="undefined")return;let t=window;if(window.location.protocol!=="https:"&&window.location.hostname!=="localhost"){typeof console!="undefined"&&console.error(`${g} Refusing to mount Aforo widgets on a non-HTTPS page. Embed Plugin requires HTTPS (FR-TIER-12). Current origin: ${window.location.origin}`);return}if(t.__aforoEmbedLoaderInitialized){typeof console!="undefined"&&console.warn(`${g} Loader already initialised on this page \u2014 skipping duplicate run.`);return}t.__aforoEmbedLoaderInitialized=true,t.aforoEmbed||(t.aforoEmbed=b);let n=D(),o=(n==null?void 0:n.getAttribute("nonce"))||null,i=(e==null?void 0:e.bundleBaseUrl)||G(n)||B,a=Array.from(document.querySelectorAll("[data-aforo-widget]"));if(a.length===0){L(t);return}let r=new Map;for(let u of a){let s=(u.getAttribute("data-aforo-widget")||"").trim();if(!U.has(s)){typeof console!="undefined"&&console.warn(`${g} Unknown widget id "${s}" \u2014 skipping`);continue}let d=r.get(s);d||(d=[],r.set(s,d)),d.push(u);}let l=Array.from(r.entries()).map(async([u,s])=>{try{await z(u,i,o);for(let d of s){let m=V(d);if(!m.widget||!m.tenantSlug||!m.embedKey){typeof console!="undefined"&&console.error(`${g} Placeholder missing required attributes (data-tenant-slug + data-embed-key). Skipping element.`,d);continue}b.mount(d,m);}}catch(d){typeof console!="undefined"&&console.error(`${g} Failed to load bundle for "${u}"`,d);}});await Promise.all(l).catch(()=>{}),L(t);}typeof document!="undefined"&&document.readyState!=="loading"?Promise.resolve().then(()=>{E();}):typeof document!="undefined"&&document.addEventListener("DOMContentLoaded",()=>{E();});b._loader={bootstrap:E};
1
+ var T="1.0.4";var y=new WeakMap,c=new Map,f={},A=false;function h(){A||typeof window!="undefined"&&(window.addEventListener("message",e=>{let t=e.data;!t||typeof t!="object"||typeof t.type!="string"||t.type.startsWith("aforo.")&&$(t);}),A=true);}function $(e){let t=c.get(e.type);if(t)for(let o of t)try{o(e);}catch(i){}let n=c.get("*");if(n)for(let o of n)try{o(e);}catch(i){}}var p=new Map;function N(e,t){p.set(e,t);}function w(e){return typeof e=="object"&&e!==null&&typeof e.tagName=="string"}var b={version:T,configure(e){f={...f,...e};},getConfig(){return {...f}},mount(e,t){var r,l,u,s,d;if(!w(e)||y.has(e))return false;let n=t.widget,o=p.get(n);if(!o)return typeof console!="undefined"&&console.warn(`[aforo:embed] No mount handler registered for widget "${n}". Loader bundle may not have finished loading.`),false;let i={widget:n,tenantSlug:(l=(r=t.tenantSlug)!=null?r:f.tenantSlug)!=null?l:"",embedKey:(s=(u=t.embedKey)!=null?u:f.embedKey)!=null?s:"",bridgeToken:(d=t.bridgeToken)!=null?d:f.bridgeToken,layout:t.layout,themeOverrides:t.themeOverrides,config:t.config};if(!i.tenantSlug||!i.embedKey)return typeof console!="undefined"&&console.error(`[aforo:embed] Widget "${n}" requires tenantSlug + embedKey. Provide via AforoEmbed.configure() or data-* attributes.`),false;h();let a=o(e,i);return y.set(e,{element:e,widget:n,teardown:a}),true},unmount(e){if(!w(e))return false;let t=y.get(e);if(!t)return false;try{t.teardown();}catch(n){}return y.delete(e),true},on(e,t){h();let n=c.get(e);return n||(n=new Set,c.set(e,n)),n.add(t),()=>{let o=c.get(e);o&&(o.delete(t),o.size===0&&c.delete(e));}},_registerWidget:N,_registeredWidgetsForTesting(){return Array.from(p.keys())},_resetForTesting(){p.clear(),c.clear(),f={};}};function k(e){if(!e)return {};try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n={},o=["primary","primaryContrast","text","textMuted","bg","border","radius","fontFamily"],i=t;for(let a of o){let r=i[a];typeof r=="string"&&r.length>0&&(n[a]=r);}return n}}catch(t){}return {}}var U=new Set(["pricing-card","subscribe-button","checkout-flow","subscription-manager","invoice-list","usage-meter","payment-method","upgrade-cancel"]),B="https://embed.aforo.ai/v1/widgets",g="[aforo:loader]";function D(){let e=typeof document!="undefined"?document.currentScript:null;if(e&&e.tagName==="SCRIPT")return e;if(typeof document!="undefined"){let t=document.getElementsByTagName("script");for(let n=t.length-1;n>=0;n--){let o=t[n];if(!o)continue;let i=o.getAttribute("src")||"";if(/(\/v1)?\/loader(\.umd)?\.js$/.test(i))return o}}return null}function G(e){let t=e==null?void 0:e.getAttribute("src");if(!t)return null;try{let n=typeof location!="undefined"?location.href:void 0,o=new URL(t,n),i=o.pathname.replace(/\/loader(\.umd)?\.js$/,"");return `${o.origin}${i}/widgets`}catch(n){return null}}function v(e,t){let n=e.getAttribute(t);if(n==null||n.trim()==="")return;let o=Number(n);return Number.isFinite(o)?o:void 0}function j(e,t){let n=e.getAttribute(t);if(n==null)return;let o=n.trim().toLowerCase();if(o==="true")return true;if(o==="false")return false}function V(e){let t=(e.getAttribute("data-aforo-widget")||"").trim(),n=e.getAttribute("data-tenant-slug")||e.getAttribute("data-tenant")||"",o=e.getAttribute("data-embed-key")||"",i=e.getAttribute("data-bridge-token")||void 0,a=e.getAttribute("data-layout")||void 0,r=k(e.getAttribute("data-theme-overrides")),l=e.getAttribute("data-offering-id")||void 0,u=e.getAttribute("data-subscription-id")||void 0,s=e.getAttribute("data-metric")||void 0,d=e.getAttribute("data-featured-offering-id")||void 0,m=e.getAttribute("data-mode")||void 0,M=e.getAttribute("data-return-url")||void 0,S=e.getAttribute("data-default-status")||void 0,F=e.getAttribute("data-render-mode")||void 0,_=e.getAttribute("data-locale")||void 0,C=v(e,"data-page-size"),O=v(e,"data-poll-interval-ms"),I=e.getAttribute("data-theme")||void 0,R=e.getAttribute("data-cart-type")||void 0,W=e.getAttribute("data-target-id")||void 0,H=e.getAttribute("data-cta-text")||void 0,x=e.getAttribute("data-cta-url")||void 0,P=v(e,"data-max-plans"),K=j(e,"data-show-features");return {widget:t,tenantSlug:n,embedKey:o,bridgeToken:i,layout:a,themeOverrides:r,config:{offeringId:l,subscriptionId:u,metricName:s,featuredOfferingId:d,mode:m,returnUrl:M,defaultStatus:S,renderMode:F,locale:_,pageSize:C,pollIntervalMs:O,theme:I,cartType:R,targetId:W,ctaText:H,ctaUrl:x,maxPlans:P,showFeatures:K}}}function z(e,t,n){return new Promise((o,i)=>{if(typeof document=="undefined")return i(new Error("no document"));let a=document.querySelector(`script[data-aforo-bundle="${e}"]`);if(a){if(a.dataset.aforoLoaded==="1")return o();a.addEventListener("load",()=>o()),a.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`)));return}let r=document.createElement("script");r.src=`${t}/${e}.js`,r.async=true,r.crossOrigin="anonymous",r.dataset.aforoBundle=e,n&&r.setAttribute("nonce",n),r.addEventListener("load",()=>{r.dataset.aforoLoaded="1",o();}),r.addEventListener("error",()=>i(new Error(`bundle load failed: ${e}`))),document.head.appendChild(r);})}function L(e){if(!e.__aforoEmbedReadyFired){e.__aforoEmbedReadyFired=true;try{typeof e.aforoEmbedReady=="function"&&e.aforoEmbedReady();}catch(t){typeof console!="undefined"&&console.error(`${g} aforoEmbedReady callback threw`,t);}if(typeof document!="undefined"&&typeof CustomEvent!="undefined")try{document.dispatchEvent(new CustomEvent("aforoEmbedReady"));}catch(t){}}}async function E(e){if(typeof window=="undefined"||typeof document=="undefined")return;let t=window;if(window.location.protocol!=="https:"&&window.location.hostname!=="localhost"){typeof console!="undefined"&&console.error(`${g} Refusing to mount Aforo widgets on a non-HTTPS page. Embed Plugin requires HTTPS (FR-TIER-12). Current origin: ${window.location.origin}`);return}if(t.__aforoEmbedLoaderInitialized){typeof console!="undefined"&&console.warn(`${g} Loader already initialised on this page \u2014 skipping duplicate run.`);return}t.__aforoEmbedLoaderInitialized=true,t.aforoEmbed||(t.aforoEmbed=b);let n=D(),o=(n==null?void 0:n.getAttribute("nonce"))||null,i=(e==null?void 0:e.bundleBaseUrl)||G(n)||B,a=Array.from(document.querySelectorAll("[data-aforo-widget]"));if(a.length===0){L(t);return}let r=new Map;for(let u of a){let s=(u.getAttribute("data-aforo-widget")||"").trim();if(!U.has(s)){typeof console!="undefined"&&console.warn(`${g} Unknown widget id "${s}" \u2014 skipping`);continue}let d=r.get(s);d||(d=[],r.set(s,d)),d.push(u);}let l=Array.from(r.entries()).map(async([u,s])=>{try{await z(u,i,o);for(let d of s){let m=V(d);if(!m.widget||!m.tenantSlug||!m.embedKey){typeof console!="undefined"&&console.error(`${g} Placeholder missing required attributes (data-tenant-slug + data-embed-key). Skipping element.`,d);continue}b.mount(d,m);}}catch(d){typeof console!="undefined"&&console.error(`${g} Failed to load bundle for "${u}"`,d);}});await Promise.all(l).catch(()=>{}),L(t);}typeof document!="undefined"&&document.readyState!=="loading"?Promise.resolve().then(()=>{E();}):typeof document!="undefined"&&document.addEventListener("DOMContentLoaded",()=>{E();});b._loader={bootstrap:E};
2
2
  export{b as AforoEmbed,E as bootstrap};//# sourceMappingURL=loader.mjs.map
3
3
  //# sourceMappingURL=loader.mjs.map
package/dist/sri.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
- "version": "1.0.2",
3
- "generatedAt": "2026-08-06T06:31:48.975Z",
2
+ "version": "1.0.4",
3
+ "generatedAt": "2026-08-12T07:41:16.132Z",
4
4
  "bundles": {
5
- "loader.js": "sha384-adV/66jM4GeO+0F6QuGDCP+hrZuc8SqeCHNCbfLEd+87lihORGgi0bivW8FVdupK",
6
- "widgets/checkout-flow.js": "sha384-OqmD7sCMmpG3IEWZx5L3gy7eaGtUhcthcICtKOOHZHvy/d3iXDB8YDz5EwJKJQ4R",
7
- "widgets/invoice-list.js": "sha384-VG+PfthxhO0FYDmEBv12fzgEL9sPaoT1ZUMVJc1DdJtUf9CZzUFa9Wl1WIklosed",
8
- "widgets/payment-method.js": "sha384-84SAN5cWfiA/zSjAxAyNMTnhn3np5OIqJV9nK5OIGcFYIJkv/Nv0DMO19lGwlxOn",
9
- "widgets/pricing-card.js": "sha384-mkoZr/tSjyXzKjetcqPbfZxrOFPGi50Z5ovzWjEZ/dau9wQSJU61BZ9jD3gnQOlH",
10
- "widgets/subscribe-button.js": "sha384-dlK9xpeNcEulhXaXMOb/zy+DYcJaGsy++N2NOj+Y251kNtTa/Pz6fLSmQsByg+zl",
11
- "widgets/subscription-manager.js": "sha384-iEGP3RdKjL48f/0isOohl9/wWZj5pqwYo/yLh1bz7HpFHd8QMEXM1kbMB0R1ynWV",
12
- "widgets/upgrade-cancel.js": "sha384-L9AdnlHJo88E/e6NibEbOi++l6gMib5SFu4vmmOf3GkXc5tyTQ4Fsha/1P36qw/I",
13
- "widgets/usage-meter.js": "sha384-UEFaHKHRkvu0GgrGodX44EQ2loDMT2wa/u1ilWlyxaURWNU7AeGW/EC4F0QejLrw"
5
+ "loader.js": "sha384-1PaCVhvIgReR0XDRtQjRnIqIqkg6XyUE8vGWDYwVPrIquBJ8nzLQ5YTYJGQ+gglP",
6
+ "widgets/checkout-flow.js": "sha384-xuqKo2+LKENycKs1xQRr+1MEoBNi/Gja7PTMORrJishixFMpb59od8dcBiMu3bTn",
7
+ "widgets/invoice-list.js": "sha384-BYAiV3yNVgfDWFM1oe+Nn/VPIBff2WCrclHtw1lTB/PiRC9fFRYggC8+ap2bwOBo",
8
+ "widgets/payment-method.js": "sha384-UKvAuOn02kOi05DyJrJS611LsoJjTMLC+y6rUCEHlZLZbym4k0jSp48C8YjvgDEm",
9
+ "widgets/pricing-card.js": "sha384-C1Y7pt2S0+jETNNnFoBH2rfySqbRTuB+IYA4hjeUuZKir9s+BM1Hu4g1ItSuEXlO",
10
+ "widgets/subscribe-button.js": "sha384-i7mqtIWTb2Olg2Uyw9sMAR+Jf53AGTwqIBRWb8QBGQNfy7eSsFNkF2J7yljl+BVz",
11
+ "widgets/subscription-manager.js": "sha384-rXZz4PRPYHhhfImIUVdfjtUJvJvNrfDLxfi/iV2EgSzONQ1m6Rc/lmhCsQYtyqeX",
12
+ "widgets/upgrade-cancel.js": "sha384-ZYZHCtJjqIlRn0yz2QR2pyv39C3mH4eFFQjSd/QkPUsqV3ht8ypbRkZOgi9Mmn8t",
13
+ "widgets/usage-meter.js": "sha384-8Jokz8Lmyb86GW9DBCaTJcsKF5KwCwoLOcZuTyecmMedIvvsSZQjZZtS4ou8bLN/"
14
14
  }
15
15
  }
@@ -61,7 +61,7 @@ interface SessionConfig {
61
61
  * naturally only ever set one).
62
62
  */
63
63
  magicLinkMode?: boolean;
64
- /** Override the default `https://embed.aforo.ai` origin. Tests + dev. */
64
+ /** Override the default `https://storefront.aforo.ai` origin. Tests + dev. */
65
65
  apiBaseUrl?: string;
66
66
  /** Override embed-key authenticated endpoint base. */
67
67
  embedBaseUrl?: string;
@@ -61,7 +61,7 @@ interface SessionConfig {
61
61
  * naturally only ever set one).
62
62
  */
63
63
  magicLinkMode?: boolean;
64
- /** Override the default `https://embed.aforo.ai` origin. Tests + dev. */
64
+ /** Override the default `https://storefront.aforo.ai` origin. Tests + dev. */
65
65
  apiBaseUrl?: string;
66
66
  /** Override embed-key authenticated endpoint base. */
67
67
  embedBaseUrl?: string;
@@ -27,7 +27,7 @@ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
27
27
  // src/vanilla/index.ts
28
28
 
29
29
  // src/core/version.ts
30
- var VERSION = "1.0.2";
30
+ var VERSION = "1.0.4";
31
31
 
32
32
  // src/core/AforoEmbed.ts
33
33
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -411,7 +411,7 @@ var BridgeClientError = class extends Error {
411
411
  this.retryable = retryable;
412
412
  }
413
413
  };
414
- var DEFAULT_BASE = "https://embed.aforo.ai";
414
+ var DEFAULT_BASE = "https://storefront.aforo.ai";
415
415
  var DEFAULT_TIMEOUT_MS = 15e3;
416
416
  function uuidv4() {
417
417
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
@@ -599,10 +599,23 @@ var _BridgeClient = class _BridgeClient {
599
599
  /**
600
600
  * Headless config — the PricingCard widget's primary read path.
601
601
  *
602
- * Mirrors `GET /api/v1/portal/headless/config` which returns
603
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
604
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
605
- * cache once per widget instance on the client.
602
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
603
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
604
+ * extended server-side with `offerings` + `embeddableWidget`. This was
605
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
606
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
607
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
608
+ * embed-tier fetch against that URL failed 400 "Missing tenant
609
+ * identification" by construction; this endpoint is scoped to the same
610
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
611
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
612
+ * sends is sufficient.
613
+ *
614
+ * The backend response is still a flat record (`tenantSlug,
615
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
616
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
617
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
618
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
606
619
  *
607
620
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
608
621
  * malformed JSON. Widgets fall through to their empty / error state and
@@ -617,7 +630,7 @@ var _BridgeClient = class _BridgeClient {
617
630
  }
618
631
  const target = slug || this.tenantSlug;
619
632
  if (!target) return null;
620
- const url = `${this.baseUrl}/api/v1/portal/headless/config?tenantSlug=${encodeURIComponent(target)}`;
633
+ const url = `${this.baseUrl}/api/v1/portal/embed/tenant-config/${encodeURIComponent(target)}`;
621
634
  let resp;
622
635
  try {
623
636
  resp = await this.send(url, {
@@ -630,7 +643,18 @@ var _BridgeClient = class _BridgeClient {
630
643
  if (!resp.ok) return null;
631
644
  try {
632
645
  const body = await resp.json();
633
- return body && typeof body === "object" ? body : null;
646
+ if (!body || typeof body !== "object") return null;
647
+ return {
648
+ tenantSlug: body.tenantSlug,
649
+ branding: {
650
+ primaryColor: body.primaryColor ?? null,
651
+ secondaryColor: body.secondaryColor ?? null,
652
+ logoUrl: body.logoUrl ?? null,
653
+ fontFamily: body.fontFamily ?? null
654
+ },
655
+ offerings: Array.isArray(body.offerings) ? body.offerings : [],
656
+ embeddableWidget: body.embeddableWidget ?? null
657
+ };
634
658
  } catch {
635
659
  return null;
636
660
  }
@@ -2135,9 +2159,10 @@ var AforoSession = {
2135
2159
  };
2136
2160
  sessions.set(k, entry);
2137
2161
  if (config.bridgeToken) {
2138
- entry.pendingExchange = refreshSession(entry).catch((err) => {
2139
- throw err;
2162
+ const exchangePromise = refreshSession(entry);
2163
+ exchangePromise.catch(() => {
2140
2164
  });
2165
+ entry.pendingExchange = exchangePromise;
2141
2166
  } else if (config.magicLinkMode) {
2142
2167
  const tokenInUrl = readMagicTokenFromUrl();
2143
2168
  if (tokenInUrl) {
@@ -2147,6 +2172,8 @@ var AforoSession = {
2147
2172
  pending = runMagicLinkVerify(entry, tokenInUrl).finally(() => {
2148
2173
  pendingMagicLinkVerifies.delete(dedupKey);
2149
2174
  });
2175
+ pending.catch(() => {
2176
+ });
2150
2177
  pendingMagicLinkVerifies.set(dedupKey, pending);
2151
2178
  }
2152
2179
  entry.pendingExchange = pending;
@@ -1,5 +1,5 @@
1
- export { A as AforoEmbed } from '../AforoEmbed-BqQOFsl3.cjs';
2
- import { aD as WidgetMountConfig } from '../types-Dm6cp_Cc.cjs';
1
+ export { A as AforoEmbed } from '../AforoEmbed-VYb6_GXB.cjs';
2
+ import { aD as WidgetMountConfig } from '../types-BbQw2_32.cjs';
3
3
 
4
4
  /**
5
5
  * @aforoai/storefront-widgets/vanilla — vanilla-JS adapter (FR-TIER-3,
@@ -1,5 +1,5 @@
1
- export { A as AforoEmbed } from '../AforoEmbed-CmqjlYlt.js';
2
- import { aD as WidgetMountConfig } from '../types-Dm6cp_Cc.js';
1
+ export { A as AforoEmbed } from '../AforoEmbed-BkJF1hAN.js';
2
+ import { aD as WidgetMountConfig } from '../types-BbQw2_32.js';
3
3
 
4
4
  /**
5
5
  * @aforoai/storefront-widgets/vanilla — vanilla-JS adapter (FR-TIER-3,