Skip to content

Commit

Permalink
Update Swell Provider (vercel#359)
Browse files Browse the repository at this point in the history
* fix update cart item

* update types

* update checkout

* update get-page, cleanup types

* revert change to incorrect file

* cleanup

Co-authored-by: Greg Hoskin <[email protected]>
  • Loading branch information
greph and Greg Hoskin authored Jun 14, 2021
1 parent ddd4631 commit 4d85b43
Show file tree
Hide file tree
Showing 55 changed files with 502 additions and 544 deletions.
20 changes: 0 additions & 20 deletions framework/swell/api/checkout/index.ts

This file was deleted.

1 change: 0 additions & 1 deletion framework/swell/api/customers/login.ts

This file was deleted.

1 change: 1 addition & 0 deletions framework/swell/api/endpoints/cart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
1 change: 1 addition & 0 deletions framework/swell/api/endpoints/catalog/products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
30 changes: 30 additions & 0 deletions framework/swell/api/endpoints/checkout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CommerceAPI, createEndpoint, GetAPISchema } from '@commerce/api'
import { CheckoutSchema } from '@commerce/types/checkout'
import { SWELL_CHECKOUT_URL_COOKIE } from '../../../const'
import checkoutEndpoint from '@commerce/api/endpoints/checkout'

const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({
req,
res,
config,
}) => {
const { cookies } = req
const checkoutUrl = cookies[SWELL_CHECKOUT_URL_COOKIE]

if (checkoutUrl) {
res.redirect(checkoutUrl)
} else {
res.redirect('/cart')
}
}
export const handlers: CheckoutEndpoint['handlers'] = { checkout }

export type CheckoutAPI = GetAPISchema<CommerceAPI, CheckoutSchema>
export type CheckoutEndpoint = CheckoutAPI['endpoint']

const checkoutApi = createEndpoint<CheckoutAPI>({
handler: checkoutEndpoint,
handlers,
})

export default checkoutApi
1 change: 1 addition & 0 deletions framework/swell/api/endpoints/customer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
1 change: 1 addition & 0 deletions framework/swell/api/endpoints/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
1 change: 1 addition & 0 deletions framework/swell/api/endpoints/logout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
1 change: 1 addition & 0 deletions framework/swell/api/endpoints/signup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
1 change: 1 addition & 0 deletions framework/swell/api/endpoints/wishlist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function (_commerce: any) {}
57 changes: 30 additions & 27 deletions framework/swell/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,53 @@
import type { CommerceAPIConfig } from '@commerce/api'

import {
CommerceAPI,
CommerceAPIConfig,
getCommerceApi as commerceApi,
} from '@commerce/api'
import {
SWELL_CHECKOUT_ID_COOKIE,
SWELL_CUSTOMER_TOKEN_COOKIE,
SWELL_COOKIE_EXPIRE,
} from '../const'

import fetchApi from './utils/fetch-swell-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 getAllProductPaths from './operations/get-all-product-paths'
import getAllProducts from './operations/get-all-products'
import getProduct from './operations/get-product'

export interface SwellConfig extends CommerceAPIConfig {
fetch: any
}

export class Config {
private config: SwellConfig

constructor(config: SwellConfig) {
this.config = config
}

getConfig(userConfig: Partial<SwellConfig> = {}) {
return Object.entries(userConfig).reduce<SwellConfig>(
(cfg, [key, value]) => Object.assign(cfg, { [key]: value }),
{ ...this.config }
)
}

setConfig(newConfig: Partial<SwellConfig>) {
Object.assign(this.config, newConfig)
}
}

const config = new Config({
const config: SwellConfig = {
locale: 'en-US',
commerceUrl: '',
apiToken: ''!,
cartCookie: SWELL_CHECKOUT_ID_COOKIE,
cartCookieMaxAge: SWELL_COOKIE_EXPIRE,
fetch: fetchApi,
customerCookie: SWELL_CUSTOMER_TOKEN_COOKIE,
})
}

export function getConfig(userConfig?: Partial<SwellConfig>) {
return config.getConfig(userConfig)
const operations = {
login,
getAllPages,
getPage,
getSiteInfo,
getAllProductPaths,
getAllProducts,
getProduct,
}

export function setConfig(newConfig: Partial<SwellConfig>) {
return config.setConfig(newConfig)
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)
}
45 changes: 45 additions & 0 deletions framework/swell/api/operations/get-all-pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Provider, SwellConfig } from '..'
import type { OperationContext } from '@commerce/api/operations'
import type { Page } from '../../types/page'

export type GetAllPagesResult<
T extends { pages: any[] } = { pages: Page[] }
> = T

