@aforoai/storefront-widgets 1.0.3 → 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.
package/dist/index.cjs CHANGED
@@ -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
  }
@@ -12151,7 +12175,7 @@ function ResultPanel({
12151
12175
  }
12152
12176
 
12153
12177
  // src/core/version.ts
12154
- var VERSION = "1.0.3";
12178
+ var VERSION = "1.0.4";
12155
12179
 
12156
12180
  // src/core/AforoEmbed.ts
12157
12181
  var mountedElements = /* @__PURE__ */ new WeakMap();
package/dist/index.d.cts CHANGED
@@ -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:
@@ -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
@@ -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:
@@ -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
@@ -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
  }
@@ -12129,7 +12153,7 @@ function ResultPanel({
12129
12153
  }
12130
12154
 
12131
12155
  // src/core/version.ts
12132
- var VERSION = "1.0.3";
12156
+ var VERSION = "1.0.4";
12133
12157
 
12134
12158
  // src/core/AforoEmbed.ts
12135
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.3";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.3";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.3",
3
- "generatedAt": "2026-08-06T10:04:55.060Z",
2
+ "version": "1.0.4",
3
+ "generatedAt": "2026-08-12T07:41:16.132Z",
4
4
  "bundles": {
5
- "loader.js": "sha384-y68Q4ZI8cjVROhc1u3KvVsUq1fWZLIMTyGZprznk6+dqlO9wKZXOQMJXnpkZNcTa",
6
- "widgets/checkout-flow.js": "sha384-TR8WKd8KcXp8X5Jn8URZRuBZVy8LWz8Yd34sqsE2i40VjgyxU1Z6qSlJIXjpCVWs",
7
- "widgets/invoice-list.js": "sha384-ccLrb3k9pXScTDTnUO8d1CXtrOO/63+KVCvlx9C7R8R8FukSDL+katg1PfYUoEru",
8
- "widgets/payment-method.js": "sha384-DjvIF+8Uj0Xf6D6LRiXWwhLNUsXv+NzhZNKchKwUWBhXLCzGkoUZMoHN18bs/9GZ",
9
- "widgets/pricing-card.js": "sha384-mWYYVjNqJ42wBqM3noL0DqT6QfZ6vUh3ZdBJrSTTVg+KbZg8VW+RMN3wqNBWwaQn",
10
- "widgets/subscribe-button.js": "sha384-nrPRcguVwH3jzMa2opsjHBx1lIn6Tr8jhbEgoBHG/notld10qgTUHHD8C4lb8iY+",
11
- "widgets/subscription-manager.js": "sha384-JFYT9O7rioOXEQBLQjikWwbD7l+cmtpx9oGM8kNaYWqZ1q6dpZPcPwwe0jFOAz6j",
12
- "widgets/upgrade-cancel.js": "sha384-fLGAjU4RoV3XsMVd/BCPcXJiJSZjT41ZZk2wIBfCrEJZvE/gflHsmgyXW02pD2b5",
13
- "widgets/usage-meter.js": "sha384-Mkfm+HYrr/ncJgAa3J/1kdVgDdf5JbOU+m8JAXQjfzqGq8epXLYLm+e6qPQf9LPf"
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
  }
@@ -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.3";
30
+ var VERSION = "1.0.4";
31
31
 
32
32
  // src/core/AforoEmbed.ts
33
33
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -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
  }
@@ -5,7 +5,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  // src/vanilla/index.ts
6
6
 
7
7
  // src/core/version.ts
8
- var VERSION = "1.0.3";
8
+ var VERSION = "1.0.4";
9
9
 
10
10
  // src/core/AforoEmbed.ts
