diff --git a/README.md b/README.md index f83d4822f..745f51d09 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,10 @@ Next.js Commerce integrates out-of-the-box with BigCommerce, Shopify, Swell, Sal ## Considerations -- `framework/commerce` contains all types, helpers and functions to be used as base to build a new **provider**. -- **Providers** live under `framework`'s root folder and they will extend Next.js Commerce types and functionality (`framework/commerce`). +- `packages/commerce` contains all types, helpers and functions to be used as base to build a new **provider**. +- **Providers** live under `packages`'s root folder and they will extend Next.js Commerce types and functionality (`packages/commerce`). - We have a **Features API** to ensure feature parity between the UI and the Provider. The UI should update accordingly and no extra code should be bundled. All extra configuration for features will live under `features` in `commerce.config.json` and if needed it can also be accessed programatically. - Each **provider** should add its corresponding `next.config.js` and `commerce.config.json` adding specific data related to the provider. For example in case of BigCommerce, the images CDN and additional API routes. -- **Providers don't depend on anything that's specific to the application they're used in**. They only depend on `framework/commerce`, on their own framework folder and on some dependencies included in `package.json` ## Configuration @@ -55,18 +54,9 @@ NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN=xxxxxxx.myshopify.com ``` -And check that the `tsconfig.json` resolves to the chosen provider: - -``` - "@framework": ["framework/shopify"], - "@framework/*": ["framework/shopify/*"] -``` - -That's it! - ### Features -Every provider defines the features that it supports under `framework/{provider}/commerce.config.json` +Every provider defines the features that it supports under `packages/{provider}/src/commerce.config.json` #### Features Available @@ -98,9 +88,7 @@ For example: Turning `cart` off will disable Cart capabilities. ### How to create a new provider -🔔 New providers are on hold [until we have a new API for commerce](https://github.com/vercel/commerce/pull/252) 🔔 - -Follow our docs for [Adding a new Commerce Provider](framework/commerce/new-provider.md). +Follow our docs for [Adding a new Commerce Provider](packages/commerce/new-provider.md). If you succeeded building a provider, submit a PR with a valid demo and we'll review it asap. @@ -119,7 +107,7 @@ Our commitment to Open Source can be found [here](https://vercel.com/oss). We're using Github Projects to keep track of issues in progress and todo's. Here is our [Board](https://github.com/vercel/commerce/projects/1) -People actively working on this project: @okbel & @lfades. +People actively working on this project: @okbel, @lfades, @dominiksipowicz, @gbibeaul. ## Troubleshoot diff --git a/packages/bigcommerce/README.md b/packages/bigcommerce/README.md index 7f62a5f3f..1e8c6cb08 100644 --- a/packages/bigcommerce/README.md +++ b/packages/bigcommerce/README.md @@ -9,7 +9,7 @@ With the deploy button below you'll be able to have a [BigCommerce](https://www. If you already have a BigCommerce account and want to use your current store, then copy the `.env.template` file in this directory to `.env.local` in the main directory (which will be ignored by Git): ```bash -cp framework/bigcommerce/.env.template .env.local +cp packages/bigcommerce/.env.template .env.local ``` Then, set the environment variables in `.env.local` to match the ones from your store. diff --git a/packages/commerce/new-provider.md b/packages/commerce/new-provider.md index 53b6c2a38..546b933f6 100644 --- a/packages/commerce/new-provider.md +++ b/packages/commerce/new-provider.md @@ -4,108 +4,82 @@ A commerce provider is a headless e-commerce platform that integrates with the [Commerce Framework](./README.md). Right now we have the following providers: -- Local ([framework/local](../local)) -- Shopify ([framework/shopify](../shopify)) -- Swell ([framework/swell](../swell)) -- BigCommerce ([framework/bigcommerce](../bigcommerce)) -- Vendure ([framework/vendure](../vendure)) -- Saleor ([framework/saleor](../saleor)) -- OrderCloud ([framework/ordercloud](../ordercloud)) -- Spree ([framework/spree](../spree)) -- Kibo Commerce ([framework/kibocommerce](../kibocommerce)) -- Commerce.js ([framework/commercejs](../commercejs)) +- Local ([packages/local](../local)) +- Shopify ([packages/shopify](../shopify)) +- Swell ([packages/swell](../swell)) +- BigCommerce ([packages/bigcommerce](../bigcommerce)) +- Vendure ([packages/vendure](../vendure)) +- Saleor ([packages/saleor](../saleor)) +- OrderCloud ([packages/ordercloud](../ordercloud)) +- Spree ([packages/spree](../spree)) +- Kibo Commerce ([packages/kibocommerce](../kibocommerce)) +- Commerce.js ([packages/commercejs](../commercejs)) -Adding a commerce provider means adding a new folder in `framework` with a folder structure like the next one: +Adding a commerce provider means adding a new folder in `packages` with a folder structure like the next one: -- `api` - - index.ts -- `product` - - usePrice - - useSearch - - getProduct - - getAllProducts -- `wishlist` - - useWishlist - - useAddItem - - useRemoveItem -- `auth` - - useLogin - - useLogout - - useSignup -- `customer` - - useCustomer - - getCustomerId - - getCustomerWistlist -- `cart` - - useCart - - useAddItem - - useRemoveItem - - useUpdateItem +- `src` + - `api` + - index.ts + - `product` + - usePrice + - useSearch + - getProduct + - getAllProducts + - `wishlist` + - useWishlist + - useAddItem + - useRemoveItem + - `auth` + - useLogin + - useLogout + - useSignup + - `customer` + - useCustomer + - getCustomerId + - getCustomerWistlist + - `cart` + - useCart + - useAddItem + - useRemoveItem + - useUpdateItem + - `index.ts` + - `provider.ts` + - `commerce.config.json` + - `next.config.cjs` +- `package.json` +- `tsconfig.json` - `env.template` -- `index.ts` -- `provider.ts` -- `commerce.config.json` -- `next.config.js` - `README.md` `provider.ts` exports a provider object with handlers for the [Commerce Hooks](./README.md#commerce-hooks) and `api/index.ts` exports a Node.js provider for the [Commerce API](./README.md#commerce-api) > **Important:** We use TypeScript for every provider and expect its usage for every new one. -The app imports from the provider directly instead of the core commerce folder (`framework/commerce`), but all providers are interchangeable and to achieve it every provider always has to implement the core types and helpers. - -The provider folder should only depend on `framework/commerce` and dependencies in the main `package.json`. In the future we'll move the `framework` folder to a package that can be shared easily for multiple apps. +The app imports from the provider directly instead of the core commerce folder (`packages/commerce`), but all providers are interchangeable and to achieve it every provider always has to implement the core types and helpers. ## Updating the list of known providers -Open [./config.js](./config.js) and add the provider name to the list in `PROVIDERS`. +Open [/site/commerce-config.js](/site/commerce-config.js) and add the provider name to the list in `PROVIDERS`. -Then, open [/.env.template](/.env.template) and add the provider name in the first line. +Then, open [/site/.env.template](/site/.env.template) and add the provider name to the list there too. ## Adding the provider hooks Using BigCommerce as an example. The first thing to do is export a `CommerceProvider` component that includes a `provider` object with all the handlers that can be used for hooks: ```tsx -import type { ReactNode } from 'react' -import { - CommerceConfig, - CommerceProvider as CoreCommerceProvider, - useCommerce as useCoreCommerce, -} from '@commerce' -import { bigcommerceProvider } from './provider' -import type { BigcommerceProvider } from './provider' +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@vercel/commerce' +import { bigcommerceProvider, BigcommerceProvider } from './provider' export { bigcommerceProvider } export type { BigcommerceProvider } -export const bigcommerceConfig: CommerceConfig = { - locale: 'en-us', - cartCookie: 'bc_cartId', -} - -export type BigcommerceConfig = Partial - -export type BigcommerceProps = { - children?: ReactNode - locale: string -} & BigcommerceConfig - -export function CommerceProvider({ children, ...config }: BigcommerceProps) { - return ( - - {children} - - ) -} +export const CommerceProvider = getCommerceProvider(bigcommerceProvider) export const useCommerce = () => useCoreCommerce() ``` -The exported types and components extend from the core ones exported by `@commerce`, which refers to `framework/commerce`. +The exported types and components extend from the core ones exported by `@vercel/commerce`, which refers to `packages/commerce`. The `bigcommerceProvider` object looks like this: @@ -146,33 +120,23 @@ export const bigcommerceProvider = { export type BigcommerceProvider = typeof bigcommerceProvider ``` -The provider object, in this case `bigcommerceProvider`, has to match the `Provider` type defined in [framework/commerce](./index.ts). +The provider object, in this case `bigcommerceProvider`, has to match the `Provider` type defined in [packages/commerce](./src/index.tsx). A hook handler, like `useCart`, looks like this: ```tsx import { useMemo } from 'react' -import { SWRHook } from '@commerce/utils/types' -import useCart, { UseCart, FetchCartInput } from '@commerce/cart/use-cart' -import { normalizeCart } from '../lib/normalize' -import type { Cart } from '../types' +import { SWRHook } from '@vercel/commerce/utils/types' +import useCart, { UseCart } from '@vercel/commerce/cart/use-cart' +import type { GetCartHook } from '@vercel/commerce/types/cart' export default useCart as UseCart -export const handler: SWRHook< - Cart | null, - {}, - FetchCartInput, - { isEmpty?: boolean } -> = { +export const handler: SWRHook = { fetchOptions: { url: '/api/cart', method: 'GET', }, - async fetcher({ input: { cartId }, options, fetch }) { - const data = cartId ? await fetch(options) : null - return data && normalizeCart(data) - }, useHook: ({ useData }) => (input) => { @@ -200,21 +164,15 @@ In the case of data fetching hooks like `useCart` each handler has to implement ```tsx import { useCallback } from 'react' -import type { MutationHook } from '@commerce/utils/types' -import { CommerceError } from '@commerce/utils/errors' -import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item' -import { normalizeCart } from '../lib/normalize' -import type { - Cart, - BigcommerceCart, - CartItemBody, - AddCartItemBody, -} from '../types' +import type { MutationHook } from '@vercel/commerce/utils/types' +import { CommerceError } from '@vercel/commerce/utils/errors' +import useAddItem, { UseAddItem } from '@vercel/commerce/cart/use-add-item' +import type { AddItemHook } from '@vercel/commerce/types/cart' import useCart from './use-cart' export default useAddItem as UseAddItem -export const handler: MutationHook = { +export const handler: MutationHook = { fetchOptions: { url: '/api/cart', method: 'POST', @@ -229,12 +187,12 @@ export const handler: MutationHook = { }) } - const data = await fetch({ + const data = await fetch({ ...options, body: { item }, }) - return normalizeCart(data) + return data }, useHook: ({ fetch }) => @@ -276,9 +234,3 @@ When creating a PR for a new provider, include this list in the PR description a * [ ] Custom checkout * [ ] Typing (in progress) * [ ] Tests - -## Adding the Node.js provider API - -TODO - -> The commerce API is currently going through a refactor in https://github.com/vercel/commerce/pull/252 - We'll update the docs once the API is released. diff --git a/packages/commercejs/README.md b/packages/commercejs/README.md index b0333c96a..20aaf70e5 100644 --- a/packages/commercejs/README.md +++ b/packages/commercejs/README.md @@ -7,7 +7,7 @@ To use this provider you must have a [Commerce.js account](https://commercejs.co Next, copy the `.env.template` file in this directory to `.env.local` in the main directory (which will be ignored by Git): ```bash -cp framework/commercejs/.env.template .env.local +cp packages/commercejs/.env.template .env.local ``` Then, set the environment variables in `.env.local` to match the ones from your store. You'll need your Commerce.js public API key, which can be found in your Commerce.js dashboard in the `Developer -> API keys` section. diff --git a/packages/kibocommerce/README.md b/packages/kibocommerce/README.md index dc7589635..13fa331d2 100644 --- a/packages/kibocommerce/README.md +++ b/packages/kibocommerce/README.md @@ -3,7 +3,7 @@ If you already have a Kibo Commerce account and want to use your current store, then copy the `.env.template` file in this directory to `.env.local` in the main directory (which will be ignored by Git): ```bash -cp framework/kibocommerce/.env.template .env.local +cp packages/kibocommerce/.env.template .env.local ``` Then, set the environment variables in `.env.local` to match the ones from your store. @@ -22,7 +22,7 @@ KIBO_AUTH_URL='https://home.mozu.com' - `KIBO_CART_COOKIE` - configurable cookie name for cart. - `KIBO_CUSTOMER_COOKIE` - configurable cookie name for shopper identifier/authentication cookie - `KIBO_CLIENT_ID` - Unique Application (Client) ID of your Application -- `KIBO_SHARED_SECRET` - Secret API key used to authenticate application/client id. +- `KIBO_SHARED_SECRET` - Secret API key used to authenticate application/client id. Your Kibo Client ID and Shared Secret can be found from your [Kibo eCommerce Dev Center](https://mozu.com/login) diff --git a/packages/saleor/README.md b/packages/saleor/README.md index dba25a243..277639622 100644 --- a/packages/saleor/README.md +++ b/packages/saleor/README.md @@ -9,7 +9,7 @@ This provider requires Saleor **3.x** or higher. Copy the `.env.template` file in this directory to `.env.local` in the main directory (which will be ignored by Git): ```bash -cp framework/saleor/.env.template .env.local +cp packages/saleor/.env.template .env.local ``` Then, set the environment following variables in your `.env.local`. Both, `NEXT_PUBLIC_SALEOR_API_URL` and `COMMERCE_IMAGE_HOST` must point to your own Saleor instance. diff --git a/packages/shopify/README.md b/packages/shopify/README.md index 82d90fc55..15a6e1f11 100644 --- a/packages/shopify/README.md +++ b/packages/shopify/README.md @@ -7,7 +7,7 @@ Before getting started, a [Shopify](https://www.shopify.com/) account and store Next, copy the `.env.template` file in this directory to `.env.local` in the main directory (which will be ignored by Git): ```bash -cp framework/shopify/.env.template .env.local +cp packages/shopify/.env.template .env.local ``` Then, set the environment variables in `.env.local` to match the ones from your store. diff --git a/packages/spree/README.md b/packages/spree/README.md index 7bbc733ab..0b172cb19 100644 --- a/packages/spree/README.md +++ b/packages/spree/README.md @@ -12,10 +12,10 @@ An integration of [Spree Commerce](https://spreecommerce.org/) within NextJS Com 1. Setup Nextjs Commerce - [instructions for setting up NextJS Commerce][2]. -1. Copy the `.env.template` file in this directory (`/framework/spree`) to `.env.local` in the main directory +1. Copy the `.env.template` file in this directory (`/packages/spree`) to `.env.local` in the main directory ```bash - cp framework/spree/.env.template .env.local + cp packages/spree/.env.template .env.local ``` 1. Set `NEXT_PUBLIC_SPREE_CATEGORIES_TAXONOMY_PERMALINK` and `NEXT_PUBLIC_SPREE_BRANDS_TAXONOMY_PERMALINK` environment variables: diff --git a/packages/vendure/README.md b/packages/vendure/README.md index 7f1dccb3f..485125ce2 100644 --- a/packages/vendure/README.md +++ b/packages/vendure/README.md @@ -28,8 +28,10 @@ This provider makes use of GraphQL code generation. The [schema.graphql](./schem When developing the provider, changes to any GraphQL operations should be followed by re-generation of the types and schema files: -From the project root dir, run +From the package dir, run ```sh -graphql-codegen --config ./framework/vendure/codegen.json +yarn generate +# or +npm run generate ```