Dynamic API routes (#836)

* Add dynamic API endpoints

* Add missing dependency

* Update api handlers

* Updates

* Fix build errors

* Update package.json

* Add checkout endpoint parser & update errors

* Update tsconfig.json

* Update cart.ts

* Update parser

* Update errors.ts

* Update errors.ts

* Move to Edge runtime

* Revert to local

* Fix switchable runtimes

* Make nodejs default runtime

* Update pnpm-lock.yaml

* Update handlers

* Fix build errors

* Change headers
This commit is contained in:
Catalin Pinte
2022-10-30 20:41:21 +02:00
committed by GitHub
parent a5b367a747
commit c75b0fc001
316 changed files with 2482 additions and 2176 deletions

View File

@@ -33,8 +33,12 @@ const LoginView: React.FC = () => {
})
setLoading(false)
closeModal()
} catch (e: any) {
setMessage(e.errors[0].message)
} catch ({ errors }) {
if (errors instanceof Array) {
setMessage(errors.map((e: any) => e.message).join('<br/>'))
} else {
setMessage('Unexpected error')
}
setLoading(false)
setDisabled(false)
}

View File

@@ -41,13 +41,14 @@ const SignUpView: FC<Props> = () => {
setLoading(false)
closeModal()
} catch ({ errors }) {
console.error(errors)
if (errors instanceof Array) {
setMessage(errors[0].message)
setMessage(errors.map((e: any) => e.message).join('<br/>'))
} else {
setMessage('Unexpected error')
console.log(errors)
}
setLoading(false)
setDisabled(false)
}
}
@@ -75,7 +76,12 @@ const SignUpView: FC<Props> = () => {
</div>
<div className="flex flex-col space-y-4">
{message && (
<div className="text-red border border-red p-3">{message}</div>
<div
className="text-red border border-red p-3"
dangerouslySetInnerHTML={{
__html: message,
}}
></div>
)}
<Input placeholder="First Name" onChange={setFirstName} />
<Input placeholder="Last Name" onChange={setLastName} />

View File

@@ -31,7 +31,7 @@ const UserNav: React.FC<{
openSidebar,
} = useUI()
const itemsCount = data?.lineItems.reduce(countItem, 0) ?? 0
const itemsCount = data?.lineItems?.reduce(countItem, 0) ?? 0
const DropdownTrigger = isCustomerLoggedIn
? DropdownTriggerInst
: React.Fragment

View File

@@ -9,6 +9,7 @@ import {
selectDefaultOptionFromProduct,
SelectedOptions,
} from '../helpers'
import ErrorMessage from '@components/ui/ErrorMessage'
interface ProductSidebarProps {
product: Product
@@ -19,6 +20,7 @@ const ProductSidebar: FC<ProductSidebarProps> = ({ product, className }) => {
const addItem = useAddItem()
const { openSidebar, setSidebarView } = useUI()
const [loading, setLoading] = useState(false)
const [error, setError] = useState<null | Error>(null)
const [selectedOptions, setSelectedOptions] = useState<SelectedOptions>({})
useEffect(() => {
@@ -28,6 +30,7 @@ const ProductSidebar: FC<ProductSidebarProps> = ({ product, className }) => {
const variant = getProductVariant(product, selectedOptions)
const addToCart = async () => {
setLoading(true)
setError(null)
try {
await addItem({
productId: String(product.id),
@@ -38,6 +41,13 @@ const ProductSidebar: FC<ProductSidebarProps> = ({ product, className }) => {
setLoading(false)
} catch (err) {
setLoading(false)
if (err instanceof Error) {
console.error(err)
setError({
...err,
message: 'Could not add item to cart. Please try again.',
})
}
}
}
@@ -57,6 +67,7 @@ const ProductSidebar: FC<ProductSidebarProps> = ({ product, className }) => {
<div className="text-accent-6 pr-1 font-medium text-sm">36 reviews</div>
</div>
<div>
{error && <ErrorMessage error={error} className="my-5" />}
{process.env.COMMERCE_CART_ENABLED && (
<Button
aria-label="Add to Cart"

View File

@@ -1,5 +1,4 @@
import cn from 'clsx'
import { inherits } from 'util'
import s from './ProductTag.module.css'
interface ProductTagProps {

View File

@@ -12,8 +12,6 @@ import { ProductCard } from '@components/product'
import { Container, Skeleton } from '@components/ui'
import useSearch from '@framework/product/use-search'
import getSlug from '@lib/get-slug'
import rangeMap from '@lib/range-map'
const SORT = {
@@ -29,6 +27,7 @@ import {
getDesignerPath,
useSearchMeta,
} from '@lib/search'
import ErrorMessage from './ui/ErrorMessage'
export default function Search({ categories, brands }: SearchPropsType) {
const [activeFilter, setActiveFilter] = useState('')
@@ -56,7 +55,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
})
if (error) {
return <div>Failed to load</div>
return <ErrorMessage error={error} />
}
const handleClick = (event: any, filter: string) => {

View File

@@ -0,0 +1,35 @@
import type { FC } from 'react'
import cn from 'clsx'
interface ErrorMessageProps {
error: {
message: string
code?: string
errors?: {
message: string
}[]
}
className?: string
}
const ErrorMessages: FC<ErrorMessageProps> = ({ error, className }) => {
return (
<div
className={cn(
'flex flex-col text-red py-2.5 px-4 border border-solid border-red',
className
)}
>
<span>{error.message}</span>
{error.errors && error.errors?.length > 0 && (
<ul className="list-disc list-inside">
{error.errors.map(({ message }, index) => (
<li key={index}>{message}</li>
))}
</ul>
)}
</div>
)
}
export default ErrorMessages

View File

@@ -0,0 +1 @@
export { default } from './ErrorMessage'

View File

@@ -1,3 +1,2 @@
import { getCommerceApi } from '@framework/api'
export default getCommerceApi()

View File

@@ -18,7 +18,7 @@ module.exports = withCommerceConfig({
return [
(isBC || isShopify || isSwell || isVendure || isSaleor) && {
source: '/checkout',
destination: '/api/checkout',
destination: '/api/commerce/checkout',
},
// The logout is also an action so this route is not required, but it's also another way
// you can allow a logout!

View File

@@ -1,4 +0,0 @@
import cartApi from '@framework/api/endpoints/cart'
import commerce from '@lib/api/commerce'
export default cartApi(commerce)

View File

@@ -1,4 +0,0 @@
import productsApi from '@framework/api/endpoints/catalog/products'
import commerce from '@lib/api/commerce'
export default productsApi(commerce)

View File

@@ -1,4 +0,0 @@
import checkoutApi from '@framework/api/endpoints/checkout'
import commerce from '@lib/api/commerce'
export default checkoutApi(commerce)

View File

@@ -0,0 +1,8 @@
import commerce from '@lib/api/commerce'
import endpoints from '@framework/api/endpoints'
// export const config = {
// runtime: 'experimental-edge',
// }
export default endpoints(commerce)

View File

@@ -1,4 +0,0 @@
import customerAddressApi from '@framework/api/endpoints/customer/address'
import commerce from '@lib/api/commerce'
export default customerAddressApi(commerce)

View File

@@ -1,4 +0,0 @@
import customerCardApi from '@framework/api/endpoints/customer/card'
import commerce from '@lib/api/commerce'
export default customerCardApi(commerce)

View File

@@ -1,4 +0,0 @@
import customerApi from '@framework/api/endpoints/customer'
import commerce from '@lib/api/commerce'
export default customerApi(commerce)

View File

@@ -1,4 +0,0 @@
import loginApi from '@framework/api/endpoints/login'
import commerce from '@lib/api/commerce'
export default loginApi(commerce)

View File

@@ -1,4 +0,0 @@
import logoutApi from '@framework/api/endpoints/logout'
import commerce from '@lib/api/commerce'
export default logoutApi(commerce)

View File

@@ -1,4 +0,0 @@
import singupApi from '@framework/api/endpoints/signup'
import commerce from '@lib/api/commerce'
export default singupApi(commerce)

View File

@@ -1,4 +0,0 @@
import wishlistApi from '@framework/api/endpoints/wishlist'
import commerce from '@lib/api/commerce'
export default wishlistApi(commerce)

View File

@@ -22,7 +22,6 @@ export async function getStaticProps({
config,
preview,
})
const allProductsPromise = commerce.getAllProducts({
variables: { first: 4 },
config,