11
11
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -577,10 +577,23 @@ var _BridgeClient = class _BridgeClient {
577
577
  /**
578
578
  * Headless config — the PricingCard widget's primary read path.
579
579
  *
580
- * Mirrors `GET /api/v1/portal/headless/config` which returns
581
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
582
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
583
- * cache once per widget instance on the client.
580
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
581
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
582
+ * extended server-side with `offerings` + `embeddableWidget`. This was
583
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
584
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
585
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
586
+ * embed-tier fetch against that URL failed 400 "Missing tenant
587
+ * identification" by construction; this endpoint is scoped to the same
588
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
589
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
590
+ * sends is sufficient.
591
+ *
592
+ * The backend response is still a flat record (`tenantSlug,
593
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
594
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
595
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
596
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
584
597
  *
585
598
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
586
599
  * malformed JSON. Widgets fall through to their empty / error state and
@@ -595,7 +608,7 @@ var _BridgeClient = class _BridgeClient {
595
608
  }
596
609
  const target = slug || this.tenantSlug;
597
610
  if (!target) return null;
598
- const url = `${this.baseUrl}/api/v1/portal/headless/config?tenantSlug=${encodeURIComponent(target)}`;
611
+ const url = `${this.baseUrl}/api/v1/portal/embed/tenant-config/${encodeURIComponent(target)}`;
599
612
  let resp;
600
613
  try {
601
614
  resp = await this.send(url, {
@@ -608,7 +621,18 @@ var _BridgeClient = class _BridgeClient {
608
621
  if (!resp.ok) return null;
609
622
  try {
610
623
  const body = await resp.json();
611
- return body && typeof body === "object" ? body : null;
624
+ if (!body || typeof body !== "object") return null;
625
+ return {
626
+ tenantSlug: body.tenantSlug,
627
+ branding: {
628
+ primaryColor: body.primaryColor ?? null,
629
+ secondaryColor: body.secondaryColor ?? null,
630
+ logoUrl: body.logoUrl ?? null,
631
+ fontFamily: body.fontFamily ?? null
632
+ },
633
+ offerings: Array.isArray(body.offerings) ? body.offerings : [],
634
+ embeddableWidget: body.embeddableWidget ?? null
635
+ };
612
636
  } catch {
613
637
  return null;
614
638
  }
@@ -28,7 +28,7 @@ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
28
28
  // src/vue/index.ts
29
29
 
30
30
  // src/core/version.ts
31
- var VERSION = "1.0.3";
31
+ var VERSION = "1.0.4";
32
32
 
33
33
  // src/core/AforoEmbed.ts
34
34
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -600,10 +600,23 @@ var _BridgeClient = class _BridgeClient {
600
600
  /**
601
601
  * Headless config — the PricingCard widget's primary read path.
602
602
  *
603
- * Mirrors `GET /api/v1/portal/headless/config` which returns
604
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
605
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
606
- * cache once per widget instance on the client.
603
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
604
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
605
+ * extended server-side with `offerings` + `embeddableWidget`. This was
606
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
607
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
608
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
609
+ * embed-tier fetch against that URL failed 400 "Missing tenant
610
+ * identification" by construction; this endpoint is scoped to the same
611
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
612
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
613
+ * sends is sufficient.
614
+ *
615
+ * The backend response is still a flat record (`tenantSlug,
616
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
617
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
618
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
619
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
607
620
  *
608
621
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
609
622
  * malformed JSON. Widgets fall through to their empty / error state and
@@ -618,7 +631,7 @@ var _BridgeClient = class _BridgeClient {
618
631
  }
619
632
  const target = slug || this.tenantSlug;
620
633
  if (!target) return null;
621
- const url = `${this.baseUrl}/api/v1/portal/headless/config?tenantSlug=${encodeURIComponent(target)}`;
634
+ const url = `${this.baseUrl}/api/v1/portal/embed/tenant-config/${encodeURIComponent(target)}`;
622
635
  let resp;
623
636
  try {
624
637
  resp = await this.send(url, {
@@ -631,7 +644,18 @@ var _BridgeClient = class _BridgeClient {
631
644
  if (!resp.ok) return null;
632
645
  try {
633
646
  const body = await resp.json();
634
- return body && typeof body === "object" ? body : null;
647
+ if (!body || typeof body !== "object") return null;
648
+ return {
649
+ tenantSlug: body.tenantSlug,
650
+ branding: {
651
+ primaryColor: body.primaryColor ?? null,
652
+ secondaryColor: body.secondaryColor ?? null,
653
+ logoUrl: body.logoUrl ?? null,
654
+ fontFamily: body.fontFamily ?? null
655
+ },
656
+ offerings: Array.isArray(body.offerings) ? body.offerings : [],
657
+ embeddableWidget: body.embeddableWidget ?? null
658
+ };
635
659
  } catch {
636
660
  return null;
637
661
  }
@@ -6,7 +6,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  // src/vue/index.ts
7
7
 
8
8
  // src/core/version.ts
9
- var VERSION = "1.0.3";
9
+ var VERSION = "1.0.4";
10
10
 
11
11
  // src/core/AforoEmbed.ts
12
12
  var mountedElements = /* @__PURE__ */ new WeakMap();
@@ -578,10 +578,23 @@ var _BridgeClient = class _BridgeClient {
578
578
  /**
579
579
  * Headless config — the PricingCard widget's primary read path.
580
580
  *
581
- * Mirrors `GET /api/v1/portal/headless/config` which returns
582
- * `{branding, offerings, ratePlans, themeTokens, customPages, ...}`
583
- * denormalized JSON. The endpoint is 60s Caffeine-cached server-side; we
584
- * cache once per widget instance on the client.
581
+ * Hits `GET /api/v1/portal/embed/tenant-config/{slug}` the SAME
582
+ * embed-key-authenticated endpoint {@link getTenantBrandKit} uses, now
583
+ * extended server-side with `offerings` + `embeddableWidget`. This was
584
+ * previously wired to `GET /api/v1/portal/headless/config`, an unrelated
585
+ * T6 Headless-tier endpoint that requires `X-Storefront-Key`/
586
+ * `X-Tenant-Id` auth — headers the embed key flow never sends. Every
587
+ * embed-tier fetch against that URL failed 400 "Missing tenant
588
+ * identification" by construction; this endpoint is scoped to the same
589
+ * `EmbedKeyAuthFilter` gate as the rest of the embed plane, so the
590
+ * `Authorization: Bearer <embed_key>` header `buildHeaders()` already
591
+ * sends is sufficient.
592
+ *
593
+ * The backend response is still a flat record (`tenantSlug,
594
+ * primaryColor, secondaryColor, logoUrl, fontFamily, offerings,
595
+ * embeddableWidget`) — kept flat so `getTenantBrandKit()`'s existing
596
+ * consumers (the ThemeReader cascade) are unaffected. This method nests
597
+ * the branding fields into the shape `HeadlessConfigResponse` expects.
585
598
  *
586
599
  * Pattern #18 fail-soft — returns `null` on transport failure, 404, or
587
600
  * malformed JSON. Widgets fall through to their empty / error state and
@@ -596,7 +609,7 @@ var _BridgeClient = class _BridgeClient {
596
609
  }
597
610
  const target = slug || this.tenantSlug;
598
611
  if (!target) return null;
599
- const url = `${this.baseUrl}/api/v1/portal/headless/config?tenantSlug=${encodeURIComponent(target)}`;
612
+ const url = `${this.baseUrl}/api/v1/portal/embed/tenant-config/${encodeURIComponent(target)}`;
600
613
  let resp;
601
614
  try {
602
615
  resp = await this.send(url, {
@@ -609,7 +622,18 @@ var _BridgeClient = class _BridgeClient {
609
622
  if (!resp.ok) return null;
610
623
  try {
611
624
  const body = await resp.json();
612
- return body && typeof body === "object" ? body : null;
625
+ if (!body || typeof body !== "object") return null;
626
+ return {
627
+ tenantSlug: body.tenantSlug,
628
+ branding: {
629
+ primaryColor: body.primaryColor ?? null,
630
+ secondaryColor: body.secondaryColor ?? null,
631
+ logoUrl: body.logoUrl ?? null,
632
+ fontFamily: body.fontFamily ?? null
633
+ },
634
+ offerings: Array.isArray(body.offerings) ? body.offerings : [],
635
+ embeddableWidget: body.embeddableWidget ?? null
636
+ };
613
637
  } catch {
614
638
  return null;
615
639
  }