@aforoai/storefront-widgets 1.0.6 → 1.0.11

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/CHANGELOG.md CHANGED
@@ -8,6 +8,99 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [1.0.11] — 2026-08-30
12
+
13
+ ### Fixed
14
+
15
+ - **SC-Ticket-10: Checkout Flow's `createCart`/`getCart`/`updateCustomerDetails`/
16
+ `initiatePayment`/`confirmCart` threw "Malformed \<method\> response
17
+ (missing required fields)" on every genuinely successful backend
18
+ response.** `parseCartResponse()` (shared by the first four) and
19
+ `confirmCart()`'s own inline parser both read `cartId`/`cartType`/
20
+ `status`/`targetId` directly off the top-level JSON body instead of
21
+ unwrapping `{success, data, meta}` — same bug class as 1.0.7/1.0.9/1.0.10,
22
+ just never applied to the checkout-cart family. Live-verified against the
23
+ isopacai tenant with a real ACTIVE offering: `exchange()` itself (and the
24
+ rest of the bootstrap path) already worked fine — the reported ticket
25
+ title ("Malformed bridge exchange response") was a misdiagnosis one call
26
+ later in the same flow, exactly like SC-Ticket-5.
27
+
28
+ ## [1.0.10] — 2026-08-29
29
+
30
+ ### Fixed
31
+
32
+ - **SC-Ticket-5: Payment Method widget's initial load silently showed 0
33
+ payment methods for every customer, even ones with real saved cards.**
34
+ `fetchPaymentMethods()` and `createPaymentMethodSetupIntent()` read
35
+ response fields directly off the top-level JSON body instead of
36
+ unwrapping `{success, data, meta}` — same bug class fixed for
37
+ `fetchInvoices()` (1.0.7) and the cancel/upgrade responses (1.0.9), never
38
+ applied here. `fetchPaymentMethods()` is Pattern #18 fail-soft, so this
39
+ never threw a visible error — it just silently returned an empty list
40
+ regardless of how many cards the customer actually had on file.
41
+ (Live-verified `exchange()` itself, and the widget bundle's own deployed
42
+ copy of it, are both already correct — the ticket's reported "Malformed
43
+ bridge exchange response" text is a misdiagnosis of this unwrap bug one
44
+ call later in the same load path.)
45
+
46
+ ## [1.0.9] — 2026-08-29
47
+
48
+ ### Fixed
49
+
50
+ - **SC-Ticket-4 continued: cancellation succeeded server-side but the widget
51
+ still showed "Could not cancel."** After the 1.0.8 idempotencyKey fix,
52
+ live testing surfaced two more bugs in the same response path:
53
+ `cancelSubscription()`/`upgradeSubscription()` read fields directly off
54
+ the top-level response body instead of unwrapping `{success, data, meta}`
55
+ (same class of bug fixed for `fetchInvoices()` in 1.0.7, never applied
56
+ here), and `cancelSubscription()` additionally required `feedbackId` to
57
+ be present even though storefront-service's `/cancel` endpoint
58
+ deliberately omits it today (documented follow-up to read the V50 audit
59
+ row id back from pricing-service). Together these rejected every
60
+ genuinely successful cancellation as "malformed." `CancelResponse.feedbackId`
61
+ is now `string | null`. Live-verified: a real subscription
62
+ (`1b3af07f-d248-4860-a02b-9e3ee5601200`) was cancelled server-side
63
+ (confirmed `status: CANCELLED` in the raw API response) but the widget
64
+ still errored before this fix; re-tested after deploying 1.0.9.
65
+
66
+ ## [1.0.8] — 2026-08-29
67
+
68
+ ### Fixed
69
+
70
+ - **SC-Ticket-4: Upgrade/Cancel widget's Confirm step always failed** — the
71
+ ticket's reported symptom ("Malformed bridge exchange response") turned
72
+ out to be a misdiagnosis of a different, real bug one step later:
73
+ `cancelSubscription()` and `upgradeSubscription()` sent `idempotencyKey`
74
+ only via the `Idempotency-Key` header, but storefront-service's
75
+ `EmbedCancelRequest`/`EmbedUpgradeRequest` DTOs require it as a
76
+ `@NotBlank` BODY field too. Every real cancellation or upgrade 400'd with
77
+ "idempotencyKey is required" (or, before a separate backend fix shipped
78
+ the same day, "Invalid value 'DISCOUNT_20_PCT' for field
79
+ 'retentionOfferShown'" — the backend enum never matched the widget's own
80
+ documented `RetentionOfferShown` values). Both methods now include
81
+ `idempotencyKey` in the serialized body as well as the header.
82
+ Live-verified: a real subscription was successfully cancelled end-to-end
83
+ through this exact code path after the fix.
84
+
85
+ ## [1.0.7] — 2026-08-29
86
+
87
+ ### Fixed
88
+
89
+ - **SC-Ticket-3: Invoice List widget always showed "0 invoices" even when
90
+ the customer had real, finalized invoices.** `BridgeClient.fetchInvoices()`
91
+ read `content`/`totalElements`/`totalPages` directly off the top-level
92
+ parsed JSON body, but `GET /api/v1/portal/embed/invoices` (like every
93
+ other Aforo endpoint) wraps its payload in `{success, data, meta}` via the
94
+ platform's global `ApiResponseAdvice`. `body.content` was therefore always
95
+ `undefined`, silently falling back to an empty page — same failure mode
96
+ as the pricing-card `offerings` bug fixed in 1.0.5, just never applied
97
+ here. Live-verified: the API correctly returned 3 real invoices
98
+ (confirmed via direct backend testing) while the widget rendered "No
99
+ invoices yet." `fetchInvoicePdfUrl()` and `initiateInvoicePayment()` had
100
+ the identical bug and are fixed the same way (`raw.data ?? raw` unwrap,
101
+ matching the existing pattern already used in `exchange()` /
102
+ `fetchHeadlessConfig()` / `initiateCheckout()`).
103
+
11
104
  ## [1.0.6] — 2026-08-26
