mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
@@ -1 +0,0 @@
|
||||
export default function () {}
|
@@ -1 +0,0 @@
|
||||
export default function () {}
|
@@ -1 +0,0 @@
|
||||
export default function () {}
|
@@ -1 +0,0 @@
|
||||
export default function () {}
|
@@ -1 +0,0 @@
|
||||
export default function () {}
|
@@ -1 +0,0 @@
|
||||
export default function () {}
|
@@ -1 +0,0 @@
|
||||
export default function () {}
|
1
framework/vendure/api/endpoints/cart/index.ts
Normal file
1
framework/vendure/api/endpoints/cart/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
1
framework/vendure/api/endpoints/catalog/index.ts
Normal file
1
framework/vendure/api/endpoints/catalog/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
1
framework/vendure/api/endpoints/catalog/products.ts
Normal file
1
framework/vendure/api/endpoints/catalog/products.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
@@ -1,6 +1,13 @@
|
||||
import { NextApiHandler } from 'next'
|
||||
import { CommerceAPI, createEndpoint, GetAPISchema } from '@commerce/api'
|
||||
import { CheckoutSchema } from '@commerce/types/checkout'
|
||||
import checkoutEndpoint from '@commerce/api/endpoints/checkout'
|
||||
|
||||
const checkoutApi = async (req: any, res: any, config: any) => {
|
||||
const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({
|
||||
req,
|
||||
res,
|
||||
config,
|
||||
}) => {
|
||||
try {
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
@@ -37,27 +44,15 @@ const checkoutApi = async (req: any, res: any, config: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
export type CheckoutAPI = GetAPISchema<CommerceAPI, CheckoutSchema>
|
||||
|
||||
return function apiHandler(req, res) {
|
||||
return handler(req, res, config, ops, opts)
|
||||
}
|
||||
}
|
||||
}
|
||||
export type CheckoutEndpoint = CheckoutAPI['endpoint']
|
||||
|
||||
export default createApiHandler(checkoutApi, {}, {})
|
||||
export const handlers: CheckoutEndpoint['handlers'] = { checkout }
|
||||
|
||||
const checkoutApi = createEndpoint<CheckoutAPI>({
|
||||
handler: checkoutEndpoint,
|
||||
handlers,
|
||||
})
|
||||
|
||||
export default checkoutApi
|
1
framework/vendure/api/endpoints/customer/index.ts
Normal file
1
framework/vendure/api/endpoints/customer/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
1
framework/vendure/api/endpoints/login/index.ts
Normal file
1
framework/vendure/api/endpoints/login/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
1
framework/vendure/api/endpoints/logout/index.ts
Normal file
1
framework/vendure/api/endpoints/logout/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
1
framework/vendure/api/endpoints/signup/index.ts
Normal file
1
framework/vendure/api/endpoints/signup/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
1
framework/vendure/api/endpoints/wishlist/index.tsx
Normal file
1
framework/vendure/api/endpoints/wishlist/index.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
@@ -1,6 +1,16 @@
|
||||
import type { CommerceAPIConfig } from '@commerce/api'
|
||||
import type { APIProvider, CommerceAPIConfig } from '@commerce/api'
|
||||
import { CommerceAPI, getCommerceApi as commerceApi } from '@commerce/api'
|
||||
import fetchGraphqlApi from './utils/fetch-graphql-api'
|
||||
|
||||
import login from './operations/login'
|
||||
import getAllPages from './operations/get-all-pages'
|
||||
import getPage from './operations/get-page'
|
||||
import getSiteInfo from './operations/get-site-info'
|
||||
import getCustomerWishlist from './operations/get-customer-wishlist'
|
||||
import getAllProductPaths from './operations/get-all-product-paths'
|
||||
import getAllProducts from './operations/get-all-products'
|
||||
import getProduct from './operations/get-product'
|
||||
|
||||
export interface VendureConfig extends CommerceAPIConfig {}
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL
|
||||
@@ -11,41 +21,33 @@ if (!API_URL) {
|
||||
)
|
||||
}
|
||||
|
||||
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({
|
||||
const config: VendureConfig = {
|
||||
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)
|
||||
const operations = {
|
||||
login,
|
||||
getAllPages,
|
||||
getPage,
|
||||
getSiteInfo,
|
||||
getCustomerWishlist,
|
||||
getAllProductPaths,
|
||||
getAllProducts,
|
||||
getProduct,
|
||||
}
|
||||
|
||||
export const provider = { config, operations }
|
||||
|
||||
export type Provider = typeof provider
|
||||
|
||||
export function getCommerceApi<P extends Provider>(
|
||||
customProvider: P = provider as any
|
||||
): CommerceAPI<P> {
|
||||
return commerceApi(customProvider)
|
||||
}
|
||||
|
41
framework/vendure/api/operations/get-all-pages.ts
Normal file
41
framework/vendure/api/operations/get-all-pages.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { VendureConfig } from '../'
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
import { Provider } from '../../../bigcommerce/api'
|
||||
|
||||
export type Page = any
|
||||
|
||||
export type GetAllPagesResult<
|
||||
T extends { pages: any[] } = { pages: Page[] }
|
||||
> = T
|
||||
|
||||
export default function getAllPagesOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getAllPages(opts?: {
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<GetAllPagesResult>
|
||||
|
||||
async function getAllPages<T extends { pages: any[] }>(opts: {
|
||||
url: string
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<GetAllPagesResult<T>>
|
||||
|
||||
async function getAllPages({
|
||||
config: cfg,
|
||||
preview,
|
||||
}: {
|
||||
url?: string
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
} = {}): Promise<GetAllPagesResult> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
|
||||
return {
|
||||
pages: [],
|
||||
}
|
||||
}
|
||||
|
||||
return getAllPages
|
||||
}
|
52
framework/vendure/api/operations/get-all-product-paths.ts
Normal file
52
framework/vendure/api/operations/get-all-product-paths.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { OperationContext, OperationOptions } from '@commerce/api/operations'
|
||||
import type { GetAllProductPathsQuery } from '../../schema'
|
||||
import { Provider } from '../index'
|
||||
import { getAllProductPathsQuery } from '../../utils/queries/get-all-product-paths-query'
|
||||
import { GetAllProductPathsOperation } from '@commerce/types/product'
|
||||
import { BigcommerceConfig } from '../../../bigcommerce/api'
|
||||
|
||||
export type GetAllProductPathsResult = {
|
||||
products: Array<{ node: { path: string } }>
|
||||
}
|
||||
|
||||
export default function getAllProductPathsOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getAllProductPaths<
|
||||
T extends GetAllProductPathsOperation
|
||||
>(opts?: {
|
||||
variables?: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<T['data']>
|
||||
|
||||
async function getAllProductPaths<T extends GetAllProductPathsOperation>(
|
||||
opts: {
|
||||
variables?: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
|
||||
async function getAllProductPaths<T extends GetAllProductPathsOperation>({
|
||||
query = getAllProductPathsQuery,
|
||||
variables,
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables?: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
} = {}): Promise<T['data']> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||
// required in case there's a custom `query`
|
||||
const { data } = await config.fetch<GetAllProductPathsQuery>(query, {
|
||||
variables,
|
||||
})
|
||||
const products = data.products.items
|
||||
|
||||
return {
|
||||
products: products.map((p) => ({ path: `/${p.slug}` })),
|
||||
}
|
||||
}
|
||||
|
||||
return getAllProductPaths
|
||||
}
|
46
framework/vendure/api/operations/get-all-products.ts
Normal file
46
framework/vendure/api/operations/get-all-products.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Product } from '@commerce/types/product'
|
||||
import { Provider, VendureConfig } from '../'
|
||||
import { GetAllProductsQuery } from '../../schema'
|
||||
import { normalizeSearchResult } from '../../utils/normalize'
|
||||
import { getAllProductsQuery } from '../../utils/queries/get-all-products-query'
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
|
||||
export type ProductVariables = { first?: number }
|
||||
|
||||
export default function getAllProductsOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getAllProducts(opts?: {
|
||||
variables?: ProductVariables
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<{ products: Product[] }>
|
||||
|
||||
async function getAllProducts({
|
||||
query = getAllProductsQuery,
|
||||
variables: { ...vars } = {},
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables?: ProductVariables
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
} = {}): Promise<{ products: Product[] | any[] }> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
const variables = {
|
||||
input: {
|
||||
take: vars.first,
|
||||
groupByProduct: true,
|
||||
},
|
||||
}
|
||||
const { data } = await config.fetch<GetAllProductsQuery>(query, {
|
||||
variables,
|
||||
})
|
||||
|
||||
return {
|
||||
products: data.search.items.map((item) => normalizeSearchResult(item)),
|
||||
}
|
||||
}
|
||||
|
||||
return getAllProducts
|
||||
}
|
23
framework/vendure/api/operations/get-customer-wishlist.ts
Normal file
23
framework/vendure/api/operations/get-customer-wishlist.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
import { Provider, VendureConfig } from '../'
|
||||
|
||||
export default function getCustomerWishlistOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getCustomerWishlist({
|
||||
config: cfg,
|
||||
variables,
|
||||
includeProducts,
|
||||
}: {
|
||||
url?: string
|
||||
variables: any
|
||||
config?: Partial<VendureConfig>
|
||||
includeProducts?: boolean
|
||||
}): Promise<any> {
|
||||
// Not implemented as Vendure does not ship with wishlist functionality at present
|
||||
const config = commerce.getConfig(cfg)
|
||||
return { wishlist: {} }
|
||||
}
|
||||
|
||||
return getCustomerWishlist
|
||||
}
|
45
framework/vendure/api/operations/get-page.ts
Normal file
45
framework/vendure/api/operations/get-page.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { VendureConfig, Provider } from '../'
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
|
||||
export type Page = any
|
||||
|
||||
export type GetPageResult<T extends { page?: any } = { page?: Page }> = T
|
||||
|
||||
export type PageVariables = {
|
||||
id: number
|
||||
}
|
||||
|
||||
export default function getPageOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getPage(opts: {
|
||||
url?: string
|
||||
variables: PageVariables
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<GetPageResult>
|
||||
|
||||
async function getPage<T extends { page?: any }, V = any>(opts: {
|
||||
url: string
|
||||
variables: V
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<GetPageResult<T>>
|
||||
|
||||
async function getPage({
|
||||
url,
|
||||
variables,
|
||||
config: cfg,
|
||||
preview,
|
||||
}: {
|
||||
url?: string
|
||||
variables: PageVariables
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<GetPageResult> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
return {}
|
||||
}
|
||||
|
||||
return getPage
|
||||
}
|
69
framework/vendure/api/operations/get-product.ts
Normal file
69
framework/vendure/api/operations/get-product.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Product } from '@commerce/types/product'
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
import { Provider, VendureConfig } from '../'
|
||||
import { GetProductQuery } from '../../schema'
|
||||
import { getProductQuery } from '../../utils/queries/get-product-query'
|
||||
|
||||
export default function getProductOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getProduct({
|
||||
query = getProductQuery,
|
||||
variables,
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables: { slug: string }
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<Product | {} | any> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
|
||||
const locale = config.locale
|
||||
const { data } = await config.fetch<GetProductQuery>(query, { variables })
|
||||
const product = data.product
|
||||
|
||||
if (product) {
|
||||
const getOptionGroupName = (id: string): string => {
|
||||
return product.optionGroups.find((og) => og.id === id)!.name
|
||||
}
|
||||
return {
|
||||
product: {
|
||||
id: product.id,
|
||||
name: product.name,
|
||||
description: product.description,
|
||||
slug: product.slug,
|
||||
images: product.assets.map((a) => ({
|
||||
url: a.preview,
|
||||
alt: a.name,
|
||||
})),
|
||||
variants: product.variants.map((v) => ({
|
||||
id: v.id,
|
||||
options: v.options.map((o) => ({
|
||||
// This __typename property is required in order for the correct
|
||||
// variant selection to work, see `components/product/helpers.ts`
|
||||
// `getVariant()` function.
|
||||
__typename: 'MultipleChoiceOption',
|
||||
id: o.id,
|
||||
displayName: getOptionGroupName(o.groupId),
|
||||
values: [{ label: o.name }],
|
||||
})),
|
||||
})),
|
||||
price: {
|
||||
value: product.variants[0].priceWithTax / 100,
|
||||
currencyCode: product.variants[0].currencyCode,
|
||||
},
|
||||
options: product.optionGroups.map((og) => ({
|
||||
id: og.id,
|
||||
displayName: og.name,
|
||||
values: og.options.map((o) => ({ label: o.name })),
|
||||
})),
|
||||
} as Product,
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
return getProduct
|
||||
}
|
50
framework/vendure/api/operations/get-site-info.ts
Normal file
50
framework/vendure/api/operations/get-site-info.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Provider, VendureConfig } from '../'
|
||||
import { GetCollectionsQuery } from '../../schema'
|
||||
import { arrayToTree } from '../../utils/array-to-tree'
|
||||
import { getCollectionsQuery } from '../../utils/queries/get-collections-query'
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
import { Category } from '@commerce/types/site'
|
||||
|
||||
export type GetSiteInfoResult<
|
||||
T extends { categories: any[]; brands: any[] } = {
|
||||
categories: Category[]
|
||||
brands: any[]
|
||||
}
|
||||
> = T
|
||||
|
||||
export default function getSiteInfoOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getSiteInfo({
|
||||
query = getCollectionsQuery,
|
||||
variables,
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables?: any
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
} = {}): Promise<GetSiteInfoResult> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
// RecursivePartial forces the method to check for every prop in the data, which is
|
||||
// required in case there's a custom `query`
|
||||
const { data } = await config.fetch<GetCollectionsQuery>(query, {
|
||||
variables,
|
||||
})
|
||||
const collections = data.collections?.items.map((i) => ({
|
||||
...i,
|
||||
entityId: i.id,
|
||||
path: i.slug,
|
||||
productCount: i.productVariants.totalItems,
|
||||
}))
|
||||
const categories = arrayToTree(collections).children
|
||||
const brands = [] as any[]
|
||||
|
||||
return {
|
||||
categories: categories ?? [],
|
||||
brands,
|
||||
}
|
||||
}
|
||||
|
||||
return getSiteInfo
|
||||
}
|
60
framework/vendure/api/operations/login.ts
Normal file
60
framework/vendure/api/operations/login.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { ServerResponse } from 'http'
|
||||
import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@commerce/api/operations'
|
||||
import { ValidationError } from '@commerce/utils/errors'
|
||||
import type { LoginOperation } from '../../types/login'
|
||||
import type { LoginMutation } from '../../schema'
|
||||
import { Provider, VendureConfig } from '..'
|
||||
import { loginMutation } from '../../utils/mutations/log-in-mutation'
|
||||
|
||||
export default function loginOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function login<T extends LoginOperation>(opts: {
|
||||
variables: T['variables']
|
||||
config?: Partial<VendureConfig>
|
||||
res: ServerResponse
|
||||
}): Promise<T['data']>
|
||||
|
||||
async function login<T extends LoginOperation>(
|
||||
opts: {
|
||||
variables: T['variables']
|
||||
config?: Partial<VendureConfig>
|
||||
res: ServerResponse
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
|
||||
async function login<T extends LoginOperation>({
|
||||
query = loginMutation,
|
||||
variables,
|
||||
res: response,
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables: T['variables']
|
||||
res: ServerResponse
|
||||
config?: Partial<VendureConfig>
|
||||
}): Promise<T['data']> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
|
||||
const { data, res } = await config.fetch<LoginMutation>(query, {
|
||||
variables,
|
||||
})
|
||||
switch (data.login.__typename) {
|
||||
case 'NativeAuthStrategyError':
|
||||
case 'InvalidCredentialsError':
|
||||
case 'NotVerifiedError':
|
||||
throw new ValidationError({
|
||||
code: data.login.errorCode,
|
||||
message: data.login.message,
|
||||
})
|
||||
}
|
||||
return {
|
||||
result: data.login.id,
|
||||
}
|
||||
}
|
||||
|
||||
return login
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
import { FetcherError } from '@commerce/utils/errors'
|
||||
import type { GraphQLFetcher } from '@commerce/api'
|
||||
import { getConfig } from '..'
|
||||
import { getCommerceApi } from '../'
|
||||
import fetch from './fetch'
|
||||
|
||||
const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
@@ -8,12 +8,11 @@ const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
{ variables, preview } = {},
|
||||
fetchOptions
|
||||
) => {
|
||||
const config = getConfig()
|
||||
const config = getCommerceApi().getConfig()
|
||||
const res = await fetch(config.commerceUrl, {
|
||||
...fetchOptions,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${config.apiToken}`,
|
||||
...fetchOptions?.headers,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
|
@@ -1,2 +0,0 @@
|
||||
export type WishlistItem = { product: any; id: number }
|
||||
export default function () {}
|
Reference in New Issue
Block a user