forked from vercel/commerce
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Minimal list/detail views working with Vendure * Implement useCart/useAddItem * Implement useUpdateItem & useRemoveItem * Implement useSearch * Add operations codegen, tidy up * Dummy checkout page * Implement auth/customer hooks * Use env var for Shop API url * Add some documentation * Improve error handling * Optimize preview image size * Fix accidental change * Update Vendure provider to latest changes * Vendure provider: split out gql operations, remove unused files * Update Vendure provider readme * Add local next.config to Vendure provider, update docs * Update to use demo server * Fix build errors * Use proxy for vendure api * Simplify instructions in Vendure readme * Refactor Vendure checkout api handler * Improve image quality
- Loading branch information
1 parent
8fb6c7b
commit da43710
Showing
71 changed files
with
8,593 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ out/ | |
# misc | ||
.DS_Store | ||
*.pem | ||
.idea | ||
|
||
# debug | ||
npm-debug.log* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
NEXT_PUBLIC_VENDURE_SHOP_API_URL=http://localhost:3001/shop-api |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Vendure Storefront Data Hooks | ||
|
||
UI hooks and data fetching methods built from the ground up for e-commerce applications written in React, that use [Vendure](http://vendure.io/) as a headless e-commerce platform. | ||
|
||
## Usage | ||
|
||
1. Clone this repo and install its dependencies with `yarn install` or `npm install` | ||
2. Set the Vendure provider and API URL in your `.env.local` file: | ||
``` | ||
COMMERCE_PROVIDER=vendure | ||
NEXT_PUBLIC_VENDURE_SHOP_API_URL=https://demo.vendure.io/shop-api | ||
NEXT_PUBLIC_VENDURE_LOCAL_URL=/vendure-shop-api | ||
``` | ||
3. With the Vendure server running, start this project using `yarn dev` or `npm run dev`. | ||
|
||
## Known Limitations | ||
|
||
1. Vendure does not ship with built-in wishlist functionality. | ||
2. Nor does it come with any kind of blog/page-building feature. Both of these can be created as Vendure plugins, however. | ||
3. The entire Vendure customer flow is carried out via its GraphQL API. This means that there is no external, pre-existing checkout flow. The checkout flow must be created as part of the Next.js app. See https://github.com/vercel/commerce/issues/64 for further discusion. | ||
4. By default, the sign-up flow in Vendure uses email verification. This means that using the existing "sign up" flow from this project will not grant a new user the ability to authenticate, since the new account must first be verified. Again, the necessary parts to support this flow can be created as part of the Next.js app. | ||
|
||
## Code generation | ||
|
||
This provider makes use of GraphQL code generation. The [schema.graphql](./schema.graphql) and [schema.d.ts](./schema.d.ts) files contain the generated types & schema introspection results. | ||
|
||
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 | ||
|
||
```sh | ||
graphql-codegen --config ./framework/vendure/codegen.json | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { NextApiHandler } from 'next' | ||
|
||
const checkoutApi = async (req: any, res: any, config: any) => { | ||
try { | ||
const html = ` | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Checkout</title> | ||
</head> | ||
<body> | ||
<div style='margin: 10rem auto; text-align: center; font-family: SansSerif, "Segoe UI", Helvetica'> | ||
<h1>Checkout not implemented :(</h1> | ||
<p> | ||
See <a href='https://github.com/vercel/commerce/issues/64' target='_blank'>#64</a> | ||
</p> | ||
</div> | ||
</body> | ||
</html> | ||
` | ||
|
||
res.status(200) | ||
res.setHeader('Content-Type', 'text/html') | ||
res.write(html) | ||
res.end() | ||
} catch (error) { | ||
console.error(error) | ||
|
||
const message = 'An unexpected error ocurred' | ||
|
||
res.status(500).json({ data: null, errors: [{ message }] }) | ||
} | ||
} | ||
|
||
export function createApiHandler<T = any, H = {}, Options extends {} = {}>( | ||
handler: any, | ||
handlers: H, | ||
defaultOptions: Options | ||
) { | ||
return function getApiHandler({ | ||
config, | ||
operations, | ||
options, | ||
}: { | ||
config?: any | ||
operations?: Partial<H> | ||
options?: Options extends {} ? Partial<Options> : never | ||
} = {}): NextApiHandler { | ||
const ops = { ...operations, ...handlers } | ||
const opts = { ...defaultOptions, ...options } | ||
|
||
return function apiHandler(req, res) { | ||
return handler(req, res, config, ops, opts) | ||
} | ||
} | ||
} | ||
|
||
export default createApiHandler(checkoutApi, {}, {}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import type { CommerceAPIConfig } from '@commerce/api' | ||
import fetchGraphqlApi from './utils/fetch-graphql-api' | ||
|
||
export interface VendureConfig extends CommerceAPIConfig {} | ||
|
||
const API_URL = process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL | ||
|
||
if (!API_URL) { | ||
throw new Error( | ||
`The environment variable NEXT_PUBLIC_VENDURE_SHOP_API_URL is missing and it's required to access your store` | ||
) | ||
} | ||
|
||
export class Config { | ||
private config: VendureConfig | ||
|
||
constructor(config: VendureConfig) { | ||
this.config = { | ||
...config, | ||
} | ||
} | ||
|
||
getConfig(userConfig: Partial<VendureConfig> = {}) { | ||
return Object.entries(userConfig).reduce<VendureConfig>( | ||
(cfg, [key, value]) => Object.assign(cfg, { [key]: value }), | ||
{ ...this.config } | ||
) | ||
} | ||
|
||
setConfig(newConfig: Partial<VendureConfig>) { | ||
Object.assign(this.config, newConfig) | ||
} | ||
} | ||
|
||
const ONE_DAY = 60 * 60 * 24 | ||
const config = new Config({ | ||
commerceUrl: API_URL, | ||
apiToken: '', | ||
cartCookie: '', | ||
customerCookie: '', | ||
cartCookieMaxAge: ONE_DAY * 30, | ||
fetch: fetchGraphqlApi, | ||
}) | ||
|
||
export function getConfig(userConfig?: Partial<VendureConfig>) { | ||
return config.getConfig(userConfig) | ||
} | ||
|
||
export function setConfig(newConfig: Partial<VendureConfig>) { | ||
return config.setConfig(newConfig) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { FetcherError } from '@commerce/utils/errors' | ||
import type { GraphQLFetcher } from '@commerce/api' | ||
import { getConfig } from '..' | ||
import fetch from './fetch' | ||
|
||
const fetchGraphqlApi: GraphQLFetcher = async ( | ||
query: string, | ||
{ variables, preview } = {}, | ||
fetchOptions | ||
) => { | ||
const config = getConfig() | ||
const res = await fetch(config.commerceUrl, { | ||
...fetchOptions, | ||
method: 'POST', | ||
headers: { | ||
Authorization: `Bearer ${config.apiToken}`, | ||
...fetchOptions?.headers, | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
query, | ||
variables, | ||
}), | ||
}) | ||
|
||
const json = await res.json() | ||
if (json.errors) { | ||
throw new FetcherError({ | ||
errors: json.errors ?? [{ message: 'Failed to fetch Vendure API' }], | ||
status: res.status, | ||
}) | ||
} | ||
|
||
return { data: json.data, res } | ||
} | ||
|
||
export default fetchGraphqlApi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import zeitFetch from '@vercel/fetch' | ||
|
||
export default zeitFetch() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export type WishlistItem = { product: any; id: number } | ||
export default function () {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { useCallback } from 'react' | ||
import { MutationHook } from '@commerce/utils/types' | ||
import useLogin, { UseLogin } from '@commerce/auth/use-login' | ||
import { CommerceError, ValidationError } from '@commerce/utils/errors' | ||
import useCustomer from '../customer/use-customer' | ||
import { LoginMutation, LoginMutationVariables } from '../schema' | ||
import { loginMutation } from '../lib/mutations/log-in-mutation' | ||
|
||
export default useLogin as UseLogin<typeof handler> | ||
|
||
export const handler: MutationHook<null, {}, any> = { | ||
fetchOptions: { | ||
query: loginMutation, | ||
}, | ||
async fetcher({ input: { email, password }, options, fetch }) { | ||
if (!(email && password)) { | ||
throw new CommerceError({ | ||
message: 'A email and password are required to login', | ||
}) | ||
} | ||
|
||
const variables: LoginMutationVariables = { | ||
username: email, | ||
password, | ||
} | ||
|
||
const { login } = await fetch<LoginMutation>({ | ||
...options, | ||
variables, | ||
}) | ||
|
||
if (login.__typename !== 'CurrentUser') { | ||
throw new ValidationError(login) | ||
} | ||
|
||
return null | ||
}, | ||
useHook: ({ fetch }) => () => { | ||
const { revalidate } = useCustomer() | ||
|
||
return useCallback( | ||
async function login(input) { | ||
const data = await fetch({ input }) | ||
await revalidate() | ||
return data | ||
}, | ||
[fetch, revalidate] | ||
) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { useCallback } from 'react' | ||
import { MutationHook } from '@commerce/utils/types' | ||
import useLogout, { UseLogout } from '@commerce/auth/use-logout' | ||
import useCustomer from '../customer/use-customer' | ||
import { LogoutMutation } from '../schema' | ||
import { logoutMutation } from '../lib/mutations/log-out-mutation' | ||
|
||
export default useLogout as UseLogout<typeof handler> | ||
|
||
export const handler: MutationHook<null> = { | ||
fetchOptions: { | ||
query: logoutMutation, | ||
}, | ||
async fetcher({ options, fetch }) { | ||
await fetch<LogoutMutation>({ | ||
...options, | ||
}) | ||
return null | ||
}, | ||
useHook: ({ fetch }) => () => { | ||
const { mutate } = useCustomer() | ||
|
||
return useCallback( | ||
async function logout() { | ||
const data = await fetch() | ||
await mutate(null, false) | ||
return data | ||
}, | ||
[fetch, mutate] | ||
) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { useCallback } from 'react' | ||
import { MutationHook } from '@commerce/utils/types' | ||
import { CommerceError, ValidationError } from '@commerce/utils/errors' | ||
import useSignup, { UseSignup } from '@commerce/auth/use-signup' | ||
import useCustomer from '../customer/use-customer' | ||
import { | ||
RegisterCustomerInput, | ||
SignupMutation, | ||
SignupMutationVariables, | ||
} from '../schema' | ||
import { signupMutation } from '../lib/mutations/sign-up-mutation' | ||
|
||
export default useSignup as UseSignup<typeof handler> | ||
|
||
export type SignupInput = { | ||
email: string | ||
firstName: string | ||
lastName: string | ||
password: string | ||
} | ||
|
||
export const handler: MutationHook<null, {}, SignupInput, SignupInput> = { | ||
fetchOptions: { | ||
query: signupMutation, | ||
}, | ||
async fetcher({ | ||
input: { firstName, lastName, email, password }, | ||
options, | ||
fetch, | ||
}) { | ||
if (!(firstName && lastName && email && password)) { | ||
throw new CommerceError({ | ||
message: | ||
'A first name, last name, email and password are required to signup', | ||
}) | ||
} | ||
const variables: SignupMutationVariables = { | ||
input: { | ||
firstName, | ||
lastName, | ||
emailAddress: email, | ||
password, | ||
}, | ||
} | ||
const { registerCustomerAccount } = await fetch<SignupMutation>({ | ||
...options, | ||
variables, | ||
}) | ||
|
||
if (registerCustomerAccount.__typename !== 'Success') { | ||
throw new ValidationError(registerCustomerAccount) | ||
} | ||
|
||
return null | ||
}, | ||
useHook: ({ fetch }) => () => { | ||
const { revalidate } = useCustomer() | ||
|
||
return useCallback( | ||
async function signup(input) { | ||
const data = await fetch({ input }) | ||
await revalidate() | ||
return data | ||
}, | ||
[fetch, revalidate] | ||
) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export { default as useCart } from './use-cart' | ||
export { default as useAddItem } from './use-add-item' | ||
export { default as useRemoveItem } from './use-remove-item' | ||
export { default as useWishlistActions } from './use-cart-actions' | ||
export { default as useUpdateItem } from './use-cart-actions' |
Oops, something went wrong.