12
105
 
13
106
  ### Fixed
@@ -1,4 +1,4 @@
1
- import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-BbQw2_32.cjs';
1
+ import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-RMTEXoGw.cjs';
2
2
 
3
3
  /**
4
4
  * AforoEmbed — vanilla-JS + script-tag mount API.
@@ -1,4 +1,4 @@
1
- import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-BbQw2_32.js';
1
+ import { aD as WidgetMountConfig, Q as AforoEventType, N as AforoEventPayload, aC as WidgetId } from './types-RMTEXoGw.js';
2
2
 
3
3
  /**
4
4
  * AforoEmbed — vanilla-JS + script-tag mount API.
package/dist/index.cjs CHANGED
@@ -510,8 +510,9 @@ var _BridgeClient = class _BridgeClient {
510
510
  }
511
511
  if (!resp.ok) return emptyPage;
512
512
  try {
513
- const body = await resp.json();
514
- if (!body || typeof body !== "object") return emptyPage;
513
+ const raw = await resp.json();
514
+ if (!raw || typeof raw !== "object") return emptyPage;
515
+ const body = raw.data ?? raw;
515
516
  return {
516
517
  content: Array.isArray(body.content) ? body.content : [],
517
518
  totalElements: typeof body.totalElements === "number" && Number.isFinite(body.totalElements) ? body.totalElements : 0,
@@ -554,7 +555,8 @@ var _BridgeClient = class _BridgeClient {
554
555
  }
555
556
  if (!resp.ok) return null;
556
557
  try {
557
- const body = await resp.json();
558
+ const raw = await resp.json();
559
+ const body = raw ? raw.data ?? raw : null;
558
560
  if (!body || typeof body.downloadUrl !== "string" || body.downloadUrl.length === 0) {
559
561
  return null;
560
562
  }
@@ -643,7 +645,8 @@ var _BridgeClient = class _BridgeClient {
643
645
  }
644
646
  let body;
645
647
  try {
646
- body = await resp.json();
648
+ const raw = await resp.json();
649
+ body = raw?.data ?? raw;
647
650
  } catch {
648
651
  throw new BridgeClientError(
649
652
  "Malformed invoice-payment-initiate response (not JSON)",
@@ -954,9 +957,9 @@ var _BridgeClient = class _BridgeClient {
954
957
  if (!resp.ok) {
955
958
  throw await this.parseError(resp);
956
959
  }
957
- let body;
960
+ let raw;
958
961
  try {
959
- body = await resp.json();
962
+ raw = await resp.json();
960
963
  } catch {
961
964
  throw new BridgeClientError(
962
965
  "Malformed confirmCart response (not JSON)",
@@ -965,6 +968,7 @@ var _BridgeClient = class _BridgeClient {
965
968
  false
966
969
  );
967
970
  }
971
+ const body = raw?.data ?? raw ?? {};
968
972
  if (!body.cartId || !body.status) {
969
973
  throw new BridgeClientError(
970
974
  "Malformed confirmCart response (missing required fields)",
@@ -1029,9 +1033,9 @@ var _BridgeClient = class _BridgeClient {
1029
1033
  * undefined access.
1030
1034
  */