export default function getAllPagesOperation({
commerce,
}: OperationContext<Provider>) {
async function getAllPages(opts?: {
config?: Partial<SwellConfig>
preview?: boolean
}): Promise<GetAllPagesResult>

async function getAllPages<T extends { pages: any[] }>(opts: {
url: string
config?: Partial<SwellConfig>
preview?: boolean
}): Promise<GetAllPagesResult<T>>

async function getAllPages({
config: cfg,
preview,
}: {
url?: string
config?: Partial<SwellConfig>
preview?: boolean
} = {}): Promise<GetAllPagesResult> {
const config = commerce.getConfig(cfg)
const { locale, fetch } = config
const data = await fetch('content', 'list', ['pages'])
const pages =
data?.results?.map(({ slug, ...rest }: { slug: string }) => ({
url: `/${locale}/${slug}`,
...rest,
})) ?? []
return {
pages,
}
}

return getAllPages
}
48 changes: 48 additions & 0 deletions framework/swell/api/operations/get-all-product-paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { SwellProduct } from '../../types'
import { SwellConfig, Provider } from '..'
import { OperationContext, OperationOptions } from '@commerce/api/operations'
import { GetAllProductPathsOperation } from '@commerce/types/product'

export default function getAllProductPathsOperation({
commerce,
}: OperationContext<Provider>) {
async function getAllProductPaths<
T extends GetAllProductPathsOperation
>(opts?: {
variables?: T['variables']
config?: SwellConfig
}): Promise<T['data']>

async function getAllProductPaths<T extends GetAllProductPathsOperation>(
opts: {
variables?: T['variables']
config?: SwellConfig
} & OperationOptions
): Promise<T['data']>

async function getAllProductPaths<T extends GetAllProductPathsOperation>({
variables,
config: cfg,
}: {
query?: string
variables?: T['variables']
config?: SwellConfig
} = {}): 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 { results } = await config.fetch('products', 'list', [
{
limit: variables?.first,
},
])

return {
products: results?.map(({ slug: handle }: SwellProduct) => ({
path: `/${handle}`,
})),
}
}

return getAllProductPaths
}
43 changes: 43 additions & 0 deletions framework/swell/api/operations/get-all-products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { normalizeProduct } from '../../utils/normalize'
import { SwellProduct } from '../../types'
import { Product } from '@commerce/types/product'
import { Provider, SwellConfig } from '../'
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<SwellConfig>
preview?: boolean
}): Promise<{ products: Product[] }>

async function getAllProducts({
config: cfg,
variables = { first: 250 },
}: {
query?: string
variables?: ProductVariables
config?: Partial<SwellConfig>
preview?: boolean
} = {}): Promise<{ products: Product[] | any[] }> {
const config = commerce.getConfig(cfg)
const { results } = await config.fetch('products', 'list', [
{
limit: variables.first,
},
])
const products = results.map((product: SwellProduct) =>
normalizeProduct(product)
)

return {
products,
}
}

return getAllProducts
}
63 changes: 46 additions & 17 deletions framework/swell/api/operations/get-page.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,54 @@
import { Page } from '../../schema'
import { SwellConfig, getConfig } from '..'
import { SwellConfig, Provider } from '..'
import { OperationContext, OperationOptions } from '@commerce/api/operations'
import { GetPageOperation } from '../../types/page'

export type GetPageResult<T extends { page?: any } = { page?: Page }> = T

export type PageVariables = {
id: string
id: number
}

async function getPage({
url,
variables,
config,
preview,
}: {
url?: string
variables: PageVariables
config?: SwellConfig
preview?: boolean
}): Promise<GetPageResult> {
config = getConfig(config)
return {}
}
export default function getPageOperation({
commerce,
}: OperationContext<Provider>) {
async function getPage<T extends GetPageOperation>(opts: {
variables: T['variables']
config?: Partial<SwellConfig>
preview?: boolean
}): Promise<T['data']>

async function getPage<T extends GetPageOperation>(
opts: {
variables: T['variables']
config?: Partial<SwellConfig>
preview?: boolean
} & OperationOptions
): Promise<T['data']>

async function getPage<T extends GetPageOperation>({
variables,
config,
}: {
query?: string
variables: T['variables']
config?: Partial<SwellConfig>
preview?: boolean
}): Promise<T['data']> {
const { fetch, locale = 'en-US' } = commerce.getConfig(config)
const id = variables.id
const result = await fetch('content', 'get', ['pages', id])
const page = result

export default getPage
return {
page: page
? {
...page,
url: `/${locale}/${page.slug}`,
}
: null,
}
}

return getPage
}
33 changes: 33 additions & 0 deletions framework/swell/api/operations/get-product.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { normalizeProduct } from '../../utils'

import { Product } from '@commerce/types/product'
import { OperationContext } from '@commerce/api/operations'
import { Provider, SwellConfig } from '../'

export default function getProductOperation({
commerce,
}: OperationContext<Provider>) {
async function getProduct({
variables,
config: cfg,
}: {
query?: string
variables: { slug: string }
config?: Partial<SwellConfig>
preview?: boolean
}): Promise<Product | {} | any> {
const config = commerce.getConfig(cfg)

const product = await config.fetch('products', 'get', [variables.slug])

if (product && product.variants) {
product.variants = product.variants?.results
}

return {
product: product ? normalizeProduct(product) : null,
}
}

return getProduct
}
Loading

0 comments on commit 4d85b43

Please sign in to comment.