diff --git a/packages/auth/components/login.tsx b/packages/auth/components/login.tsx index 31aa2bcc..7f73b324 100644 --- a/packages/auth/components/login.tsx +++ b/packages/auth/components/login.tsx @@ -98,14 +98,16 @@ const Login: React.FC<{ ) : (
-
- {returnToUrl && ( - - )} - {!hideHeader &&

Login

} -
+ {!hideHeader && ( +
+ {returnToUrl && ( + + )} +

Login

+
+ )} {redirectUrl === 'checkout' &&

You will be redirected to checkout after login.

}

- or -

diff --git a/packages/auth/package.json b/packages/auth/package.json index 76672c13..c00ea959 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@hanzo/auth", - "version": "2.0.0", + "version": "2.0.1", "description": "Library with Firebase authentication.", "publishConfig": { "registry": "https://registry.npmjs.org/", diff --git a/packages/commerce/components/checkout/contact-info.tsx b/packages/commerce/components/checkout/contact-info.tsx deleted file mode 100644 index e340e430..00000000 --- a/packages/commerce/components/checkout/contact-info.tsx +++ /dev/null @@ -1,83 +0,0 @@ -'use client' - -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@hanzo/ui/primitives/form' -import { Input, Button } from '@hanzo/ui/primitives' -import { User } from 'lucide-react' -import { EnhHeadingBlockComponent, type EnhHeadingBlock } from '@hanzo/ui/blocks' -import type { UseFormReturn } from 'react-hook-form' - -const ContactInfo: React.FC<{ - form: UseFormReturn<{ - name: string; - email: string; - }, any, { - name: string; - email: string; - }>, - selectPaymentMethod: (method: 'crypto' | 'bank') => Promise, -}> = ({ - form, - selectPaymentMethod, -}) => { - return ( -
- -
-
- ( - - Name - - - - - - )} - /> - ( - - Email - - - - - - )} - /> -
-
- - -
-
-
- - ) -} - -export default ContactInfo \ No newline at end of file diff --git a/packages/commerce/components/checkout/index.tsx b/packages/commerce/components/checkout/index.tsx index 42304e4d..a3ec33af 100644 --- a/packages/commerce/components/checkout/index.tsx +++ b/packages/commerce/components/checkout/index.tsx @@ -1,13 +1,9 @@ 'use client' -import { useEffect, useState } from 'react' +import { useState } from 'react' import { ChevronLeft } from 'lucide-react' import { observer } from 'mobx-react-lite' -import { zodResolver } from '@hookform/resolvers/zod' -import * as z from 'zod' -import { useForm } from 'react-hook-form' - import { Button, Main, Separator, Toaster } from '@hanzo/ui/primitives' import { cn } from '@hanzo/ui/util' import { useAuth } from '@hanzo/auth/service' @@ -15,85 +11,41 @@ import { LoginComponent, AuthWidget } from '@hanzo/auth/components' import ShippingInfo from './shipping-info' import ThankYou from './thank-you' -import PayWithCrypto from './pay-with-crypto' -import PayByBankTransfer from './pay-by-bank-transfer' -import ContactInfo from './contact-info' import { Cart } from '..' -import { useCommerce } from '../../service/context' - -const contactFormSchema = z.object({ - name: z.string().min(2, 'Name must be at least 2 characters.'), - email: z.string().email(), -}) +import Payment from './payment' const Checkout: React.FC<{toggleCheckout: () => void}> = observer(({toggleCheckout}) => { const auth = useAuth() - const cmmc = useCommerce() const [currentStep, setCurrentStep] = useState(1) - const [paymentMethod, setPaymentMethod] = useState<'crypto' | 'bank' | undefined>() const [orderId, setOrderId] = useState() - const contactForm = useForm>({ - resolver: zodResolver(contactFormSchema), - defaultValues: { - name: auth.user?.displayName ?? '', - email: auth.user?.email ?? '', - }, - }) - - useEffect(() => { - if (auth.loggedIn) { - contactForm.setValue('name', auth.user?.displayName ?? '') - contactForm.setValue('email', auth.user?.email ?? '') - } - }, [auth.loggedIn]) - - const selectPaymentMethod = async (method: 'crypto' | 'bank') => { - contactForm.handleSubmit(async () => { - if (auth.user) { - if (!!orderId) { - await cmmc.updateOrder(orderId, auth.user.email, method) - } else { - const id = await cmmc.createOrder(auth.user.email, method) - setOrderId(id) - } - } - setPaymentMethod(method) - setCurrentStep(2) - })() - } - - const step1 = auth.loggedIn ? ( - + ) : ( ) - const step2 = paymentMethod === 'crypto' ? ( - - ) : ( - - ) - - const step3 = ( - + const step2 = ( + ) - const step4 = + const step3 = - const steps = [step1, step2, step3, step4] + const steps = [step1, step2, step3] return ( -
+
-
+
-
+
-
Contact
+
Payment
-
Payment
+
Delivery
-
Delivery
+
Done!
{steps[currentStep - 1]} diff --git a/packages/commerce/components/checkout/pay-by-bank-transfer.tsx b/packages/commerce/components/checkout/pay-by-bank-transfer.tsx deleted file mode 100644 index cb02c5ef..00000000 --- a/packages/commerce/components/checkout/pay-by-bank-transfer.tsx +++ /dev/null @@ -1,76 +0,0 @@ -'use client' - -import type { ReactNode } from 'react' -import { Copy } from 'lucide-react' - -import { Button, Tabs, TabsContent, TabsList, TabsTrigger, toast } from '@hanzo/ui/primitives' -import { EnhHeadingBlockComponent, type EnhHeadingBlock, type Block } from '@hanzo/ui/blocks' - -const InfoField: React.FC<{label: string, value: ReactNode, copyValue: string}> = ({label, value, copyValue}) => { - const copyToClipboard = (label: string, text: string) => { - navigator.clipboard.writeText(text) - toast({title: `${label} copied to clipboard`}) - } - - return ( -
-

{label}

-
- {value} - -
-
- ) -} - -const PayByBankTransfer: React.FC<{setCurrentStep: (step: number) => void}> = ({setCurrentStep}) => { - return (<> - - - USD - EUR/GBP - - -
- Bank of America
NA 222 Broadway
New York, New York. 10038
} - copyValue='Bank of America, NA 222 Broadway, New York, New York. 10038' - /> - Hanzo, Inc
4811 Mastin Street
Merriam, KS 66203
} - copyValue='Hanzo, Inc, 4811 Mastin Street, Merriam, KS 66203' - /> - - - - -
- - -
- Clear Junction Limited
4th floor
Imperial House
} - copyValue='Clear Junction Limited, 4th floor, Imperial House' - /> - - - - - - -
- - -
- - -
- ) -} - -export default PayByBankTransfer diff --git a/packages/commerce/components/checkout/payment/contact-info.tsx b/packages/commerce/components/checkout/payment/contact-info.tsx new file mode 100644 index 00000000..90480775 --- /dev/null +++ b/packages/commerce/components/checkout/payment/contact-info.tsx @@ -0,0 +1,59 @@ +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@hanzo/ui/primitives/form' +import { Input } from '@hanzo/ui/primitives' +import type { UseFormReturn } from 'react-hook-form' + +const ContactInfo: React.FC<{ + form: UseFormReturn<{ + name: string + email: string + }, any, { + name: string + email: string + }>, +}> = ({ + form, +}) => { + return ( +
+ +
+ ( + + Full name + + + + + + )} + /> + ( + + Email + + + + + + )} + /> +
+
+ + ) +} + +export default ContactInfo \ No newline at end of file diff --git a/packages/commerce/components/checkout/payment/index.tsx b/packages/commerce/components/checkout/payment/index.tsx new file mode 100644 index 00000000..0047edf8 --- /dev/null +++ b/packages/commerce/components/checkout/payment/index.tsx @@ -0,0 +1,117 @@ +'use client' + +import { useEffect, useState } from 'react' +import { observer } from 'mobx-react-lite' + +import { zodResolver } from '@hookform/resolvers/zod' +import * as z from 'zod' +import { useForm } from 'react-hook-form' + +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@hanzo/ui/primitives' +import { useAuth } from '@hanzo/auth/service' +import PayWithCrypto from './pay-with-crypto' +import PayWithBankTransfer from './pay-with-bank-transfer' +import PayWithCard from './pay-with-card' +import { useCommerce, type TransactionStatus } from '../../..' + +const contactFormSchema = z.object({ + name: z.string().min(1, 'Enter your full name.'), + email: z.string().email(), +}) + +const Payment: React.FC<{ + setCurrentStep: (currentStep: number) => void + orderId?: string + setOrderId: (orderId?: string) => void +}> = observer(({ + setCurrentStep, + orderId, + setOrderId +}) => { + const cmmc = useCommerce() + const auth = useAuth() + const [transactionStatus, setTransactionStatus] = useState('unpaid') + + const contactForm = useForm>({ + resolver: zodResolver(contactFormSchema), + defaultValues: { + name: auth.user?.displayName ?? '', + email: auth.user?.email ?? '', + }, + }) + + useEffect(() => { + if (auth.loggedIn) { + contactForm.setValue('name', auth.user?.displayName ?? '') + contactForm.setValue('email', auth.user?.email ?? '') + } + }, [auth.loggedIn]) + + const storePaymentInfo = async (paymentInfo: any) => { + if (auth.user) { + const {name, email} = contactForm.getValues() + let id + if (!orderId) { + id = await cmmc.createOrder(email ? email : auth.user.email, name) + setOrderId(id) + } + if (id) { + await cmmc.updateOrderPaymentInfo(id, paymentInfo) + } + } + } + + return ( + + + + PAY WITH CARD + + + PAY WITH CRYPTO + + + BANK TRANSFER + + + + + + + + + + + + + ) +}) + +export default Payment diff --git a/packages/commerce/components/checkout/payment/pay-with-bank-transfer.tsx b/packages/commerce/components/checkout/payment/pay-with-bank-transfer.tsx new file mode 100644 index 00000000..01bba1d1 --- /dev/null +++ b/packages/commerce/components/checkout/payment/pay-with-bank-transfer.tsx @@ -0,0 +1,106 @@ +'use client' + +import type { ReactNode } from 'react' +import { Copy } from 'lucide-react' +import type { UseFormReturn } from 'react-hook-form' + +import { Button, Tabs, TabsContent, TabsList, TabsTrigger, toast } from '@hanzo/ui/primitives' +import ContactInfo from './contact-info' + +const InfoField: React.FC<{ + label: string, + value: ReactNode, + copyValue: string +}> = ({ + label, + value, + copyValue +}) => { + const copyToClipboard = (label: string, text: string) => { + navigator.clipboard.writeText(text) + toast({title: `${label} copied to clipboard`}) + } + + return ( +
+

