Add ordercloud provider (#500)

* Add ordercloud provider

* Fix provider errors

* Make submit checkout optional

* Make submit checkout optional

* Remove nullables when creating endpoint type

* Update readme

* Log checkout error

* Log error

* Save token to cookie

* Update fetch rest

* Use token at checkout

Co-authored-by: Luis Alvarez <luis@vercel.com>
This commit is contained in:
Gonzalo Pozzo
2021-10-05 09:49:01 -03:00
committed by GitHub
parent f9644fecef
commit 3f0c38461b
90 changed files with 2560 additions and 76 deletions

View File

@@ -0,0 +1,22 @@
import type { OrdercloudConfig } from '../'
import { GetAllPagesOperation } from '@commerce/types/page'
export type Page = { url: string }
export type GetAllPagesResult = { pages: Page[] }
export default function getAllPagesOperation() {
async function getAllPages<T extends GetAllPagesOperation>({
config,
preview,
}: {
url?: string
config?: Partial<OrdercloudConfig>
preview?: boolean
} = {}): Promise<T['data']> {
return Promise.resolve({
pages: [],
})
}
return getAllPages
}

View File

@@ -0,0 +1,34 @@
import type { OperationContext } from '@commerce/api/operations'
import type { GetAllProductPathsOperation } from '@commerce/types/product'
import type { RawProduct } from '../../types/product'
import type { OrdercloudConfig, Provider } from '../'
export type GetAllProductPathsResult = {
products: Array<{ path: string }>
}
export default function getAllProductPathsOperation({
commerce,
}: OperationContext<Provider>) {
async function getAllProductPaths<T extends GetAllProductPathsOperation>({
config,
}: {
config?: Partial<OrdercloudConfig>
} = {}): Promise<T['data']> {
// Get fetch from the config
const { restBuyerFetch } = commerce.getConfig(config)
// Get all products
const rawProducts: RawProduct[] = await restBuyerFetch<{
Items: RawProduct[]
}>('GET', '/me/products').then((response) => response.Items)
return {
// Match a path for every product retrieved
products: rawProducts.map((product) => ({ path: `/${product.ID}` })),
}
}
return getAllProductPaths
}

View File

@@ -0,0 +1,35 @@
import type { GetAllProductsOperation } from '@commerce/types/product'
import type { OperationContext } from '@commerce/api/operations'
import type { RawProduct } from '../../types/product'
import type { OrdercloudConfig, Provider } from '../index'
import { normalize as normalizeProduct } from '../../utils/product'
export default function getAllProductsOperation({
commerce,
}: OperationContext<Provider>) {
async function getAllProducts<T extends GetAllProductsOperation>({
config,
}: {
query?: string
variables?: T['variables']
config?: Partial<OrdercloudConfig>
preview?: boolean
} = {}): Promise<T['data']> {
// Get fetch from the config
const { restBuyerFetch } = commerce.getConfig(config)
// Get all products
const rawProducts: RawProduct[] = await restBuyerFetch<{
Items: RawProduct[]
}>('GET', '/me/products').then((response) => response.Items)
return {
// Normalize products to commerce schema
products: rawProducts.map(normalizeProduct),
}
}
return getAllProducts
}

View File

@@ -0,0 +1,15 @@
import { GetPageOperation } from "@commerce/types/page"
export type Page = any
export type GetPageResult = { page?: Page }
export type PageVariables = {
id: number
}
export default function getPageOperation() {
async function getPage<T extends GetPageOperation>(): Promise<T['data']> {
return Promise.resolve({})
}
return getPage
}

View File

@@ -0,0 +1,60 @@
import type { OperationContext } from '@commerce/api/operations'
import type { GetProductOperation } from '@commerce/types/product'
import type { RawProduct, RawSpec, RawVariant } from '../../types/product'
import type { OrdercloudConfig, Provider } from '../index'
import { normalize as normalizeProduct } from '../../utils/product'
export default function getProductOperation({
commerce,
}: OperationContext<Provider>) {
async function getProduct<T extends GetProductOperation>({
config,
variables,
}: {
query?: string
variables?: T['variables']
config?: Partial<OrdercloudConfig>
preview?: boolean
} = {}): Promise<T['data']> {
// Get fetch from the config
const { restBuyerFetch } = commerce.getConfig(config)
// Get a single product
const productPromise = restBuyerFetch<RawProduct>(
'GET',
`/me/products/${variables?.slug}`
)
// Get product specs
const specsPromise = restBuyerFetch<{ Items: RawSpec[] }>(
'GET',
`/me/products/${variables?.slug}/specs`
).then((res) => res.Items)
// Get product variants
const variantsPromise = restBuyerFetch<{ Items: RawVariant[] }>(
'GET',
`/me/products/${variables?.slug}/variants`
).then((res) => res.Items)
// Execute all promises in parallel
const [product, specs, variants] = await Promise.all([
productPromise,
specsPromise,
variantsPromise,
])
// Hydrate product
product.xp.Specs = specs
product.xp.Variants = variants
return {
// Normalize product to commerce schema
product: normalizeProduct(product),
}
}
return getProduct
}

View File

@@ -0,0 +1,46 @@
import type { OperationContext } from '@commerce/api/operations'
import type { Category, GetSiteInfoOperation } from '@commerce/types/site'
import type { RawCategory } from '../../types/category'
import type { OrdercloudConfig, Provider } from '../index'
export type GetSiteInfoResult<
T extends { categories: any[]; brands: any[] } = {
categories: Category[]
brands: any[]
}
> = T
export default function getSiteInfoOperation({
commerce,
}: OperationContext<Provider>) {
async function getSiteInfo<T extends GetSiteInfoOperation>({
config,
}: {
query?: string
variables?: any
config?: Partial<OrdercloudConfig>
preview?: boolean
} = {}): Promise<T['data']> {
// Get fetch from the config
const { restBuyerFetch } = commerce.getConfig(config)
// Get list of categories
const rawCategories: RawCategory[] = await restBuyerFetch<{
Items: RawCategory[]
}>('GET', `/me/categories`).then((response) => response.Items)
return {
// Normalize categories
categories: rawCategories.map((category) => ({
id: category.ID,
name: category.Name,
slug: category.ID,
path: `/${category.ID}`,
})),
brands: [],
}
}
return getSiteInfo
}

View File

@@ -0,0 +1,6 @@
export { default as getAllPages } from './get-all-pages'
export { default as getPage } from './get-page'
export { default as getSiteInfo } from './get-site-info'
export { default as getProduct } from './get-product'
export { default as getAllProducts } from './get-all-products'
export { default as getAllProductPaths } from './get-all-product-paths'