@brainerce/mcp-server 2.1.0 → 2.1.1
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/bin/http.js +73 -20
- package/dist/bin/stdio.js +73 -20
- package/dist/index.js +73 -20
- package/dist/index.mjs +73 -20
- package/package.json +1 -1
package/dist/bin/http.js
CHANGED
|
@@ -777,6 +777,12 @@ const { bundles } = await client.getCartBundles(cartId);
|
|
|
777
777
|
// bundles[].bundleProduct \u2014 the product to offer
|
|
778
778
|
// bundles[].originalPrice / bundles[].discountedPrice \u2014 prices
|
|
779
779
|
// bundles[].discountType ('PERCENTAGE' | 'FIXED_AMOUNT') + discountValue
|
|
780
|
+
|
|
781
|
+
// Add a bundle to cart (applies the discount automatically):
|
|
782
|
+
await client.addBundleToCart(cartId, bundleOfferId);
|
|
783
|
+
// Remove a bundle from cart:
|
|
784
|
+
await client.removeBundleFromCart(cartId, bundleOfferId);
|
|
785
|
+
// Detect already-added bundles: check cart.items for metadata?.isBundleItem === true
|
|
780
786
|
\`\`\`
|
|
781
787
|
|
|
782
788
|
**Free shipping progress bar** (configured threshold in channel settings):
|
|
@@ -3001,7 +3007,11 @@ export default async function ProductDetailPage({ params }: Props) {
|
|
|
3001
3007
|
|
|
3002
3008
|
import { useEffect, useState } from 'react';
|
|
3003
3009
|
import Link from 'next/link';
|
|
3004
|
-
import type {
|
|
3010
|
+
import type {
|
|
3011
|
+
CartRecommendationsResponse,
|
|
3012
|
+
CartUpgradesResponse,
|
|
3013
|
+
CartBundlesResponse,
|
|
3014
|
+
} from 'brainerce';
|
|
3005
3015
|
import { getClient } from '@/lib/brainerce';
|
|
3006
3016
|
import { useCart } from '@/providers/store-provider';
|
|
3007
3017
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
@@ -3041,7 +3051,11 @@ export default function CartPage() {
|
|
|
3041
3051
|
|
|
3042
3052
|
// Load upgrade suggestions when cart changes
|
|
3043
3053
|
useEffect(() => {
|
|
3044
|
-
if (
|
|
3054
|
+
if (
|
|
3055
|
+
!cart?.id ||
|
|
3056
|
+
cart.items.length === 0 ||
|
|
3057
|
+
storeInfo?.upsell?.cartUpgradeBannerEnabled === false
|
|
3058
|
+
) {
|
|
3045
3059
|
setUpgrades(null);
|
|
3046
3060
|
return;
|
|
3047
3061
|
}
|
|
@@ -9568,8 +9582,18 @@ function ProductThumb({
|
|
|
9568
9582
|
<Image src={imageUrl} alt={name} fill sizes="80px" className="object-cover" />
|
|
9569
9583
|
) : (
|
|
9570
9584
|
<div className="flex h-full w-full items-center justify-center">
|
|
9571
|
-
<svg
|
|
9572
|
-
|
|
9585
|
+
<svg
|
|
9586
|
+
className="text-muted-foreground h-8 w-8"
|
|
9587
|
+
fill="none"
|
|
9588
|
+
viewBox="0 0 24 24"
|
|
9589
|
+
stroke="currentColor"
|
|
9590
|
+
>
|
|
9591
|
+
<path
|
|
9592
|
+
strokeLinecap="round"
|
|
9593
|
+
strokeLinejoin="round"
|
|
9594
|
+
strokeWidth={1.5}
|
|
9595
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9596
|
+
/>
|
|
9573
9597
|
</svg>
|
|
9574
9598
|
</div>
|
|
9575
9599
|
)}
|
|
@@ -9646,7 +9670,9 @@ export function FrequentlyBoughtTogether({
|
|
|
9646
9670
|
|
|
9647
9671
|
return (
|
|
9648
9672
|
<div className={cn('border-border rounded-lg border p-6', className)}>
|
|
9649
|
-
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9673
|
+
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9674
|
+
{t('frequentlyBoughtTogether')}
|
|
9675
|
+
</h2>
|
|
9650
9676
|
|
|
9651
9677
|
<div className="flex flex-wrap items-center gap-3">
|
|
9652
9678
|
{/* Current product (always included, no checkbox) */}
|
|
@@ -9733,12 +9759,7 @@ export function FreeShippingBar({ className }: FreeShippingBarProps) {
|
|
|
9733
9759
|
<div className={cn('rounded-lg border border-green-200 bg-green-50 p-3', className)}>
|
|
9734
9760
|
<div className="flex items-center gap-2 text-sm font-medium text-green-700">
|
|
9735
9761
|
<svg className="h-4 w-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9736
|
-
<path
|
|
9737
|
-
strokeLinecap="round"
|
|
9738
|
-
strokeLinejoin="round"
|
|
9739
|
-
strokeWidth={2}
|
|
9740
|
-
d="M5 13l4 4L19 7"
|
|
9741
|
-
/>
|
|
9762
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
9742
9763
|
</svg>
|
|
9743
9764
|
{t('freeShippingQualified')}
|
|
9744
9765
|
</div>
|
|
@@ -9800,20 +9821,28 @@ export function CartUpgradeBanner({
|
|
|
9800
9821
|
if (sessionStorage.getItem(storageKey)) {
|
|
9801
9822
|
setDismissed(true);
|
|
9802
9823
|
}
|
|
9803
|
-
} catch {
|
|
9824
|
+
} catch {
|
|
9825
|
+
/* ignore */
|
|
9826
|
+
}
|
|
9804
9827
|
}, [storageKey]);
|
|
9805
9828
|
|
|
9806
9829
|
if (dismissed) return null;
|
|
9807
9830
|
|
|
9808
9831
|
const target = suggestion.targetProduct;
|
|
9809
9832
|
const firstImage = target.images?.[0];
|
|
9810
|
-
const imageUrl = firstImage
|
|
9833
|
+
const imageUrl = firstImage
|
|
9834
|
+
? typeof firstImage === 'string'
|
|
9835
|
+
? firstImage
|
|
9836
|
+
: firstImage.url
|
|
9837
|
+
: null;
|
|
9811
9838
|
const formattedDelta = formatPrice(parseFloat(suggestion.priceDelta), { currency }) as string;
|
|
9812
9839
|
|
|
9813
9840
|
function handleDismiss() {
|
|
9814
9841
|
try {
|
|
9815
9842
|
sessionStorage.setItem(storageKey, '1');
|
|
9816
|
-
} catch {
|
|
9843
|
+
} catch {
|
|
9844
|
+
/* ignore */
|
|
9845
|
+
}
|
|
9817
9846
|
setDismissed(true);
|
|
9818
9847
|
}
|
|
9819
9848
|
|
|
@@ -9846,7 +9875,13 @@ export function CartUpgradeBanner({
|
|
|
9846
9875
|
className="text-muted-foreground hover:text-foreground absolute end-2 top-2 text-xs"
|
|
9847
9876
|
aria-label={t('dismissUpgrade')}
|
|
9848
9877
|
>
|
|
9849
|
-
<svg
|
|
9878
|
+
<svg
|
|
9879
|
+
className="h-4 w-4"
|
|
9880
|
+
fill="none"
|
|
9881
|
+
viewBox="0 0 24 24"
|
|
9882
|
+
stroke="currentColor"
|
|
9883
|
+
strokeWidth={2}
|
|
9884
|
+
>
|
|
9850
9885
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
9851
9886
|
</svg>
|
|
9852
9887
|
</button>
|
|
@@ -9858,7 +9893,12 @@ export function CartUpgradeBanner({
|
|
|
9858
9893
|
) : (
|
|
9859
9894
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9860
9895
|
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9861
|
-
<path
|
|
9896
|
+
<path
|
|
9897
|
+
strokeLinecap="round"
|
|
9898
|
+
strokeLinejoin="round"
|
|
9899
|
+
strokeWidth={1.5}
|
|
9900
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9901
|
+
/>
|
|
9862
9902
|
</svg>
|
|
9863
9903
|
</div>
|
|
9864
9904
|
)}
|
|
@@ -9912,13 +9952,17 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9912
9952
|
|
|
9913
9953
|
const product = offer.bundleProduct;
|
|
9914
9954
|
const firstImage = product.images?.[0];
|
|
9915
|
-
const imageUrl = firstImage
|
|
9955
|
+
const imageUrl = firstImage
|
|
9956
|
+
? typeof firstImage === 'string'
|
|
9957
|
+
? firstImage
|
|
9958
|
+
: firstImage.url
|
|
9959
|
+
: null;
|
|
9916
9960
|
const originalPrice = parseFloat(offer.originalPrice);
|
|
9917
9961
|
const discountedPrice = parseFloat(offer.discountedPrice);
|
|
9918
9962
|
const discountLabel =
|
|
9919
9963
|
offer.discountType === 'PERCENTAGE'
|
|
9920
9964
|
? \`\${offer.discountValue}%\`
|
|
9921
|
-
: formatPrice(parseFloat(offer.discountValue), { currency }) as string;
|
|
9965
|
+
: (formatPrice(parseFloat(offer.discountValue), { currency }) as string);
|
|
9922
9966
|
|
|
9923
9967
|
async function handleAdd() {
|
|
9924
9968
|
if (adding) return;
|
|
@@ -9952,7 +9996,12 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9952
9996
|
) : (
|
|
9953
9997
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9954
9998
|
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9955
|
-
<path
|
|
9999
|
+
<path
|
|
10000
|
+
strokeLinecap="round"
|
|
10001
|
+
strokeLinejoin="round"
|
|
10002
|
+
strokeWidth={1.5}
|
|
10003
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
10004
|
+
/>
|
|
9956
10005
|
</svg>
|
|
9957
10006
|
</div>
|
|
9958
10007
|
)}
|
|
@@ -10017,7 +10066,11 @@ export function OrderBumpCard({ bump, isAdded, onToggle, loading, className }: O
|
|
|
10017
10066
|
|
|
10018
10067
|
const product = bump.bumpProduct;
|
|
10019
10068
|
const firstImage = product.images?.[0];
|
|
10020
|
-
const imageUrl = firstImage
|
|
10069
|
+
const imageUrl = firstImage
|
|
10070
|
+
? typeof firstImage === 'string'
|
|
10071
|
+
? firstImage
|
|
10072
|
+
: firstImage.url
|
|
10073
|
+
: null;
|
|
10021
10074
|
const originalPrice = parseFloat(bump.originalPrice);
|
|
10022
10075
|
const hasDiscount = bump.discountedPrice != null;
|
|
10023
10076
|
const discountedPrice = hasDiscount ? parseFloat(bump.discountedPrice!) : null;
|
package/dist/bin/stdio.js
CHANGED
|
@@ -775,6 +775,12 @@ const { bundles } = await client.getCartBundles(cartId);
|
|
|
775
775
|
// bundles[].bundleProduct \u2014 the product to offer
|
|
776
776
|
// bundles[].originalPrice / bundles[].discountedPrice \u2014 prices
|
|
777
777
|
// bundles[].discountType ('PERCENTAGE' | 'FIXED_AMOUNT') + discountValue
|
|
778
|
+
|
|
779
|
+
// Add a bundle to cart (applies the discount automatically):
|
|
780
|
+
await client.addBundleToCart(cartId, bundleOfferId);
|
|
781
|
+
// Remove a bundle from cart:
|
|
782
|
+
await client.removeBundleFromCart(cartId, bundleOfferId);
|
|
783
|
+
// Detect already-added bundles: check cart.items for metadata?.isBundleItem === true
|
|
778
784
|
\`\`\`
|
|
779
785
|
|
|
780
786
|
**Free shipping progress bar** (configured threshold in channel settings):
|
|
@@ -2999,7 +3005,11 @@ export default async function ProductDetailPage({ params }: Props) {
|
|
|
2999
3005
|
|
|
3000
3006
|
import { useEffect, useState } from 'react';
|
|
3001
3007
|
import Link from 'next/link';
|
|
3002
|
-
import type {
|
|
3008
|
+
import type {
|
|
3009
|
+
CartRecommendationsResponse,
|
|
3010
|
+
CartUpgradesResponse,
|
|
3011
|
+
CartBundlesResponse,
|
|
3012
|
+
} from 'brainerce';
|
|
3003
3013
|
import { getClient } from '@/lib/brainerce';
|
|
3004
3014
|
import { useCart } from '@/providers/store-provider';
|
|
3005
3015
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
@@ -3039,7 +3049,11 @@ export default function CartPage() {
|
|
|
3039
3049
|
|
|
3040
3050
|
// Load upgrade suggestions when cart changes
|
|
3041
3051
|
useEffect(() => {
|
|
3042
|
-
if (
|
|
3052
|
+
if (
|
|
3053
|
+
!cart?.id ||
|
|
3054
|
+
cart.items.length === 0 ||
|
|
3055
|
+
storeInfo?.upsell?.cartUpgradeBannerEnabled === false
|
|
3056
|
+
) {
|
|
3043
3057
|
setUpgrades(null);
|
|
3044
3058
|
return;
|
|
3045
3059
|
}
|
|
@@ -9566,8 +9580,18 @@ function ProductThumb({
|
|
|
9566
9580
|
<Image src={imageUrl} alt={name} fill sizes="80px" className="object-cover" />
|
|
9567
9581
|
) : (
|
|
9568
9582
|
<div className="flex h-full w-full items-center justify-center">
|
|
9569
|
-
<svg
|
|
9570
|
-
|
|
9583
|
+
<svg
|
|
9584
|
+
className="text-muted-foreground h-8 w-8"
|
|
9585
|
+
fill="none"
|
|
9586
|
+
viewBox="0 0 24 24"
|
|
9587
|
+
stroke="currentColor"
|
|
9588
|
+
>
|
|
9589
|
+
<path
|
|
9590
|
+
strokeLinecap="round"
|
|
9591
|
+
strokeLinejoin="round"
|
|
9592
|
+
strokeWidth={1.5}
|
|
9593
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9594
|
+
/>
|
|
9571
9595
|
</svg>
|
|
9572
9596
|
</div>
|
|
9573
9597
|
)}
|
|
@@ -9644,7 +9668,9 @@ export function FrequentlyBoughtTogether({
|
|
|
9644
9668
|
|
|
9645
9669
|
return (
|
|
9646
9670
|
<div className={cn('border-border rounded-lg border p-6', className)}>
|
|
9647
|
-
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9671
|
+
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9672
|
+
{t('frequentlyBoughtTogether')}
|
|
9673
|
+
</h2>
|
|
9648
9674
|
|
|
9649
9675
|
<div className="flex flex-wrap items-center gap-3">
|
|
9650
9676
|
{/* Current product (always included, no checkbox) */}
|
|
@@ -9731,12 +9757,7 @@ export function FreeShippingBar({ className }: FreeShippingBarProps) {
|
|
|
9731
9757
|
<div className={cn('rounded-lg border border-green-200 bg-green-50 p-3', className)}>
|
|
9732
9758
|
<div className="flex items-center gap-2 text-sm font-medium text-green-700">
|
|
9733
9759
|
<svg className="h-4 w-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9734
|
-
<path
|
|
9735
|
-
strokeLinecap="round"
|
|
9736
|
-
strokeLinejoin="round"
|
|
9737
|
-
strokeWidth={2}
|
|
9738
|
-
d="M5 13l4 4L19 7"
|
|
9739
|
-
/>
|
|
9760
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
9740
9761
|
</svg>
|
|
9741
9762
|
{t('freeShippingQualified')}
|
|
9742
9763
|
</div>
|
|
@@ -9798,20 +9819,28 @@ export function CartUpgradeBanner({
|
|
|
9798
9819
|
if (sessionStorage.getItem(storageKey)) {
|
|
9799
9820
|
setDismissed(true);
|
|
9800
9821
|
}
|
|
9801
|
-
} catch {
|
|
9822
|
+
} catch {
|
|
9823
|
+
/* ignore */
|
|
9824
|
+
}
|
|
9802
9825
|
}, [storageKey]);
|
|
9803
9826
|
|
|
9804
9827
|
if (dismissed) return null;
|
|
9805
9828
|
|
|
9806
9829
|
const target = suggestion.targetProduct;
|
|
9807
9830
|
const firstImage = target.images?.[0];
|
|
9808
|
-
const imageUrl = firstImage
|
|
9831
|
+
const imageUrl = firstImage
|
|
9832
|
+
? typeof firstImage === 'string'
|
|
9833
|
+
? firstImage
|
|
9834
|
+
: firstImage.url
|
|
9835
|
+
: null;
|
|
9809
9836
|
const formattedDelta = formatPrice(parseFloat(suggestion.priceDelta), { currency }) as string;
|
|
9810
9837
|
|
|
9811
9838
|
function handleDismiss() {
|
|
9812
9839
|
try {
|
|
9813
9840
|
sessionStorage.setItem(storageKey, '1');
|
|
9814
|
-
} catch {
|
|
9841
|
+
} catch {
|
|
9842
|
+
/* ignore */
|
|
9843
|
+
}
|
|
9815
9844
|
setDismissed(true);
|
|
9816
9845
|
}
|
|
9817
9846
|
|
|
@@ -9844,7 +9873,13 @@ export function CartUpgradeBanner({
|
|
|
9844
9873
|
className="text-muted-foreground hover:text-foreground absolute end-2 top-2 text-xs"
|
|
9845
9874
|
aria-label={t('dismissUpgrade')}
|
|
9846
9875
|
>
|
|
9847
|
-
<svg
|
|
9876
|
+
<svg
|
|
9877
|
+
className="h-4 w-4"
|
|
9878
|
+
fill="none"
|
|
9879
|
+
viewBox="0 0 24 24"
|
|
9880
|
+
stroke="currentColor"
|
|
9881
|
+
strokeWidth={2}
|
|
9882
|
+
>
|
|
9848
9883
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
9849
9884
|
</svg>
|
|
9850
9885
|
</button>
|
|
@@ -9856,7 +9891,12 @@ export function CartUpgradeBanner({
|
|
|
9856
9891
|
) : (
|
|
9857
9892
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9858
9893
|
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9859
|
-
<path
|
|
9894
|
+
<path
|
|
9895
|
+
strokeLinecap="round"
|
|
9896
|
+
strokeLinejoin="round"
|
|
9897
|
+
strokeWidth={1.5}
|
|
9898
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9899
|
+
/>
|
|
9860
9900
|
</svg>
|
|
9861
9901
|
</div>
|
|
9862
9902
|
)}
|
|
@@ -9910,13 +9950,17 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9910
9950
|
|
|
9911
9951
|
const product = offer.bundleProduct;
|
|
9912
9952
|
const firstImage = product.images?.[0];
|
|
9913
|
-
const imageUrl = firstImage
|
|
9953
|
+
const imageUrl = firstImage
|
|
9954
|
+
? typeof firstImage === 'string'
|
|
9955
|
+
? firstImage
|
|
9956
|
+
: firstImage.url
|
|
9957
|
+
: null;
|
|
9914
9958
|
const originalPrice = parseFloat(offer.originalPrice);
|
|
9915
9959
|
const discountedPrice = parseFloat(offer.discountedPrice);
|
|
9916
9960
|
const discountLabel =
|
|
9917
9961
|
offer.discountType === 'PERCENTAGE'
|
|
9918
9962
|
? \`\${offer.discountValue}%\`
|
|
9919
|
-
: formatPrice(parseFloat(offer.discountValue), { currency }) as string;
|
|
9963
|
+
: (formatPrice(parseFloat(offer.discountValue), { currency }) as string);
|
|
9920
9964
|
|
|
9921
9965
|
async function handleAdd() {
|
|
9922
9966
|
if (adding) return;
|
|
@@ -9950,7 +9994,12 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9950
9994
|
) : (
|
|
9951
9995
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9952
9996
|
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9953
|
-
<path
|
|
9997
|
+
<path
|
|
9998
|
+
strokeLinecap="round"
|
|
9999
|
+
strokeLinejoin="round"
|
|
10000
|
+
strokeWidth={1.5}
|
|
10001
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
10002
|
+
/>
|
|
9954
10003
|
</svg>
|
|
9955
10004
|
</div>
|
|
9956
10005
|
)}
|
|
@@ -10015,7 +10064,11 @@ export function OrderBumpCard({ bump, isAdded, onToggle, loading, className }: O
|
|
|
10015
10064
|
|
|
10016
10065
|
const product = bump.bumpProduct;
|
|
10017
10066
|
const firstImage = product.images?.[0];
|
|
10018
|
-
const imageUrl = firstImage
|
|
10067
|
+
const imageUrl = firstImage
|
|
10068
|
+
? typeof firstImage === 'string'
|
|
10069
|
+
? firstImage
|
|
10070
|
+
: firstImage.url
|
|
10071
|
+
: null;
|
|
10019
10072
|
const originalPrice = parseFloat(bump.originalPrice);
|
|
10020
10073
|
const hasDiscount = bump.discountedPrice != null;
|
|
10021
10074
|
const discountedPrice = hasDiscount ? parseFloat(bump.discountedPrice!) : null;
|
package/dist/index.js
CHANGED
|
@@ -792,6 +792,12 @@ const { bundles } = await client.getCartBundles(cartId);
|
|
|
792
792
|
// bundles[].bundleProduct \u2014 the product to offer
|
|
793
793
|
// bundles[].originalPrice / bundles[].discountedPrice \u2014 prices
|
|
794
794
|
// bundles[].discountType ('PERCENTAGE' | 'FIXED_AMOUNT') + discountValue
|
|
795
|
+
|
|
796
|
+
// Add a bundle to cart (applies the discount automatically):
|
|
797
|
+
await client.addBundleToCart(cartId, bundleOfferId);
|
|
798
|
+
// Remove a bundle from cart:
|
|
799
|
+
await client.removeBundleFromCart(cartId, bundleOfferId);
|
|
800
|
+
// Detect already-added bundles: check cart.items for metadata?.isBundleItem === true
|
|
795
801
|
\`\`\`
|
|
796
802
|
|
|
797
803
|
**Free shipping progress bar** (configured threshold in channel settings):
|
|
@@ -3016,7 +3022,11 @@ export default async function ProductDetailPage({ params }: Props) {
|
|
|
3016
3022
|
|
|
3017
3023
|
import { useEffect, useState } from 'react';
|
|
3018
3024
|
import Link from 'next/link';
|
|
3019
|
-
import type {
|
|
3025
|
+
import type {
|
|
3026
|
+
CartRecommendationsResponse,
|
|
3027
|
+
CartUpgradesResponse,
|
|
3028
|
+
CartBundlesResponse,
|
|
3029
|
+
} from 'brainerce';
|
|
3020
3030
|
import { getClient } from '@/lib/brainerce';
|
|
3021
3031
|
import { useCart } from '@/providers/store-provider';
|
|
3022
3032
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
@@ -3056,7 +3066,11 @@ export default function CartPage() {
|
|
|
3056
3066
|
|
|
3057
3067
|
// Load upgrade suggestions when cart changes
|
|
3058
3068
|
useEffect(() => {
|
|
3059
|
-
if (
|
|
3069
|
+
if (
|
|
3070
|
+
!cart?.id ||
|
|
3071
|
+
cart.items.length === 0 ||
|
|
3072
|
+
storeInfo?.upsell?.cartUpgradeBannerEnabled === false
|
|
3073
|
+
) {
|
|
3060
3074
|
setUpgrades(null);
|
|
3061
3075
|
return;
|
|
3062
3076
|
}
|
|
@@ -9583,8 +9597,18 @@ function ProductThumb({
|
|
|
9583
9597
|
<Image src={imageUrl} alt={name} fill sizes="80px" className="object-cover" />
|
|
9584
9598
|
) : (
|
|
9585
9599
|
<div className="flex h-full w-full items-center justify-center">
|
|
9586
|
-
<svg
|
|
9587
|
-
|
|
9600
|
+
<svg
|
|
9601
|
+
className="text-muted-foreground h-8 w-8"
|
|
9602
|
+
fill="none"
|
|
9603
|
+
viewBox="0 0 24 24"
|
|
9604
|
+
stroke="currentColor"
|
|
9605
|
+
>
|
|
9606
|
+
<path
|
|
9607
|
+
strokeLinecap="round"
|
|
9608
|
+
strokeLinejoin="round"
|
|
9609
|
+
strokeWidth={1.5}
|
|
9610
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9611
|
+
/>
|
|
9588
9612
|
</svg>
|
|
9589
9613
|
</div>
|
|
9590
9614
|
)}
|
|
@@ -9661,7 +9685,9 @@ export function FrequentlyBoughtTogether({
|
|
|
9661
9685
|
|
|
9662
9686
|
return (
|
|
9663
9687
|
<div className={cn('border-border rounded-lg border p-6', className)}>
|
|
9664
|
-
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9688
|
+
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9689
|
+
{t('frequentlyBoughtTogether')}
|
|
9690
|
+
</h2>
|
|
9665
9691
|
|
|
9666
9692
|
<div className="flex flex-wrap items-center gap-3">
|
|
9667
9693
|
{/* Current product (always included, no checkbox) */}
|
|
@@ -9748,12 +9774,7 @@ export function FreeShippingBar({ className }: FreeShippingBarProps) {
|
|
|
9748
9774
|
<div className={cn('rounded-lg border border-green-200 bg-green-50 p-3', className)}>
|
|
9749
9775
|
<div className="flex items-center gap-2 text-sm font-medium text-green-700">
|
|
9750
9776
|
<svg className="h-4 w-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9751
|
-
<path
|
|
9752
|
-
strokeLinecap="round"
|
|
9753
|
-
strokeLinejoin="round"
|
|
9754
|
-
strokeWidth={2}
|
|
9755
|
-
d="M5 13l4 4L19 7"
|
|
9756
|
-
/>
|
|
9777
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
9757
9778
|
</svg>
|
|
9758
9779
|
{t('freeShippingQualified')}
|
|
9759
9780
|
</div>
|
|
@@ -9815,20 +9836,28 @@ export function CartUpgradeBanner({
|
|
|
9815
9836
|
if (sessionStorage.getItem(storageKey)) {
|
|
9816
9837
|
setDismissed(true);
|
|
9817
9838
|
}
|
|
9818
|
-
} catch {
|
|
9839
|
+
} catch {
|
|
9840
|
+
/* ignore */
|
|
9841
|
+
}
|
|
9819
9842
|
}, [storageKey]);
|
|
9820
9843
|
|
|
9821
9844
|
if (dismissed) return null;
|
|
9822
9845
|
|
|
9823
9846
|
const target = suggestion.targetProduct;
|
|
9824
9847
|
const firstImage = target.images?.[0];
|
|
9825
|
-
const imageUrl = firstImage
|
|
9848
|
+
const imageUrl = firstImage
|
|
9849
|
+
? typeof firstImage === 'string'
|
|
9850
|
+
? firstImage
|
|
9851
|
+
: firstImage.url
|
|
9852
|
+
: null;
|
|
9826
9853
|
const formattedDelta = formatPrice(parseFloat(suggestion.priceDelta), { currency }) as string;
|
|
9827
9854
|
|
|
9828
9855
|
function handleDismiss() {
|
|
9829
9856
|
try {
|
|
9830
9857
|
sessionStorage.setItem(storageKey, '1');
|
|
9831
|
-
} catch {
|
|
9858
|
+
} catch {
|
|
9859
|
+
/* ignore */
|
|
9860
|
+
}
|
|
9832
9861
|
setDismissed(true);
|
|
9833
9862
|
}
|
|
9834
9863
|
|
|
@@ -9861,7 +9890,13 @@ export function CartUpgradeBanner({
|
|
|
9861
9890
|
className="text-muted-foreground hover:text-foreground absolute end-2 top-2 text-xs"
|
|
9862
9891
|
aria-label={t('dismissUpgrade')}
|
|
9863
9892
|
>
|
|
9864
|
-
<svg
|
|
9893
|
+
<svg
|
|
9894
|
+
className="h-4 w-4"
|
|
9895
|
+
fill="none"
|
|
9896
|
+
viewBox="0 0 24 24"
|
|
9897
|
+
stroke="currentColor"
|
|
9898
|
+
strokeWidth={2}
|
|
9899
|
+
>
|
|
9865
9900
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
9866
9901
|
</svg>
|
|
9867
9902
|
</button>
|
|
@@ -9873,7 +9908,12 @@ export function CartUpgradeBanner({
|
|
|
9873
9908
|
) : (
|
|
9874
9909
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9875
9910
|
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9876
|
-
<path
|
|
9911
|
+
<path
|
|
9912
|
+
strokeLinecap="round"
|
|
9913
|
+
strokeLinejoin="round"
|
|
9914
|
+
strokeWidth={1.5}
|
|
9915
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9916
|
+
/>
|
|
9877
9917
|
</svg>
|
|
9878
9918
|
</div>
|
|
9879
9919
|
)}
|
|
@@ -9927,13 +9967,17 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9927
9967
|
|
|
9928
9968
|
const product = offer.bundleProduct;
|
|
9929
9969
|
const firstImage = product.images?.[0];
|
|
9930
|
-
const imageUrl = firstImage
|
|
9970
|
+
const imageUrl = firstImage
|
|
9971
|
+
? typeof firstImage === 'string'
|
|
9972
|
+
? firstImage
|
|
9973
|
+
: firstImage.url
|
|
9974
|
+
: null;
|
|
9931
9975
|
const originalPrice = parseFloat(offer.originalPrice);
|
|
9932
9976
|
const discountedPrice = parseFloat(offer.discountedPrice);
|
|
9933
9977
|
const discountLabel =
|
|
9934
9978
|
offer.discountType === 'PERCENTAGE'
|
|
9935
9979
|
? \`\${offer.discountValue}%\`
|
|
9936
|
-
: formatPrice(parseFloat(offer.discountValue), { currency }) as string;
|
|
9980
|
+
: (formatPrice(parseFloat(offer.discountValue), { currency }) as string);
|
|
9937
9981
|
|
|
9938
9982
|
async function handleAdd() {
|
|
9939
9983
|
if (adding) return;
|
|
@@ -9967,7 +10011,12 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9967
10011
|
) : (
|
|
9968
10012
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9969
10013
|
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9970
|
-
<path
|
|
10014
|
+
<path
|
|
10015
|
+
strokeLinecap="round"
|
|
10016
|
+
strokeLinejoin="round"
|
|
10017
|
+
strokeWidth={1.5}
|
|
10018
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
10019
|
+
/>
|
|
9971
10020
|
</svg>
|
|
9972
10021
|
</div>
|
|
9973
10022
|
)}
|
|
@@ -10032,7 +10081,11 @@ export function OrderBumpCard({ bump, isAdded, onToggle, loading, className }: O
|
|
|
10032
10081
|
|
|
10033
10082
|
const product = bump.bumpProduct;
|
|
10034
10083
|
const firstImage = product.images?.[0];
|
|
10035
|
-
const imageUrl = firstImage
|
|
10084
|
+
const imageUrl = firstImage
|
|
10085
|
+
? typeof firstImage === 'string'
|
|
10086
|
+
? firstImage
|
|
10087
|
+
: firstImage.url
|
|
10088
|
+
: null;
|
|
10036
10089
|
const originalPrice = parseFloat(bump.originalPrice);
|
|
10037
10090
|
const hasDiscount = bump.discountedPrice != null;
|
|
10038
10091
|
const discountedPrice = hasDiscount ? parseFloat(bump.discountedPrice!) : null;
|
package/dist/index.mjs
CHANGED
|
@@ -747,6 +747,12 @@ const { bundles } = await client.getCartBundles(cartId);
|
|
|
747
747
|
// bundles[].bundleProduct \u2014 the product to offer
|
|
748
748
|
// bundles[].originalPrice / bundles[].discountedPrice \u2014 prices
|
|
749
749
|
// bundles[].discountType ('PERCENTAGE' | 'FIXED_AMOUNT') + discountValue
|
|
750
|
+
|
|
751
|
+
// Add a bundle to cart (applies the discount automatically):
|
|
752
|
+
await client.addBundleToCart(cartId, bundleOfferId);
|
|
753
|
+
// Remove a bundle from cart:
|
|
754
|
+
await client.removeBundleFromCart(cartId, bundleOfferId);
|
|
755
|
+
// Detect already-added bundles: check cart.items for metadata?.isBundleItem === true
|
|
750
756
|
\`\`\`
|
|
751
757
|
|
|
752
758
|
**Free shipping progress bar** (configured threshold in channel settings):
|
|
@@ -2971,7 +2977,11 @@ export default async function ProductDetailPage({ params }: Props) {
|
|
|
2971
2977
|
|
|
2972
2978
|
import { useEffect, useState } from 'react';
|
|
2973
2979
|
import Link from 'next/link';
|
|
2974
|
-
import type {
|
|
2980
|
+
import type {
|
|
2981
|
+
CartRecommendationsResponse,
|
|
2982
|
+
CartUpgradesResponse,
|
|
2983
|
+
CartBundlesResponse,
|
|
2984
|
+
} from 'brainerce';
|
|
2975
2985
|
import { getClient } from '@/lib/brainerce';
|
|
2976
2986
|
import { useCart } from '@/providers/store-provider';
|
|
2977
2987
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
@@ -3011,7 +3021,11 @@ export default function CartPage() {
|
|
|
3011
3021
|
|
|
3012
3022
|
// Load upgrade suggestions when cart changes
|
|
3013
3023
|
useEffect(() => {
|
|
3014
|
-
if (
|
|
3024
|
+
if (
|
|
3025
|
+
!cart?.id ||
|
|
3026
|
+
cart.items.length === 0 ||
|
|
3027
|
+
storeInfo?.upsell?.cartUpgradeBannerEnabled === false
|
|
3028
|
+
) {
|
|
3015
3029
|
setUpgrades(null);
|
|
3016
3030
|
return;
|
|
3017
3031
|
}
|
|
@@ -9538,8 +9552,18 @@ function ProductThumb({
|
|
|
9538
9552
|
<Image src={imageUrl} alt={name} fill sizes="80px" className="object-cover" />
|
|
9539
9553
|
) : (
|
|
9540
9554
|
<div className="flex h-full w-full items-center justify-center">
|
|
9541
|
-
<svg
|
|
9542
|
-
|
|
9555
|
+
<svg
|
|
9556
|
+
className="text-muted-foreground h-8 w-8"
|
|
9557
|
+
fill="none"
|
|
9558
|
+
viewBox="0 0 24 24"
|
|
9559
|
+
stroke="currentColor"
|
|
9560
|
+
>
|
|
9561
|
+
<path
|
|
9562
|
+
strokeLinecap="round"
|
|
9563
|
+
strokeLinejoin="round"
|
|
9564
|
+
strokeWidth={1.5}
|
|
9565
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9566
|
+
/>
|
|
9543
9567
|
</svg>
|
|
9544
9568
|
</div>
|
|
9545
9569
|
)}
|
|
@@ -9616,7 +9640,9 @@ export function FrequentlyBoughtTogether({
|
|
|
9616
9640
|
|
|
9617
9641
|
return (
|
|
9618
9642
|
<div className={cn('border-border rounded-lg border p-6', className)}>
|
|
9619
|
-
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9643
|
+
<h2 className="text-foreground mb-4 text-xl font-semibold">
|
|
9644
|
+
{t('frequentlyBoughtTogether')}
|
|
9645
|
+
</h2>
|
|
9620
9646
|
|
|
9621
9647
|
<div className="flex flex-wrap items-center gap-3">
|
|
9622
9648
|
{/* Current product (always included, no checkbox) */}
|
|
@@ -9703,12 +9729,7 @@ export function FreeShippingBar({ className }: FreeShippingBarProps) {
|
|
|
9703
9729
|
<div className={cn('rounded-lg border border-green-200 bg-green-50 p-3', className)}>
|
|
9704
9730
|
<div className="flex items-center gap-2 text-sm font-medium text-green-700">
|
|
9705
9731
|
<svg className="h-4 w-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9706
|
-
<path
|
|
9707
|
-
strokeLinecap="round"
|
|
9708
|
-
strokeLinejoin="round"
|
|
9709
|
-
strokeWidth={2}
|
|
9710
|
-
d="M5 13l4 4L19 7"
|
|
9711
|
-
/>
|
|
9732
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
9712
9733
|
</svg>
|
|
9713
9734
|
{t('freeShippingQualified')}
|
|
9714
9735
|
</div>
|
|
@@ -9770,20 +9791,28 @@ export function CartUpgradeBanner({
|
|
|
9770
9791
|
if (sessionStorage.getItem(storageKey)) {
|
|
9771
9792
|
setDismissed(true);
|
|
9772
9793
|
}
|
|
9773
|
-
} catch {
|
|
9794
|
+
} catch {
|
|
9795
|
+
/* ignore */
|
|
9796
|
+
}
|
|
9774
9797
|
}, [storageKey]);
|
|
9775
9798
|
|
|
9776
9799
|
if (dismissed) return null;
|
|
9777
9800
|
|
|
9778
9801
|
const target = suggestion.targetProduct;
|
|
9779
9802
|
const firstImage = target.images?.[0];
|
|
9780
|
-
const imageUrl = firstImage
|
|
9803
|
+
const imageUrl = firstImage
|
|
9804
|
+
? typeof firstImage === 'string'
|
|
9805
|
+
? firstImage
|
|
9806
|
+
: firstImage.url
|
|
9807
|
+
: null;
|
|
9781
9808
|
const formattedDelta = formatPrice(parseFloat(suggestion.priceDelta), { currency }) as string;
|
|
9782
9809
|
|
|
9783
9810
|
function handleDismiss() {
|
|
9784
9811
|
try {
|
|
9785
9812
|
sessionStorage.setItem(storageKey, '1');
|
|
9786
|
-
} catch {
|
|
9813
|
+
} catch {
|
|
9814
|
+
/* ignore */
|
|
9815
|
+
}
|
|
9787
9816
|
setDismissed(true);
|
|
9788
9817
|
}
|
|
9789
9818
|
|
|
@@ -9816,7 +9845,13 @@ export function CartUpgradeBanner({
|
|
|
9816
9845
|
className="text-muted-foreground hover:text-foreground absolute end-2 top-2 text-xs"
|
|
9817
9846
|
aria-label={t('dismissUpgrade')}
|
|
9818
9847
|
>
|
|
9819
|
-
<svg
|
|
9848
|
+
<svg
|
|
9849
|
+
className="h-4 w-4"
|
|
9850
|
+
fill="none"
|
|
9851
|
+
viewBox="0 0 24 24"
|
|
9852
|
+
stroke="currentColor"
|
|
9853
|
+
strokeWidth={2}
|
|
9854
|
+
>
|
|
9820
9855
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
9821
9856
|
</svg>
|
|
9822
9857
|
</button>
|
|
@@ -9828,7 +9863,12 @@ export function CartUpgradeBanner({
|
|
|
9828
9863
|
) : (
|
|
9829
9864
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9830
9865
|
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9831
|
-
<path
|
|
9866
|
+
<path
|
|
9867
|
+
strokeLinecap="round"
|
|
9868
|
+
strokeLinejoin="round"
|
|
9869
|
+
strokeWidth={1.5}
|
|
9870
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9871
|
+
/>
|
|
9832
9872
|
</svg>
|
|
9833
9873
|
</div>
|
|
9834
9874
|
)}
|
|
@@ -9882,13 +9922,17 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9882
9922
|
|
|
9883
9923
|
const product = offer.bundleProduct;
|
|
9884
9924
|
const firstImage = product.images?.[0];
|
|
9885
|
-
const imageUrl = firstImage
|
|
9925
|
+
const imageUrl = firstImage
|
|
9926
|
+
? typeof firstImage === 'string'
|
|
9927
|
+
? firstImage
|
|
9928
|
+
: firstImage.url
|
|
9929
|
+
: null;
|
|
9886
9930
|
const originalPrice = parseFloat(offer.originalPrice);
|
|
9887
9931
|
const discountedPrice = parseFloat(offer.discountedPrice);
|
|
9888
9932
|
const discountLabel =
|
|
9889
9933
|
offer.discountType === 'PERCENTAGE'
|
|
9890
9934
|
? \`\${offer.discountValue}%\`
|
|
9891
|
-
: formatPrice(parseFloat(offer.discountValue), { currency }) as string;
|
|
9935
|
+
: (formatPrice(parseFloat(offer.discountValue), { currency }) as string);
|
|
9892
9936
|
|
|
9893
9937
|
async function handleAdd() {
|
|
9894
9938
|
if (adding) return;
|
|
@@ -9922,7 +9966,12 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9922
9966
|
) : (
|
|
9923
9967
|
<div className="text-muted-foreground flex h-full w-full items-center justify-center">
|
|
9924
9968
|
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
9925
|
-
<path
|
|
9969
|
+
<path
|
|
9970
|
+
strokeLinecap="round"
|
|
9971
|
+
strokeLinejoin="round"
|
|
9972
|
+
strokeWidth={1.5}
|
|
9973
|
+
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
9974
|
+
/>
|
|
9926
9975
|
</svg>
|
|
9927
9976
|
</div>
|
|
9928
9977
|
)}
|
|
@@ -9987,7 +10036,11 @@ export function OrderBumpCard({ bump, isAdded, onToggle, loading, className }: O
|
|
|
9987
10036
|
|
|
9988
10037
|
const product = bump.bumpProduct;
|
|
9989
10038
|
const firstImage = product.images?.[0];
|
|
9990
|
-
const imageUrl = firstImage
|
|
10039
|
+
const imageUrl = firstImage
|
|
10040
|
+
? typeof firstImage === 'string'
|
|
10041
|
+
? firstImage
|
|
10042
|
+
: firstImage.url
|
|
10043
|
+
: null;
|
|
9991
10044
|
const originalPrice = parseFloat(bump.originalPrice);
|
|
9992
10045
|
const hasDiscount = bump.discountedPrice != null;
|
|
9993
10046
|
const discountedPrice = hasDiscount ? parseFloat(bump.discountedPrice!) : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainerce/mcp-server",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "MCP server for AI-powered Brainerce store building. Provides SDK docs, types, and code examples to AI tools like Lovable, Cursor, and Claude Code.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"brainerce-mcp": "dist/bin/stdio.js"
|