1031
1035
  async parseCartResponse(resp, methodName) {
1032
- let body;
1036
+ let raw;
1033
1037
  try {
1034
- body = await resp.json();
1038
+ raw = await resp.json();
1035
1039
  } catch {
1036
1040
  throw new BridgeClientError(
1037
1041
  `Malformed ${methodName} response (not JSON)`,
@@ -1040,7 +1044,8 @@ var _BridgeClient = class _BridgeClient {
1040
1044
  false
1041
1045
  );
1042
1046
  }
1043
- if (!body.cartId || !body.cartType || !body.status || !body.targetId) {
1047
+ const data = raw?.data ?? raw ?? {};
1048
+ if (!data.cartId || !data.cartType || !data.status || !data.targetId) {
1044
1049
  throw new BridgeClientError(
1045
1050
  `Malformed ${methodName} response (missing required fields)`,
1046
1051
  500,
@@ -1049,21 +1054,21 @@ var _BridgeClient = class _BridgeClient {
1049
1054
  );
1050
1055
  }
1051
1056
  return {
1052
- cartId: body.cartId,
1053
- cartType: body.cartType,
1054
- targetId: body.targetId,
1055
- status: body.status,
1056
- totalCents: typeof body.totalCents === "number" && Number.isFinite(body.totalCents) ? body.totalCents : 0,
1057
- currency: typeof body.currency === "string" ? body.currency : "USD",
1058
- gatewayProvider: body.gatewayProvider ?? null,
1059
- gatewayClientSecret: body.gatewayClientSecret ?? null,
1060
- gatewayOrderId: body.gatewayOrderId ?? null,
1061
- gatewayApprovalUrl: body.gatewayApprovalUrl ?? null,
1062
- gatewaySandboxMode: body.gatewaySandboxMode ?? null,
1063
- subscriptionId: body.subscriptionId ?? null,
1064
- invoiceId: body.invoiceId ?? null,
1065
- expiresAt: typeof body.expiresAt === "string" ? body.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1066
- completedAt: body.completedAt ?? null
1057
+ cartId: data.cartId,
1058
+ cartType: data.cartType,
1059
+ targetId: data.targetId,
1060
+ status: data.status,
1061
+ totalCents: typeof data.totalCents === "number" && Number.isFinite(data.totalCents) ? data.totalCents : 0,
1062
+ currency: typeof data.currency === "string" ? data.currency : "USD",
1063
+ gatewayProvider: data.gatewayProvider ?? null,
1064
+ gatewayClientSecret: data.gatewayClientSecret ?? null,
1065
+ gatewayOrderId: data.gatewayOrderId ?? null,
1066
+ gatewayApprovalUrl: data.gatewayApprovalUrl ?? null,
1067
+ gatewaySandboxMode: data.gatewaySandboxMode ?? null,
1068
+ subscriptionId: data.subscriptionId ?? null,
1069
+ invoiceId: data.invoiceId ?? null,
1070
+ expiresAt: typeof data.expiresAt === "string" ? data.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1071
+ completedAt: data.completedAt ?? null
1067
1072
  };
1068
1073
  }
1069
1074
  /** Public liveness probe. Returns null on failure (not an error). */
@@ -1424,14 +1429,17 @@ var _BridgeClient = class _BridgeClient {
1424
1429
  idempotencyKey,
1425
1430
  sessionJwt
1426
1431
  }),
1427
- body: JSON.stringify(request)
1432
+ // 2026-08-29 fix: same bug as cancelSubscription() below — EmbedUpgradeRequest
1433
+ // requires idempotencyKey as a @NotBlank BODY field, but this only ever sent
1434
+ // it via the Idempotency-Key header.
1435
+ body: JSON.stringify({ ...request, idempotencyKey })
1428
1436
  });
