@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 +31 -7
- package/dist/index.d.cts +18 -5
- package/dist/index.d.ts +18 -5
- package/dist/index.mjs +31 -7
- package/dist/loader.js +1 -1
- package/dist/loader.mjs +1 -1
- package/dist/sri.json +11 -11
- package/dist/vanilla/index.cjs +31 -7
- package/dist/vanilla/index.mjs +31 -7
- package/dist/vue/index.cjs +31 -7
- package/dist/vue/index.mjs +31 -7
- package/dist/widgets/checkout-flow.js +5 -5
- package/dist/widgets/invoice-list.js +6 -6
- package/dist/widgets/payment-method.js +2 -2
- package/dist/widgets/pricing-card.js +7 -7
- package/dist/widgets/subscribe-button.js +8 -8
- package/dist/widgets/subscription-manager.js +5 -5
- package/dist/widgets/upgrade-cancel.js +6 -6
- package/dist/widgets/usage-meter.js +5 -5
- package/loader.sri.txt +1 -1
- package/package.json +1 -1
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
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
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/
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
*
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
*
|
|
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
|
|
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
|
-
*
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
*
|
|
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
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
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/
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
"generatedAt": "2026-08-
|
|
2
|
+
"version": "1.0.4",
|
|
3
|
+
"generatedAt": "2026-08-12T07:41:16.132Z",
|
|
4
4
|
"bundles": {
|
|
5
|
-
"loader.js": "sha384-
|
|
6
|
-
"widgets/checkout-flow.js": "sha384-
|
|
7
|
-
"widgets/invoice-list.js": "sha384-
|
|
8
|
-
"widgets/payment-method.js": "sha384-
|
|
9
|
-
"widgets/pricing-card.js": "sha384-
|
|
10
|
-
"widgets/subscribe-button.js": "sha384-
|
|
11
|
-
"widgets/subscription-manager.js": "sha384-
|
|
12
|
-
"widgets/upgrade-cancel.js": "sha384-
|
|
13
|
-
"widgets/usage-meter.js": "sha384-
|
|
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
|
}
|
package/dist/vanilla/index.cjs
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
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/
|
|
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
|
-
|
|
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
|
}
|
package/dist/vanilla/index.mjs
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
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/
|
|
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
|
-
|
|
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
|
}
|
package/dist/vue/index.cjs
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
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/
|
|
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
|
-
|
|
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
|
}
|
package/dist/vue/index.mjs
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
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/
|
|
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
|
-
|
|
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
|
}
|