commerce icon indicating copy to clipboard operation
commerce copied to clipboard

Find a way to replace the custom Provider generic

Open lfades opened this issue 4 years ago • 1 comments
trafficstars

It's currently not fun to work with commerce types, specially for the API setup, most commerce types come from a generic named Provider, which is defined by every provider.

Initially we'll need to work on getting the issue below first:

  • [ ] https://github.com/vercel/commerce/issues/512

Once that's done we might be able to have a single API Provider and a single client Provider defined in the core.

For more context on why do we want to have a single provider, let's see an example. In the case of BigCommerce its API provider looks like this:

const operations = {
  login,
  getAllPages,
  getPage,
  getSiteInfo,
  getCustomerWishlist,
  getAllProductPaths,
  getAllProducts,
  getProduct,
}

export const provider = { config, operations }

export type Provider = typeof provider

export type APIs =
  | CartAPI
  | CustomerAPI
  | LoginAPI
  | LogoutAPI
  | SignupAPI
  | ProductsAPI
  | WishlistAPI

export type BigcommerceAPI<P extends Provider = Provider> = CommerceAPI<P>

That's ll fine until you decide to use one of the types that uses the Provider generic, so for example in that same code:

image

VS Code will show something unreadable, and this also affects the DX when there's an error, you have to scroll down multiple pages and hope to find the error, which might be inside the generic and that can happen often because the Provider is huge.

In the case of hooks we have a similar issue, below is the client provider of BigCommerce:

// framework/bigcommerce/provider.ts

export const bigcommerceProvider = {
  locale: 'en-us',
  cartCookie: 'bc_cartId',
  fetcher,
  cart: { useCart, useAddItem, useUpdateItem, useRemoveItem },
  wishlist: {
    useWishlist,
    useAddItem: useWishlistAddItem,
    useRemoveItem: useWishlistRemoveItem,
  },
  customer: { useCustomer },
  products: { useSearch },
  auth: { useLogin, useLogout, useSignup },
}

export type BigcommerceProvider = typeof bigcommerceProvider

// framework/bigcommerce/index.tsx

export const CommerceProvider = getCommerceProvider(bigcommerceProvider)

export const useCommerce = () => useCoreCommerce<BigcommerceProvider>()

Now If I try to read the type of useCommerce:

image

I don't even get to see the returned type. However for the case of the API provider this is more annoying due to an often usage of the generic.

lfades avatar Oct 01 '21 00:10 lfades

Maybe we can find a way to create a Proxy f or API operations that's perfectly typed but does multiple checks behind the scenes for actually defined operations, it might also help reducing js footprint.

lfades avatar Oct 01 '21 00:10 lfades