1429
1437
  if (!resp.ok) {
1430
1438
  throw await this.parseError(resp);
1431
1439
  }
1432
- let body;
1440
+ let raw;
1433
1441
  try {
1434
- body = await resp.json();
1442
+ raw = await resp.json();
1435
1443
  } catch {
1436
1444
  throw new BridgeClientError(
1437
1445
  "Malformed upgrade response (not JSON)",
@@ -1440,6 +1448,7 @@ var _BridgeClient = class _BridgeClient {
1440
1448
  false
1441
1449
  );
1442
1450
  }
1451
+ const body = raw ? raw.data ?? raw : {};
1443
1452
  if (!body.subscriptionId || !body.previousOfferingId || !body.newOfferingId || !body.status) {
1444
1453
  throw new BridgeClientError(
1445
1454
  "Malformed upgrade response (missing required fields)",
@@ -1503,14 +1512,19 @@ var _BridgeClient = class _BridgeClient {
1503
1512
  idempotencyKey,
1504
1513
  sessionJwt
1505
1514
  }),
1506
- body: JSON.stringify(request)
1515
+ // 2026-08-29 fix: EmbedCancelRequest (storefront-service) requires
1516
+ // idempotencyKey as a @NotBlank BODY field — this only ever sent it
1517
+ // via the Idempotency-Key header, so every real cancellation 400'd
1518
+ // with "idempotencyKey is required" regardless of any other field.
1519
+ // Confirmed live against production.
1520
+ body: JSON.stringify({ ...request, idempotencyKey })
1507
1521
  });
1508
1522
  if (!resp.ok) {
1509
1523
  throw await this.parseError(resp);
1510
1524
  }
