brainerce 1.47.1 → 1.47.3

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.mjs CHANGED
@@ -585,6 +585,7 @@ var BrainerceClient = class {
585
585
  this.proxyMode = options.proxyMode || false;
586
586
  this.analyticsBaseUrl = this.resolveAnalyticsBaseUrl(options.analyticsBaseUrl, resolvedBase);
587
587
  this.onAuthError = options.onAuthError;
588
+ this.onCartReset = options.onCartReset;
588
589
  this.hydrateSessionCart();
589
590
  this.detectRecoverCartFromUrl();
590
591
  }
@@ -4183,14 +4184,17 @@ var BrainerceClient = class {
4183
4184
  const migrated = await this.migrateLocalCartToSession();
4184
4185
  if (migrated) return migrated;
4185
4186
  if (this.sessionCartId && this.sessionToken) {
4187
+ const previousCartId = this.sessionCartId;
4186
4188
  try {
4187
4189
  const cart2 = await this.getCart(this.sessionCartId);
4188
4190
  if (cart2.status === "ACTIVE") {
4189
4191
  return cart2;
4190
4192
  }
4191
4193
  this.clearSessionCart();
4194
+ this.onCartReset?.({ previousCartId, reason: "not_active" });
4192
4195
  } catch {
4193
4196
  this.clearSessionCart();
4197
+ this.onCartReset?.({ previousCartId, reason: "not_found" });
4194
4198
  }
4195
4199
  }
4196
4200
  if (this.sessionToken) {
@@ -6419,9 +6423,9 @@ var BrainerceClient = class {
6419
6423
  );
6420
6424
  }
6421
6425
  // -------------------- Loyalty --------------------
6422
- // Storefront-mode only (storeId + customerToken). The backend exposes loyalty
6423
- // solely under /api/stores/:storeId/loyalty there is no vibe-coded route, so
6424
- // these do NOT branch on isVibeCodedMode() (that would 404 silently).
6426
+ // Available in both storefront mode (storeId + customerToken) and
6427
+ // vibe-coded mode (salesChannelId + customerToken) Phase 5 added the
6428
+ // /api/vc/:connectionId/loyalty/* routes mirroring /api/stores/:storeId/loyalty.
6425
6429
  /**
6426
6430
  * Get the logged-in customer's loyalty status: enrollment, points balance,
6427
6431
  * lifetime earned, the program's display config, earned milestone `badges`,
@@ -6445,10 +6449,16 @@ var BrainerceClient = class {
6445
6449
  401
6446
6450
  );
6447
6451
  }
6452
+ if (this.isVibeCodedMode()) {
6453
+ return this.vibeCodedRequest("GET", "/loyalty/me");
6454
+ }
6448
6455
  if (this.storeId && !this.apiKey) {
6449
6456
  return this.storefrontRequest("GET", "/loyalty/me");
6450
6457
  }
6451
- throw new BrainerceError("getLoyaltyStatus is only available in storefront mode", 400);
6458
+ throw new BrainerceError(
6459
+ "getLoyaltyStatus is only available in vibe-coded or storefront mode",
6460
+ 400
6461
+ );
6452
6462
  }
6453
6463
  /**
6454
6464
  * Enroll the logged-in customer in the store's loyalty program (requires
@@ -6467,10 +6477,16 @@ var BrainerceClient = class {
6467
6477
  401
6468
6478
  );
6469
6479
  }
6480
+ if (this.isVibeCodedMode()) {
6481
+ return this.vibeCodedRequest("POST", "/loyalty/enroll");
6482
+ }
6470
6483
  if (this.storeId && !this.apiKey) {
6471
6484
  return this.storefrontRequest("POST", "/loyalty/enroll");
6472
6485
  }
6473
- throw new BrainerceError("enrollInLoyalty is only available in storefront mode", 400);
6486
+ throw new BrainerceError(
6487
+ "enrollInLoyalty is only available in vibe-coded or storefront mode",
6488
+ 400
6489
+ );
6474
6490
  }
6475
6491
  /**
6476
6492
  * List the rewards the customer can redeem points for (active rewards, cheapest
@@ -6489,10 +6505,16 @@ var BrainerceClient = class {
6489
6505
  401
6490
6506
  );
6491
6507
  }
6508
+ if (this.isVibeCodedMode()) {
6509
+ return this.vibeCodedRequest("GET", "/loyalty/rewards/available");
6510
+ }
6492
6511
  if (this.storeId && !this.apiKey) {
6493
6512
  return this.storefrontRequest("GET", "/loyalty/rewards/available");
6494
6513
  }
6495
- throw new BrainerceError("getAvailableRewards is only available in storefront mode", 400);
6514
+ throw new BrainerceError(
6515
+ "getAvailableRewards is only available in vibe-coded or storefront mode",
6516
+ 400
6517
+ );
6496
6518
  }
6497
6519
  /**
6498
6520
  * Redeem a reward: spends the customer's points and mints a one-time coupon
@@ -6512,10 +6534,16 @@ var BrainerceClient = class {
6512
6534
  401
6513
6535
  );
6514
6536
  }
6537
+ if (this.isVibeCodedMode()) {
6538
+ return this.vibeCodedRequest("POST", "/loyalty/redeem", { rewardId });
6539
+ }
6515
6540
  if (this.storeId && !this.apiKey) {
6516
6541
  return this.storefrontRequest("POST", "/loyalty/redeem", { rewardId });
6517
6542
  }
6518
- throw new BrainerceError("redeemLoyaltyReward is only available in storefront mode", 400);
6543
+ throw new BrainerceError(
6544
+ "redeemLoyaltyReward is only available in vibe-coded or storefront mode",
6545
+ 400
6546
+ );
6519
6547
  }
6520
6548
  /**
6521
6549
  * Report a social share, granting the SOCIAL_SHARE earning-rule bonus if the
@@ -6535,6 +6563,13 @@ var BrainerceClient = class {
6535
6563
  401
6536
6564
  );
6537
6565
  }
6566
+ if (this.isVibeCodedMode()) {
6567
+ return this.vibeCodedRequest(
6568
+ "POST",
6569
+ "/loyalty/social-share",
6570
+ platform ? { platform } : {}
6571
+ );
6572
+ }
6538
6573
  if (this.storeId && !this.apiKey) {
6539
6574
  return this.storefrontRequest(
6540
6575
  "POST",
@@ -6542,7 +6577,10 @@ var BrainerceClient = class {
6542
6577
  platform ? { platform } : {}
6543
6578
  );
6544
6579
  }
6545
- throw new BrainerceError("reportSocialShare is only available in storefront mode", 400);
6580
+ throw new BrainerceError(
6581
+ "reportSocialShare is only available in vibe-coded or storefront mode",
6582
+ 400
6583
+ );
6546
6584
  }
6547
6585
  /**
6548
6586
  * Public referral-link lookup: who referred the visitor and what welcome
@@ -6561,12 +6599,20 @@ var BrainerceClient = class {
6561
6599
  * ```
6562
6600
  */
6563
6601
  async getReferralInfo(code) {
6602
+ if (this.isVibeCodedMode()) {
6603
+ return this.vibeCodedRequest("GET", "/loyalty/referral-info", void 0, {
6604
+ code
6605
+ });
6606
+ }
6564
6607
  if (this.storeId && !this.apiKey) {
6565
6608
  return this.storefrontRequest("GET", "/loyalty/referral-info", void 0, {
6566
6609
  code
6567
6610
  });
6568
6611
  }
6569
- throw new BrainerceError("getReferralInfo is only available in storefront mode", 400);
6612
+ throw new BrainerceError(
6613
+ "getReferralInfo is only available in vibe-coded or storefront mode",
6614
+ 400
6615
+ );
6570
6616
  }
6571
6617
  /**
6572
6618
  * AI-recommended reward for the logged-in customer — "recommended for you"
@@ -6590,13 +6636,22 @@ var BrainerceClient = class {
6590
6636
  401
6591
6637
  );
6592
6638
  }
6639
+ if (this.isVibeCodedMode()) {
6640
+ return this.vibeCodedRequest(
6641
+ "GET",
6642
+ "/loyalty/rewards/recommended"
6643
+ );
6644
+ }
6593
6645
  if (this.storeId && !this.apiKey) {
6594
6646
  return this.storefrontRequest(
6595
6647
  "GET",
6596
6648
  "/loyalty/rewards/recommended"
6597
6649
  );
6598
6650
  }
6599
- throw new BrainerceError("getRecommendedReward is only available in storefront mode", 400);
6651
+ throw new BrainerceError(
6652
+ "getRecommendedReward is only available in vibe-coded or storefront mode",
6653
+ 400
6654
+ );
6600
6655
  }
6601
6656
  /**
6602
6657
  * List the paid membership plans the customer can subscribe to (requires
@@ -6615,10 +6670,16 @@ var BrainerceClient = class {
6615
6670
  401
6616
6671
  );
6617
6672
  }
6673
+ if (this.isVibeCodedMode()) {
6674
+ return this.vibeCodedRequest("GET", "/loyalty/membership/plans");
6675
+ }
6618
6676
  if (this.storeId && !this.apiKey) {
6619
6677
  return this.storefrontRequest("GET", "/loyalty/membership/plans");
6620
6678
  }
6621
- throw new BrainerceError("getMembershipPlans is only available in storefront mode", 400);
6679
+ throw new BrainerceError(
6680
+ "getMembershipPlans is only available in vibe-coded or storefront mode",
6681
+ 400
6682
+ );
6622
6683
  }
6623
6684
  /**
6624
6685
  * List the customer's saved payment methods (display fields only — brand /
@@ -6638,6 +6699,12 @@ var BrainerceClient = class {
6638
6699
  401
6639
6700
  );
6640
6701
  }
6702
+ if (this.isVibeCodedMode()) {
6703
+ return this.vibeCodedRequest(
6704
+ "GET",
6705
+ "/loyalty/membership/payment-methods"
6706
+ );
6707
+ }
6641
6708
  if (this.storeId && !this.apiKey) {
6642
6709
  return this.storefrontRequest(
6643
6710
  "GET",
@@ -6645,7 +6712,7 @@ var BrainerceClient = class {
6645
6712
  );
6646
6713
  }
6647
6714
  throw new BrainerceError(
6648
- "getMySavedPaymentMethods is only available in storefront mode",
6715
+ "getMySavedPaymentMethods is only available in vibe-coded or storefront mode",
6649
6716
  400
6650
6717
  );
6651
6718
  }
@@ -6672,6 +6739,13 @@ var BrainerceClient = class {
6672
6739
  401
6673
6740
  );
6674
6741
  }
6742
+ if (this.isVibeCodedMode()) {
6743
+ return this.vibeCodedRequest(
6744
+ "POST",
6745
+ "/loyalty/membership/subscribe",
6746
+ params
6747
+ );
6748
+ }
6675
6749
  if (this.storeId && !this.apiKey) {
6676
6750
  return this.storefrontRequest(
6677
6751
  "POST",
@@ -6679,7 +6753,10 @@ var BrainerceClient = class {
6679
6753
  params
6680
6754
  );
6681
6755
  }
6682
- throw new BrainerceError("subscribeToMembership is only available in storefront mode", 400);
6756
+ throw new BrainerceError(
6757
+ "subscribeToMembership is only available in vibe-coded or storefront mode",
6758
+ 400
6759
+ );
6683
6760
  }
6684
6761
  /**
6685
6762
  * Cancel the customer's paid membership (requires customerToken).
@@ -6701,10 +6778,52 @@ var BrainerceClient = class {
6701
6778
  401
6702
6779
  );
6703
6780
  }
6781
+ if (this.isVibeCodedMode()) {
6782
+ return this.vibeCodedRequest("POST", "/loyalty/membership/cancel");
6783
+ }
6704
6784
  if (this.storeId && !this.apiKey) {
6705
6785
  return this.storefrontRequest("POST", "/loyalty/membership/cancel");
6706
6786
  }
6707
- throw new BrainerceError("cancelMembership is only available in storefront mode", 400);
6787
+ throw new BrainerceError(
6788
+ "cancelMembership is only available in vibe-coded or storefront mode",
6789
+ 400
6790
+ );
6791
+ }
6792
+ /**
6793
+ * Mint a short-lived session for the embeddable loyalty widget (Phase 5) and
6794
+ * return the ready-to-use iframe URL. Requires customerToken. The returned
6795
+ * `embedUrl` is safe to drop straight into an `<iframe src>` — it carries a
6796
+ * scoped ~15-minute session token, never the real customerToken. Re-call this
6797
+ * before the iframe reloads (e.g. on page navigation) to refresh it.
6798
+ *
6799
+ * @example
6800
+ * ```typescript
6801
+ * const { embedUrl } = await client.getLoyaltyWidgetSession();
6802
+ * // <iframe src={embedUrl} width="360" height="420" />
6803
+ * ```
6804
+ */
6805
+ async getLoyaltyWidgetSession() {
6806
+ if (!this.customerToken && !this.proxyMode) {
6807
+ throw new BrainerceError(
6808
+ "Customer token required. Call setCustomerToken() after login.",
6809
+ 401
6810
+ );
6811
+ }
6812
+ let result;
6813
+ if (this.isVibeCodedMode()) {
6814
+ result = await this.vibeCodedRequest("POST", "/loyalty/widget-session");
6815
+ } else if (this.storeId && !this.apiKey) {
6816
+ result = await this.storefrontRequest("POST", "/loyalty/widget-session");
6817
+ } else {
6818
+ throw new BrainerceError(
6819
+ "getLoyaltyWidgetSession is only available in vibe-coded or storefront mode",
6820
+ 400
6821
+ );
6822
+ }
6823
+ return {
6824
+ ...result,
6825
+ embedUrl: `${this.baseUrl}/api/loyalty/embed/${encodePathSegment(result.storeId)}/${encodePathSegment(result.sessionId)}`
6826
+ };
6708
6827
  }
6709
6828
  /**
6710
6829
  * Get the current customer's orders (requires customerToken)
@@ -9019,25 +9138,60 @@ function buildArticleJsonLd(post, opts) {
9019
9138
  return result;
9020
9139
  }
9021
9140
  function buildProductJsonLd(product, opts) {
9022
- const url = absoluteUrl(opts.siteUrl, opts.path ?? (product.slug ? `/products/${product.slug}` : void 0));
9141
+ const url = absoluteUrl(
9142
+ opts.siteUrl,
9143
+ opts.path ?? (product.slug ? `/products/${product.slug}` : void 0)
9144
+ );
9023
9145
  const images = (product.images ?? []).map((img) => img.url).filter(Boolean);
9024
9146
  const brand = opts.brandName ?? product.brands?.[0]?.name;
9025
9147
  const description = stripHtml(product.description).slice(0, 5e3);
9026
9148
  const effectivePrice = product.salePrice ?? product.basePrice;
9027
9149
  const inStock = product.inventory ? (product.inventory.available ?? 0) > 0 : true;
9028
9150
  const isVariable = product.type === "VARIABLE" && product.priceMin && product.priceMax;
9151
+ const itemCondition = "https://schema.org/NewCondition";
9152
+ const shippingDetails = (opts.shipping ?? []).filter((z) => z.amount !== null).map((z) => ({
9153
+ "@type": "OfferShippingDetails",
9154
+ shippingRate: { "@type": "MonetaryAmount", value: z.amount, currency: opts.currency },
9155
+ shippingDestination: { "@type": "DefinedRegion", addressCountry: z.countries },
9156
+ ...z.handlingTime != null || z.minDeliveryDays != null || z.maxDeliveryDays != null ? {
9157
+ deliveryTime: {
9158
+ "@type": "ShippingDeliveryTime",
9159
+ ...z.handlingTime != null ? {
9160
+ handlingTime: {
9161
+ "@type": "QuantitativeValue",
9162
+ minValue: 0,
9163
+ maxValue: z.handlingTime
9164
+ }
9165
+ } : {},
9166
+ ...z.minDeliveryDays != null || z.maxDeliveryDays != null ? {
9167
+ transitTime: {
9168
+ "@type": "QuantitativeValue",
9169
+ minValue: z.minDeliveryDays ?? z.maxDeliveryDays,
9170
+ maxValue: z.maxDeliveryDays ?? z.minDeliveryDays
9171
+ }
9172
+ } : {}
9173
+ }
9174
+ } : {}
9175
+ }));
9029
9176
  const offer = isVariable ? {
9030
9177
  "@type": "AggregateOffer",
9031
9178
  lowPrice: product.priceMin,
9032
9179
  highPrice: product.priceMax,
9033
9180
  priceCurrency: opts.currency,
9034
9181
  availability: inStock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
9182
+ itemCondition,
9183
+ ...shippingDetails.length > 0 ? { shippingDetails } : {},
9035
9184
  ...url ? { url } : {}
9036
9185
  } : {
9037
9186
  "@type": "Offer",
9038
9187
  price: effectivePrice,
9039
9188
  priceCurrency: opts.currency,
9040
9189
  availability: inStock ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
9190
+ itemCondition,
9191
+ // Only meaningful for an active sale price with a known end date —
9192
+ // a regular (non-sale) price has no expiry to declare.
9193
+ ...product.salePrice && product.salePriceEndsAt ? { priceValidUntil: product.salePriceEndsAt } : {},
9194
+ ...shippingDetails.length > 0 ? { shippingDetails } : {},
9041
9195
  ...url ? { url } : {}
9042
9196
  };
9043
9197
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainerce",
3
- "version": "1.47.1",
3
+ "version": "1.47.3",
4
4
  "description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",