{label}

+
+ {value} + +
+
+ ) +} + +const PayWithBankTransfer: React.FC<{ + setCurrentStep: (step: number) => void + storePaymentInfo: (paymentInfo: any) => Promise + contactForm: UseFormReturn<{ + name: string + email: string + }, any, { + name: string + email: string + }> +}> = ({ + setCurrentStep, + storePaymentInfo, + contactForm +}) => { + const payByBankTransfer = async () => { + contactForm.handleSubmit(async () => { + await storePaymentInfo({paymentMethod: 'bank-transfer'}) + setCurrentStep(2) + })() + } + + return ( +
+ + + + USD + EUR/GBP + + +
+ Bank of America
NA 222 Broadway
New York, New York. 10038
} + copyValue='Bank of America, NA 222 Broadway, New York, New York. 10038' + /> + Hanzo, Inc
4811 Mastin Street
Merriam, KS 66203
} + copyValue='Hanzo, Inc, 4811 Mastin Street, Merriam, KS 66203' + /> + + + + +
+ + +
+ Clear Junction Limited
4th floor
Imperial House
} + copyValue='Clear Junction Limited, 4th floor, Imperial House' + /> + + + + + + +
+ + + +
+ ) +} + +export default PayWithBankTransfer diff --git a/packages/commerce/components/checkout/payment/pay-with-card.tsx b/packages/commerce/components/checkout/payment/pay-with-card.tsx new file mode 100644 index 00000000..5d8e0eab --- /dev/null +++ b/packages/commerce/components/checkout/payment/pay-with-card.tsx @@ -0,0 +1,193 @@ +'use client' + +// @ts-ignore +import { ApplePay, GooglePay, CreditCard, PaymentForm } from 'react-square-web-payments-sdk' +import type { UseFormReturn } from 'react-hook-form' +import { ApplyTypography, Button } from '@hanzo/ui/primitives' +import { useCommerce, type TransactionStatus } from '../../..' +import PaymentMethods from './payment-methods' +import { processSquareCardPayment } from '../../../util' +import ContactInfo from './contact-info' + +const PayWithCard: React.FC<{ + setCurrentStep: (currentStep: number) => void + transactionStatus: TransactionStatus + setTransactionStatus: (status: TransactionStatus) => void + storePaymentInfo: (paymentInfo: any) => Promise + contactForm: UseFormReturn<{ + name: string + email: string + }, any, { + name: string + email: string + }> +}> = ({ + setCurrentStep, + transactionStatus, + setTransactionStatus, + storePaymentInfo, + contactForm, +}) => { + const cmmc = useCommerce() + + const cardTokenizeResponseReceived = async ( + token: any, + verifiedBuyer: any + ) => { + contactForm.handleSubmit(async () => { + setTransactionStatus('paid') + const res = await processSquareCardPayment(token.token, cmmc.cartTotal, verifiedBuyer.token) + if (res) { + console.log(token) + await storePaymentInfo({paymentMethod: token.details.method ?? null, processed: res}) + setTransactionStatus('confirmed') + } else { + setTransactionStatus('error') + } + })() + } + + const createVerificationDetails = () => { + const {name, email} = contactForm.getValues() + return { + amount: cmmc.cartTotal.toFixed(2), + billingContact: { + givenName: name, + email, + }, + currencyCode: 'USD', + intent: 'CHARGE', + } + } + + const createPaymentRequest= () => ({ + countryCode: "US", + currencyCode: "USD", + lineItems: cmmc.cartItems.map(item => ({ + amount: item.price.toFixed(2), + label: item.title, + id: item.sku, + })), + requestBillingContact: false, + requestShippingContact: false, + total: { + amount: cmmc.cartTotal.toFixed(2), + label: "Total", + }, + }) + + return ( + +
+ {transactionStatus === 'confirmed' ? ( + +
Payment confirmed!
+

Thank you for your purchase.

+ +
+ ) : transactionStatus === 'paid' ? ( + +
Processing your payment...
+
+ ) : ( + <> + + + +

+


or pay with card
+

+ + + + + + {/* Imitates hanzo/ui Button and Input styles, I was unable to render the + hanzo/ui button outright and keeping the submit form functionality*/} + + {transactionStatus === 'error' && ( + +

There was an error processing your payment.

+
+ )} + + )} +
+
+ ) +} + +export default PayWithCard \ No newline at end of file diff --git a/packages/commerce/components/checkout/pay-with-crypto.tsx b/packages/commerce/components/checkout/payment/pay-with-crypto.tsx similarity index 78% rename from packages/commerce/components/checkout/pay-with-crypto.tsx rename to packages/commerce/components/checkout/payment/pay-with-crypto.tsx index a256d007..31c81f89 100644 --- a/packages/commerce/components/checkout/pay-with-crypto.tsx +++ b/packages/commerce/components/checkout/payment/pay-with-crypto.tsx @@ -22,11 +22,9 @@ import { import { useAuth } from '@hanzo/auth/service' import { Ethereum as EthIconFromAuth } from '@hanzo/auth/icons' -import Eth from './icons/eth' -import Btc from './icons/btc' -import Usdt from './icons/usdt' -import { useCommerce } from '../..' -import { formatPrice } from '../../util' +import Eth from '../icons/eth' +import { useCommerce, type TransactionStatus } from '../../..' +import { formatPrice } from '../../../util' declare global { interface Window{ @@ -36,10 +34,15 @@ declare global { const PayWithCrypto: React.FC<{ setCurrentStep: (currentStep: number) => void + transactionStatus: TransactionStatus + setTransactionStatus: (status: TransactionStatus) => void + storePaymentInfo: (paymentInfo: any) => Promise }> = observer(({ - setCurrentStep + setCurrentStep, + transactionStatus, + setTransactionStatus, + storePaymentInfo }) => { - const c = useCommerce() const auth = useAuth() const [loadingPrice, setLoadingPrice] = useState(false) @@ -47,7 +50,6 @@ const PayWithCrypto: React.FC<{ const [amount, setAmount] = useState() const [availableAmount, setAvailableAmount] = useState() const [provider, setProvider] = useState() - const [transactionStatus, setTransactionStatus] = useState<'unpaid' | 'paid' | 'confirmed' | 'error'>('unpaid') //const selectedToken = 'eth' @@ -126,12 +128,17 @@ const PayWithCrypto: React.FC<{ setTransactionStatus('paid') provider.waitForTransaction(tx.hash) - .then((receipt) => { + .then(async (receipt) => { console.log(receipt) + await storePaymentInfo({ + ether, + addr: process.env.NEXT_PUBLIC_ETH_PAYMENT_ADDRESS, + receipt + }) setTransactionStatus('confirmed') }) .catch((error) => { - console.log(error) + console.error(error) setTransactionStatus('error') }) } catch (err) { @@ -141,9 +148,20 @@ const PayWithCrypto: React.FC<{ } } - const payWidget = !!!(auth.user?.walletAddress) ? ( + const nextStep = async () => { + await storePaymentInfo({ + paymentMethod: 'crypto' + }) + setCurrentStep(2) + } + + const cryptoPriceWidget = !!!(auth.user?.walletAddress) ? (
-
@@ -165,30 +183,35 @@ const PayWithCrypto: React.FC<{
Available funds in your wallet: {availableAmount} ETH
-
ETH
+
+ + ETH +
- {transactionStatus === 'unpaid' || transactionStatus === 'error' ? ( - + {transactionStatus === 'error' ? ( +

There was an error while confirming the transaction.

) : transactionStatus === 'paid' ? (

Waiting for transaction to be confirmed on chain.

- ) : ( + ) : transactionStatus === 'confirmed' ? (

Transaction confirmed!

- )} + ) : null} ) return ( -
- {payWidget} -
- - -
+
+ {cryptoPriceWidget} + {transactionStatus === 'unpaid' ? ( + + ) : ( + + )}
) }) diff --git a/packages/commerce/components/checkout/payment/payment-methods/amex.tsx b/packages/commerce/components/checkout/payment/payment-methods/amex.tsx new file mode 100644 index 00000000..bf71d5f3 --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/amex.tsx @@ -0,0 +1,32 @@ +import React from 'react' +import { type LucideProps } from 'lucide-react' + +const Amex: React.FC = (props: LucideProps) => ( + + American Express + + + + + + + +) + +export default Amex diff --git a/packages/commerce/components/checkout/payment/payment-methods/diners-club.tsx b/packages/commerce/components/checkout/payment/payment-methods/diners-club.tsx new file mode 100644 index 00000000..4844592a --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/diners-club.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import { type LucideProps } from 'lucide-react' + +const DinersClub: React.FC = (props: LucideProps) => ( + + + + + + +) + +export default DinersClub diff --git a/packages/commerce/components/checkout/payment/payment-methods/discover.tsx b/packages/commerce/components/checkout/payment/payment-methods/discover.tsx new file mode 100644 index 00000000..324097e5 --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/discover.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import { type LucideProps } from 'lucide-react' + +const Discover: React.FC = (props: LucideProps) => ( + + Discover + + + + + + +) + +export default Discover diff --git a/packages/commerce/components/checkout/payment/payment-methods/index.tsx b/packages/commerce/components/checkout/payment/payment-methods/index.tsx new file mode 100644 index 00000000..aea17e35 --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/index.tsx @@ -0,0 +1,24 @@ +import { LockKeyhole } from 'lucide-react' +import Amex from './amex' +import Discover from './discover' +import Mastercard from './mastercard' +import Visa from './visa' +import DinersClub from './diners-club' +import Jcb from './jcb' + +const PaymentMethods: React.FC = () => { + return ( +
+ + Secure payments with + + + + + + +
+ ) +} + +export default PaymentMethods diff --git a/packages/commerce/components/checkout/payment/payment-methods/jcb.tsx b/packages/commerce/components/checkout/payment/payment-methods/jcb.tsx new file mode 100644 index 00000000..1ecc4cf9 --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/jcb.tsx @@ -0,0 +1,26 @@ +import React from 'react' +import { type LucideProps } from 'lucide-react' + +const Jcb: React.FC = (props: LucideProps) => ( + + + + + + + + + + + + + + + + + + + +) + +export default Jcb diff --git a/packages/commerce/components/checkout/payment/payment-methods/mastercard.tsx b/packages/commerce/components/checkout/payment/payment-methods/mastercard.tsx new file mode 100644 index 00000000..09ac5ace --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/mastercard.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { type LucideProps } from 'lucide-react' + +const Mastercard: React.FC = (props: LucideProps) => ( + + Mastercard + + + + + + +) + +export default Mastercard diff --git a/packages/commerce/components/checkout/payment/payment-methods/visa.tsx b/packages/commerce/components/checkout/payment/payment-methods/visa.tsx new file mode 100644 index 00000000..bc0a9ce2 --- /dev/null +++ b/packages/commerce/components/checkout/payment/payment-methods/visa.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import { type LucideProps } from 'lucide-react' + +const Visa: React.FC = (props: LucideProps) => ( + + Visa + + + + +) + +export default Visa diff --git a/packages/commerce/components/checkout/shipping-info.tsx b/packages/commerce/components/checkout/shipping-info.tsx index 7d6fbbc6..eff41ba8 100644 --- a/packages/commerce/components/checkout/shipping-info.tsx +++ b/packages/commerce/components/checkout/shipping-info.tsx @@ -40,11 +40,9 @@ const shippingFormSchema = z.object({ const ShippingInfo: React.FC<{ orderId?: string, - paymentMethod?: string, setCurrentStep: (currentStep: number) => void }> = ({ orderId, - paymentMethod, setCurrentStep }) => { const auth = useAuth() @@ -65,10 +63,10 @@ const ShippingInfo: React.FC<{ }) const onSubmit = async (values: z.infer) => { - if (auth.user && orderId && paymentMethod) { - await cmmc.updateOrder(orderId, auth.user.email, paymentMethod, values) + if (auth.user && orderId) { + await cmmc.updateOrderShippingInfo(orderId, values) } - setCurrentStep(4) + setCurrentStep(3) } return ( @@ -198,11 +196,7 @@ const ShippingInfo: React.FC<{ />
- -
- - -
+ ) diff --git a/packages/commerce/package.json b/packages/commerce/package.json index 5c70d1d0..082264cb 100644 --- a/packages/commerce/package.json +++ b/packages/commerce/package.json @@ -1,6 +1,6 @@ { "name": "@hanzo/commerce", - "version": "2.0.0", + "version": "2.1.0", "description": "Library with shopping cart components.", "publishConfig": { "registry": "https://registry.npmjs.org/", @@ -29,10 +29,12 @@ "dependencies": { "ethers": "^6.11.1", "next-usequerystate": "^1.17.0", - "react-mobile-picker": "^1.0.0" + "react-mobile-picker": "^1.0.0", + "react-square-web-payments-sdk": "^3.2.1", + "square": "^35.0.0" }, "peerDependencies": { - "@hanzo/auth": "^2.0.0", + "@hanzo/auth": "^2.0.1", "@hanzo/ui": "^3.0.0", "@hookform/resolvers": "^3.3.4", "firebase": "^10.8.0", diff --git a/packages/commerce/service/impls/standalone/orders/index.ts b/packages/commerce/service/impls/standalone/orders/index.ts index 2a656245..078ba887 100644 --- a/packages/commerce/service/impls/standalone/orders/index.ts +++ b/packages/commerce/service/impls/standalone/orders/index.ts @@ -23,9 +23,10 @@ const getDBInstance = (name: string): Firestore => { interface SavedOrder { email: string - paymentMethod: string + name: string // TODO: add shippingInfo type shippingInfo?: any + paymentInfo?: any status: string timestamp: FieldValue items: ActualLineItemSnapshot[] @@ -33,16 +34,16 @@ interface SavedOrder { const createOrder = async ( email: string, - paymentMethod: string, items: ActualLineItemSnapshot[], options: { dbName: string ordersTable: string - } + }, + name?: string ): Promise<{ success: boolean, error: any, - id?: string + id?: string, }> => { let error: any | null = null @@ -52,7 +53,7 @@ const createOrder = async ( try { await setDoc(doc(ordersRef, orderId), { email, - paymentMethod, + name: name ?? '', status: 'open', timestamp: serverTimestamp(), items, @@ -67,17 +68,13 @@ const createOrder = async ( return { success: !error, error } } -const updateOrder = async ( +const updateOrderShippingInfo = async ( orderId: string, - email: string, - paymentMethod: string, - // TODO: add shippingInfo type - items: ActualLineItemSnapshot[], + shippingInfo: any, options: { dbName: string ordersTable: string - }, - shippingInfo?: any + } ): Promise<{ success: boolean, error: any @@ -88,20 +85,45 @@ const updateOrder = async ( try { await setDoc(doc(ordersRef, orderId), { - email, - paymentMethod, shippingInfo, - status: 'open', timestamp: serverTimestamp(), - items, - } satisfies SavedOrder) + }, { merge: true }) } catch (e) { - console.error('Error writing item document: ', e) - error = e + console.error('Error writing item document: ', e) + error = e + } + + return { success: !error, error } +} + +const updateOrderPaymentInfo = async ( + orderId: string, + paymentInfo: any, + options: { + dbName: string + ordersTable: string + } +): Promise<{ + success: boolean, + error: any +}> => { + + let error: any | null = null + const ordersRef = collection(getDBInstance(options.dbName), options.ordersTable) + + try { + await setDoc(doc(ordersRef, orderId), { + paymentInfo, + timestamp: serverTimestamp(), + }, { merge: true }) + } + catch (e) { + console.error('Error writing item document: ', e) + error = e } return { success: !error, error } } -export { createOrder, updateOrder } \ No newline at end of file +export { createOrder, updateOrderShippingInfo, updateOrderPaymentInfo } \ No newline at end of file diff --git a/packages/commerce/service/impls/standalone/standalone-service.ts b/packages/commerce/service/impls/standalone/standalone-service.ts index e20c3978..8fe20bab 100644 --- a/packages/commerce/service/impls/standalone/standalone-service.ts +++ b/packages/commerce/service/impls/standalone/standalone-service.ts @@ -17,7 +17,8 @@ import type { import { createOrder as createOrderHelper, - updateOrder as updateOrderHelper + updateOrderShippingInfo as updateOrderShippingInfoHelper, + updateOrderPaymentInfo as updateOrderPaymentInfoHelper } from './orders' import ActualLineItem, { type ActualLineItemSnapshot } from './actual-line-item' @@ -88,16 +89,20 @@ class StandaloneService }) } - async createOrder(email: string, paymentMethod: string): Promise { + async createOrder(email: string, name?: string): Promise { const snapshot = this.takeSnapshot() - const order = await createOrderHelper(email, paymentMethod, snapshot.items, this._options) // didn't want to have two levels of 'items' + const order = await createOrderHelper(email, snapshot.items, this._options, name) // didn't want to have two levels of 'items' return order.id } // TODO: add shippingInfo type - async updateOrder(orderId: string, email: string, paymentMethod: string, shippingInfo?: any): Promise { - const snapshot = this.takeSnapshot() - updateOrderHelper(orderId, email, paymentMethod, snapshot.items, this._options, shippingInfo) // didn't want to have two levels of 'items' + async updateOrderShippingInfo(orderId: string, shippingInfo: any): Promise { + updateOrderShippingInfoHelper(orderId, shippingInfo, this._options) + } + + // TODO: add paymentInfo type + async updateOrderPaymentInfo(orderId: string, paymentInfo: any): Promise { + updateOrderPaymentInfoHelper(orderId, paymentInfo, this._options) } takeSnapshot = (): StandaloneServiceSnapshot => ({ diff --git a/packages/commerce/types/checkout.ts b/packages/commerce/types/checkout.ts new file mode 100644 index 00000000..e9e69fa6 --- /dev/null +++ b/packages/commerce/types/checkout.ts @@ -0,0 +1,6 @@ + +type TransactionStatus = 'unpaid' | 'paid' | 'confirmed' | 'error' + +export { + type TransactionStatus as default +} \ No newline at end of file diff --git a/packages/commerce/types/commerce-service.ts b/packages/commerce/types/commerce-service.ts index ff723be4..5a287434 100644 --- a/packages/commerce/types/commerce-service.ts +++ b/packages/commerce/types/commerce-service.ts @@ -13,9 +13,9 @@ interface CommerceService extends ObsLineItemRef { getCartCategorySubtotal(categoryId: string): number - createOrder(email: string, paymentMethod: string): Promise - // TODO: add shippingInfo type - updateOrder(orderId: string, email: string, paymentMethod: string, shippingInfo?: any): Promise + createOrder(email: string, name?: string): Promise + updateOrderShippingInfo(orderId: string, shippingInfo: any): Promise + updateOrderPaymentInfo(orderId: string, paymentInfo: any): Promise /** * Sets the tokens at each level supplied. diff --git a/packages/commerce/types/index.ts b/packages/commerce/types/index.ts index 848c2168..30b0907d 100644 --- a/packages/commerce/types/index.ts +++ b/packages/commerce/types/index.ts @@ -2,9 +2,7 @@ export type { default as CommerceService } from './commerce-service' export type { default as Product } from './product' export type { default as Category } from './category' +export type { default as TransactionStatus } from './checkout' export * from './line-item' export * from './facet' export * from './string-mutator' - - - diff --git a/packages/commerce/util/index.ts b/packages/commerce/util/index.ts index dadb420b..fb9de922 100644 --- a/packages/commerce/util/index.ts +++ b/packages/commerce/util/index.ts @@ -28,4 +28,5 @@ export function formatPrice(price: number): string { } -export { default as useSyncSkuParamWithCurrentItem } from './use-sync-sku-param-w-current-item' \ No newline at end of file +export { default as useSyncSkuParamWithCurrentItem } from './use-sync-sku-param-w-current-item' +export { default as processSquareCardPayment } from './square-payment' \ No newline at end of file diff --git a/packages/commerce/util/square-payment.ts b/packages/commerce/util/square-payment.ts new file mode 100644 index 00000000..bebc760f --- /dev/null +++ b/packages/commerce/util/square-payment.ts @@ -0,0 +1,43 @@ +'use server' + +import { Client, Environment } from 'square' +import { randomUUID } from 'crypto' + +// https://developer.squareup.com/blog/online-payments-with-square-and-react/ +declare global { + interface BigInt { + toJSON(): string; + } +} + +BigInt.prototype.toJSON = function() { return this.toString(); } + +const { paymentsApi } = new Client({ + accessToken: process.env.SQUARE_ACCESS_TOKEN, + environment: process.env.SQUARE_ENVIRONMENT as Environment +}) + +const processPayment = async (sourceId: string, amount: number, verificationToken: string) => { + // Square API accepts amount in cents + const amountInCents = amount * 100 + + try { + const { result } = await paymentsApi.createPayment({ + idempotencyKey: randomUUID(), + sourceId: sourceId, + amountMoney: { + currency: 'USD', + amount: BigInt(amountInCents) + }, + verificationToken + }) + return result + } catch (error) { + console.error('Error processing payment:', error) + return null + } +} + +export { + processPayment as default +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eba0ecd5..0573741d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -317,7 +317,7 @@ importers: packages/commerce: dependencies: '@hanzo/auth': - specifier: ^2.0.0 + specifier: ^2.0.1 version: link:../auth '@hanzo/ui': specifier: ^3.0.0 @@ -358,6 +358,12 @@ importers: react-mobile-picker: specifier: ^1.0.0 version: 1.0.0(react-dom@18.2.0)(react@18.2.0) + react-square-web-payments-sdk: + specifier: ^3.2.1 + version: 3.2.1(react@18.2.0) + square: + specifier: ^35.0.0 + version: 35.0.0 zod: specifier: 3.21.4 version: 3.21.4 @@ -651,6 +657,112 @@ packages: '@jridgewell/gen-mapping': 0.3.4 '@jridgewell/trace-mapping': 0.3.23 + /@apimatic/authentication-adapters@0.5.2: + resolution: {integrity: sha512-VDB63xhBSSKnMTjrXXk+ZxdBfHSYU8avYDnvGnhDWQ59Ij3N1G0gaqNcR8JV/M0MGCTgI+7ODSGsKWT8QC77dA==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + '@apimatic/core-interfaces': 0.2.3 + '@apimatic/http-headers': 0.3.1 + '@apimatic/http-query': 0.3.1 + tslib: 2.6.2 + dev: false + + /@apimatic/axios-client-adapter@0.2.2: + resolution: {integrity: sha512-cbMd/CiIUmbtYpHjQgptptkeeWWko8MtuOI5rJfqxL/ElYI0ABSytdO5fuT4Q+hXQHQrkPRgL2z9yUMRoFEARg==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + '@apimatic/convert-to-stream': 0.1.0 + '@apimatic/core-interfaces': 0.2.3 + '@apimatic/file-wrapper': 0.3.1 + '@apimatic/http-headers': 0.3.1 + '@apimatic/http-query': 0.3.1 + '@apimatic/json-bigint': 1.2.0 + '@apimatic/schema': 0.7.6 + axios: 0.21.4 + detect-browser: 5.3.0 + detect-node: 2.1.0 + form-data: 3.0.1 + lodash.flatmap: 4.5.0 + tiny-warning: 1.0.3 + tslib: 2.6.2 + transitivePeerDependencies: + - debug + dev: false + + /@apimatic/convert-to-stream@0.0.2: + resolution: {integrity: sha512-1DRg17ItExfMYsXwjt6WIjJSCgV5RGg3fHPLgYD44/YmiU+7suWj7YfPKKUqmNcnJ/AvMh4lG1+tHrfOT01zXw==} + engines: {node: '>=10.4.0'} + dev: false + + /@apimatic/convert-to-stream@0.1.0: + resolution: {integrity: sha512-yVwPBnUhFD0X+veZ9KaVXBv/9svSB41GOp51Y5W+tMM316fXFQRC8jlc3XONRabQ2QWfwCz7iLtdABL41VXRcA==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dev: false + + /@apimatic/core-interfaces@0.2.3: + resolution: {integrity: sha512-/R+UCnC8qSDwGbINhLq76jpt1VEP+owAn90xAXaZ9daahQPcLtLcvU0Jj6I4SNSSsBWcZ9bKYuTohQ8uRyzRkg==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + '@apimatic/file-wrapper': 0.3.1 + tslib: 2.6.2 + dev: false + + /@apimatic/core@0.10.4: + resolution: {integrity: sha512-bcNC+UFmEFKIJnHxT1bpF7KDmJbEen4hrlw6x+n5KHvVX/SN4wINzwgVNK4dMqaZdKL4A2MVmyMswFnozvY+/w==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + '@apimatic/convert-to-stream': 0.0.2 + '@apimatic/core-interfaces': 0.2.3 + '@apimatic/file-wrapper': 0.3.1 + '@apimatic/http-headers': 0.3.1 + '@apimatic/http-query': 0.3.1 + '@apimatic/json-bigint': 1.2.0 + '@apimatic/schema': 0.7.6 + axios: 0.21.4 + detect-browser: 5.3.0 + detect-node: 2.1.0 + form-data: 3.0.1 + json-ptr: 3.1.1 + lodash.flatmap: 4.5.0 + tiny-warning: 1.0.3 + tslib: 2.6.2 + transitivePeerDependencies: + - debug + dev: false + + /@apimatic/file-wrapper@0.3.1: + resolution: {integrity: sha512-RUJe0fNO/b7vgH0jFjMgyRqBILNQ4kYZcZz8cxd3DODjKBT0R+jS6IU1KIDOTj2lJFdvPmIuPUOJbilKI2eAmA==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@apimatic/http-headers@0.3.1: + resolution: {integrity: sha512-q5cmRHbSnweet2FFW4NSTZaVPdmVZLJJTUFdMs3dJON+tw2WcH2bNprORi26DrYBE0Dz/4u1Fip5uqRvBYNULA==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@apimatic/http-query@0.3.1: + resolution: {integrity: sha512-YC/dFTX35Q3XWuVbTgEFsQVmpVJlmSrfhI7TBuiUTSlex0uPi3cBQejnLPq0+thpCbGifaL/J+bRbngBO3Kt3Q==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + '@apimatic/file-wrapper': 0.3.1 + tslib: 2.6.2 + dev: false + + /@apimatic/json-bigint@1.2.0: + resolution: {integrity: sha512-+bmVzYMdZu0Ya5L+my4FXFUih54OvQA/qlZsFOYdOoostyUuB27UDrVWQs/WVCmS0ADdo5vTU0eeTrrBkHoySw==} + dev: false + + /@apimatic/schema@0.7.6: + resolution: {integrity: sha512-0h2WPULh1lYa9nzNQufXL6JDRm2ykr57mSKneF7surtFiUYZ+bubskBxaP9YoH8zzrshPLBqs/R9TY0QhK5YJQ==} + engines: {node: '>=14.15.0 || >=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -4045,6 +4157,27 @@ packages: string.prototype.codepointat: 0.2.1 dev: false + /@square/web-payments-sdk-types@1.54.9: + resolution: {integrity: sha512-fZjGM3WqWrzoSNtnSZP19GLmxXqQ2JMA5eaAGF9V90L8Dq5UTILj5B21c6tzkNq/tMJ9cXHi1kUNGjOB+yDjjA==} + dependencies: + typescript: 4.9.5 + dev: false + + /@square/web-sdk@2.0.1: + resolution: {integrity: sha512-m+pauPLJUHO4qzBNKlHRMe+qDAhQdbEd7g/v/SW8BWZARwJC0liHB4AnVAJuM/7JMFEPiT2ZO3SRt1VQsCeoYg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + '@square/web-payments-sdk-types': 1.54.9 + dev: false + + /@stitches/react@1.2.8(react@18.2.0): + resolution: {integrity: sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA==} + peerDependencies: + react: '>= 16.3.0' + dependencies: + react: 18.2.0 + dev: false + /@swc/helpers@0.5.2: resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} dependencies: @@ -4282,6 +4415,10 @@ packages: /@types/ms@0.7.34: resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + /@types/node@14.18.63: + resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} + dev: false + /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} @@ -4847,7 +4984,6 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} requiresBuild: true dev: false - optional: true /autoprefixer@10.4.17(postcss@8.4.35): resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==} @@ -4877,6 +5013,14 @@ packages: engines: {node: '>=4'} dev: true + /axios@0.21.4: + resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + dependencies: + follow-redirects: 1.15.6 + transitivePeerDependencies: + - debug + dev: false + /axobject-query@3.2.1: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} dependencies: @@ -5157,7 +5301,6 @@ packages: dependencies: delayed-stream: 1.0.0 dev: false - optional: true /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -5422,12 +5565,15 @@ packages: engines: {node: '>=0.4.0'} requiresBuild: true dev: false - optional: true /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + /detect-browser@5.3.0: + resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + dev: false + /detect-libc@2.0.2: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} @@ -5437,6 +5583,10 @@ packages: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} dev: false + /detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + dev: false + /devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} dependencies: @@ -6313,6 +6463,16 @@ packages: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} dev: true + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -6337,6 +6497,15 @@ packages: dev: false optional: true + /form-data@3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + /format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} @@ -7317,6 +7486,10 @@ packages: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true + /json-ptr@3.1.1: + resolution: {integrity: sha512-SiSJQ805W1sDUCD1+/t1/1BIrveq2Fe9HJqENxZmMCILmrPI7WhS/pePpIOx85v6/H2z1Vy7AI08GV2TzfXocg==} + dev: false + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -7496,6 +7669,10 @@ packages: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} dev: false + /lodash.flatmap@4.5.0: + resolution: {integrity: sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg==} + dev: false + /lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} dev: false @@ -9478,6 +9655,16 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false + /react-square-web-payments-sdk@3.2.1(react@18.2.0): + resolution: {integrity: sha512-XhW4snpCfUNaVqS652dDWSWJd+r9OftkqmvP9hix5ISEV8Foo9QrGDe33t1w+uMIl9ox1EWlexGb0yDe8ZYamQ==} + peerDependencies: + react: ^16 || ^17 || ^18 + dependencies: + '@square/web-sdk': 2.0.1 + '@stitches/react': 1.2.8(react@18.2.0) + react: 18.2.0 + dev: false + /react-style-singleton@2.2.1(@types/react@18.2.65)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} @@ -10066,6 +10253,20 @@ packages: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: false + /square@35.0.0: + resolution: {integrity: sha512-DuBD/CQOBaXgkNeLwkdKYYrhb0bIOeArmyNY76Y38RcVRHZX0exqxpa2ukU8/8s0eMh7j7paJ9twnMAZmu9cFA==} + engines: {node: '>=14.17.0'} + dependencies: + '@apimatic/authentication-adapters': 0.5.2 + '@apimatic/axios-client-adapter': 0.2.2 + '@apimatic/core': 0.10.4 + '@apimatic/json-bigint': 1.2.0 + '@apimatic/schema': 0.7.6 + '@types/node': 14.18.63 + transitivePeerDependencies: + - debug + dev: false + /stream-events@1.0.5: resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} requiresBuild: true @@ -10428,6 +10629,10 @@ packages: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} dev: false + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: false + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'}