1511
- let body;
1525
+ let raw;
1512
1526
  try {
1513
- body = await resp.json();
1527
+ raw = await resp.json();
1514
1528
  } catch {
1515
1529
  throw new BridgeClientError(
1516
1530
  "Malformed cancel response (not JSON)",
@@ -1519,7 +1533,8 @@ var _BridgeClient = class _BridgeClient {
1519
1533
  false
1520
1534
  );
1521
1535
  }
1522
- if (!body.subscriptionId || !body.status || !body.effectiveAt || !body.feedbackId) {
1536
+ const body = raw ? raw.data ?? raw : null;
1537
+ if (!body || !body.subscriptionId || !body.status || !body.effectiveAt) {
1523
1538
  throw new BridgeClientError(
1524
1539
  "Malformed cancel response (missing required fields)",
1525
1540
  500,
@@ -1532,7 +1547,7 @@ var _BridgeClient = class _BridgeClient {
1532
1547
  status: body.status,
1533
1548
  cancelledAt: body.cancelledAt ?? null,
1534
1549
  effectiveAt: body.effectiveAt,
1535
- feedbackId: body.feedbackId,
1550
+ feedbackId: body.feedbackId ?? null,
1536
1551
  creditNoteId: body.creditNoteId ?? null
1537
1552
  };
1538
1553
  }
@@ -1562,7 +1577,8 @@ var _BridgeClient = class _BridgeClient {
1562
1577
  if (!resp.ok) {
1563
1578
  return { methods: [], defaultMethodId: null };
1564
1579
  }
1565
- const body = await resp.json();
1580
+ const raw = await resp.json();
1581
+ const body = raw ? raw.data ?? raw : {};
1566
1582
  return {
1567
1583
  methods: Array.isArray(body.methods) ? body.methods : [],
1568
1584
  defaultMethodId: body.defaultMethodId ?? null
@@ -1592,7 +1608,8 @@ var _BridgeClient = class _BridgeClient {
1592
1608
  body: JSON.stringify({})
1593
1609
  });
1594
1610
  if (!resp.ok) return null;
1595
- const body = await resp.json();
1611
+ const raw = await resp.json();
1612
+ const body = raw ? raw.data ?? raw : {};
1596
1613
  if (!body.clientSecret) return null;
1597
1614
  return {
1598
1615
  clientSecret: body.clientSecret,
@@ -12208,7 +12225,7 @@ function ResultPanel({
12208
12225
  }
12209
12226
 
12210
12227
  // src/core/version.ts
12211
- var VERSION = "1.0.6";
12228
+ var VERSION = "1.0.11";
12212
12229
 
12213
12230
  // src/core/AforoEmbed.ts
12214
12231
  var mountedElements = /* @__PURE__ */ new WeakMap();
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-BbQw2_32.cjs';
3
- export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-BbQw2_32.cjs';
4
- export { A as AforoEmbed } from './AforoEmbed-VYb6_GXB.cjs';
2
+ import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-RMTEXoGw.cjs';
3
+ export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-RMTEXoGw.cjs';
4
+ export { A as AforoEmbed } from './AforoEmbed-BX2HPXWT.cjs';
5
5
  export { EmbedEnvironment, EmbedKey } from '@aforoai/types';
6
6
 
7
7
  /**
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-BbQw2_32.js';
3
- export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-BbQw2_32.js';
4
- export { A as AforoEmbed } from './AforoEmbed-BkJF1hAN.js';
2
+ import { T as ThemeTokenOverrides, O as OfferingPayload, H as HeadlessConfigResponse, S as SubscriptionPayload, W as WidgetErrorPayload, a as SubscriptionForOfferingResponse, C as CheckoutCartType, b as CheckoutConfirmedPayload, c as CheckoutCancelledPayload, d as CheckoutCartResponse, e as SubscriptionStatusFilter, f as SubscriptionPayloadV2, g as SubscriptionPageResponse, I as InvoiceStatusFilter, h as InvoicePayload, i as InvoicePageResponse, U as UsageMetricPayload, j as UsageThreshold, k as UsageResponse, P as PaymentMethodListResponse, A as ApplyAt, l as UpgradeCancelResultPayload, D as DemoModeBridgeProvider, m as TenantBrandKit, n as InitiateCheckoutRequest, o as InitiateCheckoutResponse, p as InvoiceListFilter, q as InvoicePdfUrlResponse, r as InitiateInvoicePaymentRequest, s as InitiateInvoicePaymentResponse, t as CreateCartRequest, u as UpdateCustomerDetailsRequest, v as InitiateCartPaymentRequest, w as ConfirmCartResponse, R as RequestMagicLinkRequest, x as RequestMagicLinkResponse, V as VerifyMagicLinkResponse, y as SubscriptionListFilter, z as PreviewChangeRequest, B as PreviewChangeResponse, E as UpgradeRequest, F as UpgradeResponse, G as CancelWithFeedbackRequest, J as CancelResponse, K as SetupIntentResponse, L as SessionConfig, M as SessionState } from './types-RMTEXoGw.js';
3
+ export { N as AforoEventPayload, Q as AforoEventType, X as CancelReason, Y as CheckoutBillingAddress, Z as CheckoutCartErrorResponse, _ as CheckoutCartStatus, $ as CheckoutCustomerDetailsSubmittedPayload, a0 as CheckoutExpiredPayload, a1 as CheckoutFlowPhase, a2 as CheckoutPaymentCompletedPayload, a3 as CheckoutPaymentInitiatedPayload, a4 as CheckoutPaymentProvider, a5 as CheckoutStepChangedPayload, a6 as ConsentState, a7 as FeaturePayload, a8 as HeadlessBrandingPayload, a9 as InvoiceDownloadedPayload, aa as InvoiceExpandedPayload, ab as InvoiceFilterChangedPayload, ac as InvoicePaidPayload, ad as InvoicePayRequestedPayload, ae as InvoiceSearchChangedPayload, af as InvoiceStatus, ag as InvoiceTypeKind, ah as LiveSubscriptionStatus, ai as MagicLinkFailureCode, aj as OfferingSummary, ak as RatePlanPayload, al as RetentionOfferShown, am as RetentionOutcome, an as SubscriptionCancelRequestedPayload, ao as SubscriptionChangeType, ap as SubscriptionClickedPayload, aq as SubscriptionFilterChangedPayload, ar as SubscriptionStatus, as as SubscriptionUpgradeRequestedPayload, at as ThemeTokens, au as UpgradeCancelAbandonedPayload, av as UpgradeCancelCompletedPayload, aw as UpgradeCancelDeflectionOfferAcceptedPayload, ax as UpgradeCancelDeflectionOfferShownPayload, ay as UpgradeCancelPreviewFetchedPayload, az as UpgradeCancelStepChangedPayload, aA as UsageMetricClickedPayload, aB as UsageThresholdReachedPayload, aC as WidgetId, aD as WidgetMountConfig } from './types-RMTEXoGw.js';
4
+ export { A as AforoEmbed } from './AforoEmbed-PsTY7zh0.js';
5
5
  export { EmbedEnvironment, EmbedKey } from '@aforoai/types';
6
6
 
7
7
  /**
package/dist/index.mjs CHANGED
@@ -488,8 +488,9 @@ var _BridgeClient = class _BridgeClient {
488
488
  }
489
489
  if (!resp.ok) return emptyPage;
490
490
  try {
491
- const body = await resp.json();
492
- if (!body || typeof body !== "object") return emptyPage;
491
+ const raw = await resp.json();
492
+ if (!raw || typeof raw !== "object") return emptyPage;
493
+ const body = raw.data ?? raw;
493
494
  return {
494
495
  content: Array.isArray(body.content) ? body.content : [],
495
496
  totalElements: typeof body.totalElements === "number" && Number.isFinite(body.totalElements) ? body.totalElements : 0,
@@ -532,7 +533,8 @@ var _BridgeClient = class _BridgeClient {
532
533
  }
533
534
  if (!resp.ok) return null;
534
535
  try {
535
- const body = await resp.json();
536
+ const raw = await resp.json();
537
+ const body = raw ? raw.data ?? raw : null;
536
538
  if (!body || typeof body.downloadUrl !== "string" || body.downloadUrl.length === 0) {
537
539
  return null;
538
540
  }
@@ -621,7 +623,8 @@ var _BridgeClient = class _BridgeClient {
621
623
  }
622
624
  let body;
623
625
  try {
624
- body = await resp.json();
626
+ const raw = await resp.json();
627
+ body = raw?.data ?? raw;
625
628
  } catch {
626
629
  throw new BridgeClientError(
627
630
  "Malformed invoice-payment-initiate response (not JSON)",
@@ -932,9 +935,9 @@ var _BridgeClient = class _BridgeClient {
932
935
  if (!resp.ok) {
933
936
  throw await this.parseError(resp);
934
937
  }
935
- let body;
938
+ let raw;
936
939
  try {
937
- body = await resp.json();
940
+ raw = await resp.json();
938
941
  } catch {
939
942
  throw new BridgeClientError(
940
943
  "Malformed confirmCart response (not JSON)",
@@ -943,6 +946,7 @@ var _BridgeClient = class _BridgeClient {
943
946
  false
944
947
  );
945
948
  }
949
+ const body = raw?.data ?? raw ?? {};
946
950
  if (!body.cartId || !body.status) {
947
951
  throw new BridgeClientError(
948
952
  "Malformed confirmCart response (missing required fields)",
@@ -1007,9 +1011,9 @@ var _BridgeClient = class _BridgeClient {
1007
1011
  * undefined access.
1008
1012
  */
1009
1013
  async parseCartResponse(resp, methodName) {
1010
- let body;
1014
+ let raw;
1011
1015
  try {
1012
- body = await resp.json();
1016
+ raw = await resp.json();
1013
1017
  } catch {
1014
1018
  throw new BridgeClientError(
1015
1019
  `Malformed ${methodName} response (not JSON)`,
@@ -1018,7 +1022,8 @@ var _BridgeClient = class _BridgeClient {
1018
1022
  false
1019
1023
  );
1020
1024
  }
1021
- if (!body.cartId || !body.cartType || !body.status || !body.targetId) {
1025
+ const data = raw?.data ?? raw ?? {};
1026
+ if (!data.cartId || !data.cartType || !data.status || !data.targetId) {
1022
1027
  throw new BridgeClientError(
1023
1028
  `Malformed ${methodName} response (missing required fields)`,
1024
1029
  500,
@@ -1027,21 +1032,21 @@ var _BridgeClient = class _BridgeClient {
1027
1032
  );
1028
1033
  }
1029
1034
  return {
1030
- cartId: body.cartId,
1031
- cartType: body.cartType,
1032
- targetId: body.targetId,
1033
- status: body.status,
1034
- totalCents: typeof body.totalCents === "number" && Number.isFinite(body.totalCents) ? body.totalCents : 0,
1035
- currency: typeof body.currency === "string" ? body.currency : "USD",
1036
- gatewayProvider: body.gatewayProvider ?? null,
1037
- gatewayClientSecret: body.gatewayClientSecret ?? null,
1038
- gatewayOrderId: body.gatewayOrderId ?? null,
1039
- gatewayApprovalUrl: body.gatewayApprovalUrl ?? null,
1040
- gatewaySandboxMode: body.gatewaySandboxMode ?? null,
1041
- subscriptionId: body.subscriptionId ?? null,
1042
- invoiceId: body.invoiceId ?? null,
1043
- expiresAt: typeof body.expiresAt === "string" ? body.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1044
- completedAt: body.completedAt ?? null
1035
+ cartId: data.cartId,
1036
+ cartType: data.cartType,
1037
+ targetId: data.targetId,
1038
+ status: data.status,
1039
+ totalCents: typeof data.totalCents === "number" && Number.isFinite(data.totalCents) ? data.totalCents : 0,
1040
+ currency: typeof data.currency === "string" ? data.currency : "USD",
1041
+ gatewayProvider: data.gatewayProvider ?? null,
1042
+ gatewayClientSecret: data.gatewayClientSecret ?? null,
1043
+ gatewayOrderId: data.gatewayOrderId ?? null,
1044
+ gatewayApprovalUrl: data.gatewayApprovalUrl ?? null,
1045
+ gatewaySandboxMode: data.gatewaySandboxMode ?? null,
1046
+ subscriptionId: data.subscriptionId ?? null,
1047
+ invoiceId: data.invoiceId ?? null,
1048
+ expiresAt: typeof data.expiresAt === "string" ? data.expiresAt : (/* @__PURE__ */ new Date(0)).toISOString(),
1049
+ completedAt: data.completedAt ?? null
1045
1050
  };
1046
1051
  }
1047
1052
  /** Public liveness probe. Returns null on failure (not an error). */
@@ -1402,14 +1407,17 @@ var _BridgeClient = class _BridgeClient {
1402
1407
  idempotencyKey,
1403
1408
  sessionJwt
1404
1409
  }),
1405
- body: JSON.stringify(request)
1410
+ // 2026-08-29 fix: same bug as cancelSubscription() below — EmbedUpgradeRequest
1411
+ // requires idempotencyKey as a @NotBlank BODY field, but this only ever sent
1412
+ // it via the Idempotency-Key header.
1413
+ body: JSON.stringify({ ...request, idempotencyKey })
1406
1414
  });
1407
1415
  if (!resp.ok) {
1408
1416
  throw await this.parseError(resp);
1409
1417
  }
1410
- let body;
1418
+ let raw;
1411
1419
  try {
1412
- body = await resp.json();
1420
+ raw = await resp.json();
1413
1421
  } catch {
1414
1422
  throw new BridgeClientError(
1415
1423
  "Malformed upgrade response (not JSON)",
@@ -1418,6 +1426,7 @@ var _BridgeClient = class _BridgeClient {
1418
1426
  false
1419
1427
  );
1420
1428
  }
1429
+ const body = raw ? raw.data ?? raw : {};
1421
1430
  if (!body.subscriptionId || !body.previousOfferingId || !body.newOfferingId || !body.status) {
1422
1431
  throw new BridgeClientError(
1423
1432
  "Malformed upgrade response (missing required fields)",
@@ -1481,14 +1490,19 @@ var _BridgeClient = class _BridgeClient {
1481
1490
  idempotencyKey,
1482
1491
  sessionJwt
1483
1492
  }),
1484
- body: JSON.stringify(request)
1493
+ // 2026-08-29 fix: EmbedCancelRequest (storefront-service) requires
1494
+ // idempotencyKey as a @NotBlank BODY field — this only ever sent it
1495
+ // via the Idempotency-Key header, so every real cancellation 400'd
1496
+ // with "idempotencyKey is required" regardless of any other field.
1497
+ // Confirmed live against production.
1498
+ body: JSON.stringify({ ...request, idempotencyKey })
1485
1499
  });
1486
1500
  if (!resp.ok) {
1487
1501
  throw await this.parseError(resp);
1488
1502
  }
1489
- let body;
1503
+ let raw;
1490
1504
  try {
1491
- body = await resp.json();
1505
+ raw = await resp.json();
1492
1506
  } catch {
1493
1507
  throw new BridgeClientError(
1494
1508
  "Malformed cancel response (not JSON)",
@@ -1497,7 +1511,8 @@ var _BridgeClient = class _BridgeClient {
1497
1511
  false
1498
1512
  );
1499
1513
  }
1500
- if (!body.subscriptionId || !body.status || !body.effectiveAt || !body.feedbackId) {
1514
+ const body = raw ? raw.data ?? raw : null;
1515
+ if (!body || !body.subscriptionId || !body.status || !body.effectiveAt) {
1501
1516
  throw new BridgeClientError(
1502
1517
  "Malformed cancel response (missing required fields)",
1503
1518
  500,
@@ -1510,7 +1525,7 @@ var _BridgeClient = class _BridgeClient {
1510
1525
  status: body.status,
1511
1526
  cancelledAt: body.cancelledAt ?? null,
1512
1527
  effectiveAt: body.effectiveAt,
1513
- feedbackId: body.feedbackId,
1528
+ feedbackId: body.feedbackId ?? null,
1514
1529
  creditNoteId: body.creditNoteId ?? null
1515
1530
  };
1516
1531
  }
@@ -1540,7 +1555,8 @@ var _BridgeClient = class _BridgeClient {
1540
1555
  if (!resp.ok) {
1541
1556
  return { methods: [], defaultMethodId: null };
1542
1557
  }
1543
- const body = await resp.json();
1558
+ const raw = await resp.json();
1559
+ const body = raw ? raw.data ?? raw : {};
1544
1560
  return {
1545
1561
  methods: Array.isArray(body.methods) ? body.methods : [],
1546
1562
  defaultMethodId: body.defaultMethodId ?? null
@@ -1570,7 +1586,8 @@ var _BridgeClient = class _BridgeClient {
1570
1586
  body: JSON.stringify({})
1571
1587
  });
1572
1588
  if (!resp.ok) return null;
1573
- const body = await resp.json();
1589
+ const raw = await resp.json();
1590
+ const body = raw ? raw.data ?? raw : {};
1574
1591
  if (!body.clientSecret) return null;
1575
1592
  return {
1576
1593
  clientSecret: body.clientSecret,
@@ -12186,7 +12203,7 @@ function ResultPanel({
12186
12203
  }
12187
12204
 
12188
12205
  // src/core/version.ts
12189
- var VERSION = "1.0.6";
12206
+ var VERSION = "1.0.11";
12190
12207
 
12191
12208
  // src/core/AforoEmbed.ts
12192
12209
  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.6";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.11";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