@brainerce/mcp-server 2.1.1 → 2.3.0
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 +57 -9
- package/dist/bin/stdio.js +57 -9
- package/dist/index.js +57 -9
- package/dist/index.mjs +57 -9
- package/package.json +1 -1
package/dist/bin/http.js
CHANGED
|
@@ -3157,7 +3157,12 @@ export default function CartPage() {
|
|
|
3157
3157
|
<div className="mt-6 space-y-3">
|
|
3158
3158
|
<h3 className="text-foreground text-sm font-semibold">{t('bundleOffers')}</h3>
|
|
3159
3159
|
{bundles.bundles.map((offer) => (
|
|
3160
|
-
<CartBundleOfferCard
|
|
3160
|
+
<CartBundleOfferCard
|
|
3161
|
+
key={offer.id}
|
|
3162
|
+
offer={offer}
|
|
3163
|
+
cartId={cart.id}
|
|
3164
|
+
onAdd={refreshCart}
|
|
3165
|
+
/>
|
|
3161
3166
|
))}
|
|
3162
3167
|
</div>
|
|
3163
3168
|
)}
|
|
@@ -7654,8 +7659,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7654
7659
|
})
|
|
7655
7660
|
.catch(() => null);
|
|
7656
7661
|
|
|
7657
|
-
// B) Load + init SDK as early as possible
|
|
7662
|
+
// B) Load + init SDK as early as possible (skip for sandbox)
|
|
7658
7663
|
providerPromise.then((providerSdk) => {
|
|
7664
|
+
if (providerSdk?.renderType === 'sandbox') return;
|
|
7659
7665
|
if (providerSdk?.renderType === 'sdk-widget' && providerSdk.scriptUrl) {
|
|
7660
7666
|
currentSdk = providerSdk;
|
|
7661
7667
|
loadScript(providerSdk);
|
|
@@ -7682,6 +7688,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7682
7688
|
const sdk = resolveClientSdk(intent, providerSdk);
|
|
7683
7689
|
currentSdk = sdk;
|
|
7684
7690
|
|
|
7691
|
+
// Sandbox mode \u2014 no SDK to load, UI handles it
|
|
7692
|
+
if (sdk.renderType === 'sandbox') return;
|
|
7693
|
+
|
|
7685
7694
|
if (sdk.renderType === 'redirect') {
|
|
7686
7695
|
window.location.href = intent.clientSecret;
|
|
7687
7696
|
return;
|
|
@@ -7776,6 +7785,48 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7776
7785
|
|
|
7777
7786
|
const sdk = resolveClientSdk(paymentIntent, preloadedSdk);
|
|
7778
7787
|
|
|
7788
|
+
if (sdk.renderType === 'sandbox') {
|
|
7789
|
+
const handleCompleteSandbox = async () => {
|
|
7790
|
+
setLoading(true);
|
|
7791
|
+
try {
|
|
7792
|
+
const client = getClient();
|
|
7793
|
+
await client.completeGuestCheckout(checkoutId);
|
|
7794
|
+
window.location.href = \`/order-confirmation?checkout_id=\${checkoutId}\`;
|
|
7795
|
+
} catch (err) {
|
|
7796
|
+
setError(err instanceof Error ? err.message : t('paymentError'));
|
|
7797
|
+
setLoading(false);
|
|
7798
|
+
}
|
|
7799
|
+
};
|
|
7800
|
+
|
|
7801
|
+
return (
|
|
7802
|
+
<div className={cn('py-8 text-center', className)}>
|
|
7803
|
+
<div className="mx-auto max-w-md rounded-lg border border-amber-200 bg-amber-50 p-6">
|
|
7804
|
+
<svg
|
|
7805
|
+
className="mx-auto mb-3 h-10 w-10 text-amber-500"
|
|
7806
|
+
fill="none"
|
|
7807
|
+
viewBox="0 0 24 24"
|
|
7808
|
+
stroke="currentColor"
|
|
7809
|
+
>
|
|
7810
|
+
<path
|
|
7811
|
+
strokeLinecap="round"
|
|
7812
|
+
strokeLinejoin="round"
|
|
7813
|
+
strokeWidth={1.5}
|
|
7814
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4.5c-.77-.833-2.694-.833-3.464 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
7815
|
+
/>
|
|
7816
|
+
</svg>
|
|
7817
|
+
<h3 className="text-foreground mb-1 text-lg font-semibold">{t('sandboxTitle')}</h3>
|
|
7818
|
+
<p className="text-muted-foreground mb-4 text-sm">{t('sandboxDescription')}</p>
|
|
7819
|
+
<button
|
|
7820
|
+
onClick={handleCompleteSandbox}
|
|
7821
|
+
className="inline-flex items-center rounded-md bg-amber-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-amber-600"
|
|
7822
|
+
>
|
|
7823
|
+
{t('completeTestOrder')}
|
|
7824
|
+
</button>
|
|
7825
|
+
</div>
|
|
7826
|
+
</div>
|
|
7827
|
+
);
|
|
7828
|
+
}
|
|
7829
|
+
|
|
7779
7830
|
if (sdk.renderType === 'sdk-widget') {
|
|
7780
7831
|
const containerId =
|
|
7781
7832
|
sdk.containerId || \`\${paymentIntent.provider || 'payment'}-payment-container\`;
|
|
@@ -9933,18 +9984,18 @@ import { useState } from 'react';
|
|
|
9933
9984
|
import Image from 'next/image';
|
|
9934
9985
|
import type { CartBundleOffer as CartBundleOfferType } from 'brainerce';
|
|
9935
9986
|
import { formatPrice } from 'brainerce';
|
|
9936
|
-
import { getClient } from '@/lib/brainerce';
|
|
9937
9987
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
9938
9988
|
import { useTranslations } from '@/lib/translations';
|
|
9939
9989
|
import { cn } from '@/lib/utils';
|
|
9940
9990
|
|
|
9941
9991
|
interface CartBundleOfferCardProps {
|
|
9942
9992
|
offer: CartBundleOfferType;
|
|
9993
|
+
cartId: string;
|
|
9943
9994
|
onAdd: () => void;
|
|
9944
9995
|
className?: string;
|
|
9945
9996
|
}
|
|
9946
9997
|
|
|
9947
|
-
export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOfferCardProps) {
|
|
9998
|
+
export function CartBundleOfferCard({ offer, cartId, onAdd, className }: CartBundleOfferCardProps) {
|
|
9948
9999
|
const { storeInfo } = useStoreInfo();
|
|
9949
10000
|
const t = useTranslations('cart');
|
|
9950
10001
|
const currency = storeInfo?.currency || 'USD';
|
|
@@ -9968,12 +10019,9 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9968
10019
|
if (adding) return;
|
|
9969
10020
|
try {
|
|
9970
10021
|
setAdding(true);
|
|
10022
|
+
const { getClient } = await import('@/lib/brainerce');
|
|
9971
10023
|
const client = getClient();
|
|
9972
|
-
await client.
|
|
9973
|
-
productId: product.id,
|
|
9974
|
-
variantId: offer.bundleVariantId || undefined,
|
|
9975
|
-
quantity: 1,
|
|
9976
|
-
});
|
|
10024
|
+
await client.addBundleToCart(cartId, offer.id);
|
|
9977
10025
|
onAdd();
|
|
9978
10026
|
} catch (err) {
|
|
9979
10027
|
console.error('Failed to add bundle item:', err);
|
package/dist/bin/stdio.js
CHANGED
|
@@ -3155,7 +3155,12 @@ export default function CartPage() {
|
|
|
3155
3155
|
<div className="mt-6 space-y-3">
|
|
3156
3156
|
<h3 className="text-foreground text-sm font-semibold">{t('bundleOffers')}</h3>
|
|
3157
3157
|
{bundles.bundles.map((offer) => (
|
|
3158
|
-
<CartBundleOfferCard
|
|
3158
|
+
<CartBundleOfferCard
|
|
3159
|
+
key={offer.id}
|
|
3160
|
+
offer={offer}
|
|
3161
|
+
cartId={cart.id}
|
|
3162
|
+
onAdd={refreshCart}
|
|
3163
|
+
/>
|
|
3159
3164
|
))}
|
|
3160
3165
|
</div>
|
|
3161
3166
|
)}
|
|
@@ -7652,8 +7657,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7652
7657
|
})
|
|
7653
7658
|
.catch(() => null);
|
|
7654
7659
|
|
|
7655
|
-
// B) Load + init SDK as early as possible
|
|
7660
|
+
// B) Load + init SDK as early as possible (skip for sandbox)
|
|
7656
7661
|
providerPromise.then((providerSdk) => {
|
|
7662
|
+
if (providerSdk?.renderType === 'sandbox') return;
|
|
7657
7663
|
if (providerSdk?.renderType === 'sdk-widget' && providerSdk.scriptUrl) {
|
|
7658
7664
|
currentSdk = providerSdk;
|
|
7659
7665
|
loadScript(providerSdk);
|
|
@@ -7680,6 +7686,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7680
7686
|
const sdk = resolveClientSdk(intent, providerSdk);
|
|
7681
7687
|
currentSdk = sdk;
|
|
7682
7688
|
|
|
7689
|
+
// Sandbox mode \u2014 no SDK to load, UI handles it
|
|
7690
|
+
if (sdk.renderType === 'sandbox') return;
|
|
7691
|
+
|
|
7683
7692
|
if (sdk.renderType === 'redirect') {
|
|
7684
7693
|
window.location.href = intent.clientSecret;
|
|
7685
7694
|
return;
|
|
@@ -7774,6 +7783,48 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7774
7783
|
|
|
7775
7784
|
const sdk = resolveClientSdk(paymentIntent, preloadedSdk);
|
|
7776
7785
|
|
|
7786
|
+
if (sdk.renderType === 'sandbox') {
|
|
7787
|
+
const handleCompleteSandbox = async () => {
|
|
7788
|
+
setLoading(true);
|
|
7789
|
+
try {
|
|
7790
|
+
const client = getClient();
|
|
7791
|
+
await client.completeGuestCheckout(checkoutId);
|
|
7792
|
+
window.location.href = \`/order-confirmation?checkout_id=\${checkoutId}\`;
|
|
7793
|
+
} catch (err) {
|
|
7794
|
+
setError(err instanceof Error ? err.message : t('paymentError'));
|
|
7795
|
+
setLoading(false);
|
|
7796
|
+
}
|
|
7797
|
+
};
|
|
7798
|
+
|
|
7799
|
+
return (
|
|
7800
|
+
<div className={cn('py-8 text-center', className)}>
|
|
7801
|
+
<div className="mx-auto max-w-md rounded-lg border border-amber-200 bg-amber-50 p-6">
|
|
7802
|
+
<svg
|
|
7803
|
+
className="mx-auto mb-3 h-10 w-10 text-amber-500"
|
|
7804
|
+
fill="none"
|
|
7805
|
+
viewBox="0 0 24 24"
|
|
7806
|
+
stroke="currentColor"
|
|
7807
|
+
>
|
|
7808
|
+
<path
|
|
7809
|
+
strokeLinecap="round"
|
|
7810
|
+
strokeLinejoin="round"
|
|
7811
|
+
strokeWidth={1.5}
|
|
7812
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4.5c-.77-.833-2.694-.833-3.464 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
7813
|
+
/>
|
|
7814
|
+
</svg>
|
|
7815
|
+
<h3 className="text-foreground mb-1 text-lg font-semibold">{t('sandboxTitle')}</h3>
|
|
7816
|
+
<p className="text-muted-foreground mb-4 text-sm">{t('sandboxDescription')}</p>
|
|
7817
|
+
<button
|
|
7818
|
+
onClick={handleCompleteSandbox}
|
|
7819
|
+
className="inline-flex items-center rounded-md bg-amber-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-amber-600"
|
|
7820
|
+
>
|
|
7821
|
+
{t('completeTestOrder')}
|
|
7822
|
+
</button>
|
|
7823
|
+
</div>
|
|
7824
|
+
</div>
|
|
7825
|
+
);
|
|
7826
|
+
}
|
|
7827
|
+
|
|
7777
7828
|
if (sdk.renderType === 'sdk-widget') {
|
|
7778
7829
|
const containerId =
|
|
7779
7830
|
sdk.containerId || \`\${paymentIntent.provider || 'payment'}-payment-container\`;
|
|
@@ -9931,18 +9982,18 @@ import { useState } from 'react';
|
|
|
9931
9982
|
import Image from 'next/image';
|
|
9932
9983
|
import type { CartBundleOffer as CartBundleOfferType } from 'brainerce';
|
|
9933
9984
|
import { formatPrice } from 'brainerce';
|
|
9934
|
-
import { getClient } from '@/lib/brainerce';
|
|
9935
9985
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
9936
9986
|
import { useTranslations } from '@/lib/translations';
|
|
9937
9987
|
import { cn } from '@/lib/utils';
|
|
9938
9988
|
|
|
9939
9989
|
interface CartBundleOfferCardProps {
|
|
9940
9990
|
offer: CartBundleOfferType;
|
|
9991
|
+
cartId: string;
|
|
9941
9992
|
onAdd: () => void;
|
|
9942
9993
|
className?: string;
|
|
9943
9994
|
}
|
|
9944
9995
|
|
|
9945
|
-
export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOfferCardProps) {
|
|
9996
|
+
export function CartBundleOfferCard({ offer, cartId, onAdd, className }: CartBundleOfferCardProps) {
|
|
9946
9997
|
const { storeInfo } = useStoreInfo();
|
|
9947
9998
|
const t = useTranslations('cart');
|
|
9948
9999
|
const currency = storeInfo?.currency || 'USD';
|
|
@@ -9966,12 +10017,9 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9966
10017
|
if (adding) return;
|
|
9967
10018
|
try {
|
|
9968
10019
|
setAdding(true);
|
|
10020
|
+
const { getClient } = await import('@/lib/brainerce');
|
|
9969
10021
|
const client = getClient();
|
|
9970
|
-
await client.
|
|
9971
|
-
productId: product.id,
|
|
9972
|
-
variantId: offer.bundleVariantId || undefined,
|
|
9973
|
-
quantity: 1,
|
|
9974
|
-
});
|
|
10022
|
+
await client.addBundleToCart(cartId, offer.id);
|
|
9975
10023
|
onAdd();
|
|
9976
10024
|
} catch (err) {
|
|
9977
10025
|
console.error('Failed to add bundle item:', err);
|
package/dist/index.js
CHANGED
|
@@ -3172,7 +3172,12 @@ export default function CartPage() {
|
|
|
3172
3172
|
<div className="mt-6 space-y-3">
|
|
3173
3173
|
<h3 className="text-foreground text-sm font-semibold">{t('bundleOffers')}</h3>
|
|
3174
3174
|
{bundles.bundles.map((offer) => (
|
|
3175
|
-
<CartBundleOfferCard
|
|
3175
|
+
<CartBundleOfferCard
|
|
3176
|
+
key={offer.id}
|
|
3177
|
+
offer={offer}
|
|
3178
|
+
cartId={cart.id}
|
|
3179
|
+
onAdd={refreshCart}
|
|
3180
|
+
/>
|
|
3176
3181
|
))}
|
|
3177
3182
|
</div>
|
|
3178
3183
|
)}
|
|
@@ -7669,8 +7674,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7669
7674
|
})
|
|
7670
7675
|
.catch(() => null);
|
|
7671
7676
|
|
|
7672
|
-
// B) Load + init SDK as early as possible
|
|
7677
|
+
// B) Load + init SDK as early as possible (skip for sandbox)
|
|
7673
7678
|
providerPromise.then((providerSdk) => {
|
|
7679
|
+
if (providerSdk?.renderType === 'sandbox') return;
|
|
7674
7680
|
if (providerSdk?.renderType === 'sdk-widget' && providerSdk.scriptUrl) {
|
|
7675
7681
|
currentSdk = providerSdk;
|
|
7676
7682
|
loadScript(providerSdk);
|
|
@@ -7697,6 +7703,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7697
7703
|
const sdk = resolveClientSdk(intent, providerSdk);
|
|
7698
7704
|
currentSdk = sdk;
|
|
7699
7705
|
|
|
7706
|
+
// Sandbox mode \u2014 no SDK to load, UI handles it
|
|
7707
|
+
if (sdk.renderType === 'sandbox') return;
|
|
7708
|
+
|
|
7700
7709
|
if (sdk.renderType === 'redirect') {
|
|
7701
7710
|
window.location.href = intent.clientSecret;
|
|
7702
7711
|
return;
|
|
@@ -7791,6 +7800,48 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7791
7800
|
|
|
7792
7801
|
const sdk = resolveClientSdk(paymentIntent, preloadedSdk);
|
|
7793
7802
|
|
|
7803
|
+
if (sdk.renderType === 'sandbox') {
|
|
7804
|
+
const handleCompleteSandbox = async () => {
|
|
7805
|
+
setLoading(true);
|
|
7806
|
+
try {
|
|
7807
|
+
const client = getClient();
|
|
7808
|
+
await client.completeGuestCheckout(checkoutId);
|
|
7809
|
+
window.location.href = \`/order-confirmation?checkout_id=\${checkoutId}\`;
|
|
7810
|
+
} catch (err) {
|
|
7811
|
+
setError(err instanceof Error ? err.message : t('paymentError'));
|
|
7812
|
+
setLoading(false);
|
|
7813
|
+
}
|
|
7814
|
+
};
|
|
7815
|
+
|
|
7816
|
+
return (
|
|
7817
|
+
<div className={cn('py-8 text-center', className)}>
|
|
7818
|
+
<div className="mx-auto max-w-md rounded-lg border border-amber-200 bg-amber-50 p-6">
|
|
7819
|
+
<svg
|
|
7820
|
+
className="mx-auto mb-3 h-10 w-10 text-amber-500"
|
|
7821
|
+
fill="none"
|
|
7822
|
+
viewBox="0 0 24 24"
|
|
7823
|
+
stroke="currentColor"
|
|
7824
|
+
>
|
|
7825
|
+
<path
|
|
7826
|
+
strokeLinecap="round"
|
|
7827
|
+
strokeLinejoin="round"
|
|
7828
|
+
strokeWidth={1.5}
|
|
7829
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4.5c-.77-.833-2.694-.833-3.464 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
7830
|
+
/>
|
|
7831
|
+
</svg>
|
|
7832
|
+
<h3 className="text-foreground mb-1 text-lg font-semibold">{t('sandboxTitle')}</h3>
|
|
7833
|
+
<p className="text-muted-foreground mb-4 text-sm">{t('sandboxDescription')}</p>
|
|
7834
|
+
<button
|
|
7835
|
+
onClick={handleCompleteSandbox}
|
|
7836
|
+
className="inline-flex items-center rounded-md bg-amber-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-amber-600"
|
|
7837
|
+
>
|
|
7838
|
+
{t('completeTestOrder')}
|
|
7839
|
+
</button>
|
|
7840
|
+
</div>
|
|
7841
|
+
</div>
|
|
7842
|
+
);
|
|
7843
|
+
}
|
|
7844
|
+
|
|
7794
7845
|
if (sdk.renderType === 'sdk-widget') {
|
|
7795
7846
|
const containerId =
|
|
7796
7847
|
sdk.containerId || \`\${paymentIntent.provider || 'payment'}-payment-container\`;
|
|
@@ -9948,18 +9999,18 @@ import { useState } from 'react';
|
|
|
9948
9999
|
import Image from 'next/image';
|
|
9949
10000
|
import type { CartBundleOffer as CartBundleOfferType } from 'brainerce';
|
|
9950
10001
|
import { formatPrice } from 'brainerce';
|
|
9951
|
-
import { getClient } from '@/lib/brainerce';
|
|
9952
10002
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
9953
10003
|
import { useTranslations } from '@/lib/translations';
|
|
9954
10004
|
import { cn } from '@/lib/utils';
|
|
9955
10005
|
|
|
9956
10006
|
interface CartBundleOfferCardProps {
|
|
9957
10007
|
offer: CartBundleOfferType;
|
|
10008
|
+
cartId: string;
|
|
9958
10009
|
onAdd: () => void;
|
|
9959
10010
|
className?: string;
|
|
9960
10011
|
}
|
|
9961
10012
|
|
|
9962
|
-
export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOfferCardProps) {
|
|
10013
|
+
export function CartBundleOfferCard({ offer, cartId, onAdd, className }: CartBundleOfferCardProps) {
|
|
9963
10014
|
const { storeInfo } = useStoreInfo();
|
|
9964
10015
|
const t = useTranslations('cart');
|
|
9965
10016
|
const currency = storeInfo?.currency || 'USD';
|
|
@@ -9983,12 +10034,9 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9983
10034
|
if (adding) return;
|
|
9984
10035
|
try {
|
|
9985
10036
|
setAdding(true);
|
|
10037
|
+
const { getClient } = await import('@/lib/brainerce');
|
|
9986
10038
|
const client = getClient();
|
|
9987
|
-
await client.
|
|
9988
|
-
productId: product.id,
|
|
9989
|
-
variantId: offer.bundleVariantId || undefined,
|
|
9990
|
-
quantity: 1,
|
|
9991
|
-
});
|
|
10039
|
+
await client.addBundleToCart(cartId, offer.id);
|
|
9992
10040
|
onAdd();
|
|
9993
10041
|
} catch (err) {
|
|
9994
10042
|
console.error('Failed to add bundle item:', err);
|
package/dist/index.mjs
CHANGED
|
@@ -3127,7 +3127,12 @@ export default function CartPage() {
|
|
|
3127
3127
|
<div className="mt-6 space-y-3">
|
|
3128
3128
|
<h3 className="text-foreground text-sm font-semibold">{t('bundleOffers')}</h3>
|
|
3129
3129
|
{bundles.bundles.map((offer) => (
|
|
3130
|
-
<CartBundleOfferCard
|
|
3130
|
+
<CartBundleOfferCard
|
|
3131
|
+
key={offer.id}
|
|
3132
|
+
offer={offer}
|
|
3133
|
+
cartId={cart.id}
|
|
3134
|
+
onAdd={refreshCart}
|
|
3135
|
+
/>
|
|
3131
3136
|
))}
|
|
3132
3137
|
</div>
|
|
3133
3138
|
)}
|
|
@@ -7624,8 +7629,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7624
7629
|
})
|
|
7625
7630
|
.catch(() => null);
|
|
7626
7631
|
|
|
7627
|
-
// B) Load + init SDK as early as possible
|
|
7632
|
+
// B) Load + init SDK as early as possible (skip for sandbox)
|
|
7628
7633
|
providerPromise.then((providerSdk) => {
|
|
7634
|
+
if (providerSdk?.renderType === 'sandbox') return;
|
|
7629
7635
|
if (providerSdk?.renderType === 'sdk-widget' && providerSdk.scriptUrl) {
|
|
7630
7636
|
currentSdk = providerSdk;
|
|
7631
7637
|
loadScript(providerSdk);
|
|
@@ -7652,6 +7658,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7652
7658
|
const sdk = resolveClientSdk(intent, providerSdk);
|
|
7653
7659
|
currentSdk = sdk;
|
|
7654
7660
|
|
|
7661
|
+
// Sandbox mode \u2014 no SDK to load, UI handles it
|
|
7662
|
+
if (sdk.renderType === 'sandbox') return;
|
|
7663
|
+
|
|
7655
7664
|
if (sdk.renderType === 'redirect') {
|
|
7656
7665
|
window.location.href = intent.clientSecret;
|
|
7657
7666
|
return;
|
|
@@ -7746,6 +7755,48 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
|
|
|
7746
7755
|
|
|
7747
7756
|
const sdk = resolveClientSdk(paymentIntent, preloadedSdk);
|
|
7748
7757
|
|
|
7758
|
+
if (sdk.renderType === 'sandbox') {
|
|
7759
|
+
const handleCompleteSandbox = async () => {
|
|
7760
|
+
setLoading(true);
|
|
7761
|
+
try {
|
|
7762
|
+
const client = getClient();
|
|
7763
|
+
await client.completeGuestCheckout(checkoutId);
|
|
7764
|
+
window.location.href = \`/order-confirmation?checkout_id=\${checkoutId}\`;
|
|
7765
|
+
} catch (err) {
|
|
7766
|
+
setError(err instanceof Error ? err.message : t('paymentError'));
|
|
7767
|
+
setLoading(false);
|
|
7768
|
+
}
|
|
7769
|
+
};
|
|
7770
|
+
|
|
7771
|
+
return (
|
|
7772
|
+
<div className={cn('py-8 text-center', className)}>
|
|
7773
|
+
<div className="mx-auto max-w-md rounded-lg border border-amber-200 bg-amber-50 p-6">
|
|
7774
|
+
<svg
|
|
7775
|
+
className="mx-auto mb-3 h-10 w-10 text-amber-500"
|
|
7776
|
+
fill="none"
|
|
7777
|
+
viewBox="0 0 24 24"
|
|
7778
|
+
stroke="currentColor"
|
|
7779
|
+
>
|
|
7780
|
+
<path
|
|
7781
|
+
strokeLinecap="round"
|
|
7782
|
+
strokeLinejoin="round"
|
|
7783
|
+
strokeWidth={1.5}
|
|
7784
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4.5c-.77-.833-2.694-.833-3.464 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
7785
|
+
/>
|
|
7786
|
+
</svg>
|
|
7787
|
+
<h3 className="text-foreground mb-1 text-lg font-semibold">{t('sandboxTitle')}</h3>
|
|
7788
|
+
<p className="text-muted-foreground mb-4 text-sm">{t('sandboxDescription')}</p>
|
|
7789
|
+
<button
|
|
7790
|
+
onClick={handleCompleteSandbox}
|
|
7791
|
+
className="inline-flex items-center rounded-md bg-amber-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-amber-600"
|
|
7792
|
+
>
|
|
7793
|
+
{t('completeTestOrder')}
|
|
7794
|
+
</button>
|
|
7795
|
+
</div>
|
|
7796
|
+
</div>
|
|
7797
|
+
);
|
|
7798
|
+
}
|
|
7799
|
+
|
|
7749
7800
|
if (sdk.renderType === 'sdk-widget') {
|
|
7750
7801
|
const containerId =
|
|
7751
7802
|
sdk.containerId || \`\${paymentIntent.provider || 'payment'}-payment-container\`;
|
|
@@ -9903,18 +9954,18 @@ import { useState } from 'react';
|
|
|
9903
9954
|
import Image from 'next/image';
|
|
9904
9955
|
import type { CartBundleOffer as CartBundleOfferType } from 'brainerce';
|
|
9905
9956
|
import { formatPrice } from 'brainerce';
|
|
9906
|
-
import { getClient } from '@/lib/brainerce';
|
|
9907
9957
|
import { useStoreInfo } from '@/providers/store-provider';
|
|
9908
9958
|
import { useTranslations } from '@/lib/translations';
|
|
9909
9959
|
import { cn } from '@/lib/utils';
|
|
9910
9960
|
|
|
9911
9961
|
interface CartBundleOfferCardProps {
|
|
9912
9962
|
offer: CartBundleOfferType;
|
|
9963
|
+
cartId: string;
|
|
9913
9964
|
onAdd: () => void;
|
|
9914
9965
|
className?: string;
|
|
9915
9966
|
}
|
|
9916
9967
|
|
|
9917
|
-
export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOfferCardProps) {
|
|
9968
|
+
export function CartBundleOfferCard({ offer, cartId, onAdd, className }: CartBundleOfferCardProps) {
|
|
9918
9969
|
const { storeInfo } = useStoreInfo();
|
|
9919
9970
|
const t = useTranslations('cart');
|
|
9920
9971
|
const currency = storeInfo?.currency || 'USD';
|
|
@@ -9938,12 +9989,9 @@ export function CartBundleOfferCard({ offer, onAdd, className }: CartBundleOffer
|
|
|
9938
9989
|
if (adding) return;
|
|
9939
9990
|
try {
|
|
9940
9991
|
setAdding(true);
|
|
9992
|
+
const { getClient } = await import('@/lib/brainerce');
|
|
9941
9993
|
const client = getClient();
|
|
9942
|
-
await client.
|
|
9943
|
-
productId: product.id,
|
|
9944
|
-
variantId: offer.bundleVariantId || undefined,
|
|
9945
|
-
quantity: 1,
|
|
9946
|
-
});
|
|
9994
|
+
await client.addBundleToCart(cartId, offer.id);
|
|
9947
9995
|
onAdd();
|
|
9948
9996
|
} catch (err) {
|
|
9949
9997
|
console.error('Failed to add bundle item:', err);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainerce/mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
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"
|