mirror of
https://github.com/vercel/commerce.git
synced 2025-07-26 19:51:23 +00:00
Shopify Provider (#186)
* Start of Shopify provider * add missing comment to documentation * add missing env vars to documentation * update reference to types file
This commit is contained in:
1
framework/shopify/api/cart/index.ts
Normal file
1
framework/shopify/api/cart/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/catalog/index.ts
Normal file
1
framework/shopify/api/catalog/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/catalog/products.ts
Normal file
1
framework/shopify/api/catalog/products.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/checkout/index.ts
Normal file
1
framework/shopify/api/checkout/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/customers/index.ts
Normal file
1
framework/shopify/api/customers/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/customers/login.ts
Normal file
1
framework/shopify/api/customers/login.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/customers/logout.ts
Normal file
1
framework/shopify/api/customers/logout.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
1
framework/shopify/api/customers/signup.ts
Normal file
1
framework/shopify/api/customers/signup.ts
Normal file
@@ -0,0 +1 @@
|
||||
export default function () {}
|
60
framework/shopify/api/index.ts
Normal file
60
framework/shopify/api/index.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { CommerceAPIConfig } from '@commerce/api'
|
||||
import fetchGraphqlApi from './utils/fetch-graphql-api'
|
||||
|
||||
export interface ShopifyConfig extends CommerceAPIConfig {}
|
||||
|
||||
// No I don't like this - will fix it later
|
||||
const API_URL =
|
||||
process.env.SHOPIFY_STORE_DOMAIN ||
|
||||
process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN
|
||||
const API_TOKEN =
|
||||
process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN ||
|
||||
process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN
|
||||
|
||||
if (!API_URL) {
|
||||
throw new Error(
|
||||
`The environment variable SHOPIFY_STORE_DOMAIN is missing and it's required to access your store`
|
||||
)
|
||||
}
|
||||
|
||||
if (!API_TOKEN) {
|
||||
throw new Error(
|
||||
`The environment variable SHOPIFY_STOREFRONT_ACCESS_TOKEN is missing and it's required to access your store`
|
||||
)
|
||||
}
|
||||
|
||||
export class Config {
|
||||
private config: ShopifyConfig
|
||||
|
||||
constructor(config: ShopifyConfig) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
getConfig(userConfig: Partial<ShopifyConfig> = {}) {
|
||||
return Object.entries(userConfig).reduce<ShopifyConfig>(
|
||||
(cfg, [key, value]) => Object.assign(cfg, { [key]: value }),
|
||||
{ ...this.config }
|
||||
)
|
||||
}
|
||||
|
||||
setConfig(newConfig: Partial<ShopifyConfig>) {
|
||||
Object.assign(this.config, newConfig)
|
||||
}
|
||||
}
|
||||
|
||||
const config = new Config({
|
||||
commerceUrl: API_URL,
|
||||
apiToken: API_TOKEN,
|
||||
// TODO
|
||||
// @ts-ignore
|
||||
fetch: fetchGraphqlApi,
|
||||
customerCookie: 'SHOP_TOKEN',
|
||||
})
|
||||
|
||||
export function getConfig(userConfig?: Partial<ShopifyConfig>) {
|
||||
return config.getConfig(userConfig)
|
||||
}
|
||||
|
||||
export function setConfig(newConfig: Partial<ShopifyConfig>) {
|
||||
return config.setConfig(newConfig)
|
||||
}
|
21
framework/shopify/api/operations/get-all-collections.ts
Normal file
21
framework/shopify/api/operations/get-all-collections.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import Client from 'shopify-buy'
|
||||
import { ShopifyConfig } from '../index'
|
||||
|
||||
type Options = {
|
||||
config: ShopifyConfig
|
||||
}
|
||||
|
||||
const getAllCollections = async (options: Options) => {
|
||||
const { config } = options
|
||||
|
||||
const client = Client.buildClient({
|
||||
storefrontAccessToken: config.apiToken,
|
||||
domain: config.commerceUrl,
|
||||
})
|
||||
|
||||
const res = await client.collection.fetchAllWithProducts()
|
||||
|
||||
return JSON.parse(JSON.stringify(res))
|
||||
}
|
||||
|
||||
export default getAllCollections
|
27
framework/shopify/api/operations/get-page.ts
Normal file
27
framework/shopify/api/operations/get-page.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { ShopifyConfig, getConfig } from '..'
|
||||
import type { Page } from '../../types'
|
||||
|
||||
export type { Page }
|
||||
|
||||
export type GetPageResult<T extends { page?: any } = { page?: Page }> = T
|
||||
|
||||
export type PageVariables = {
|
||||
id: string
|
||||
}
|
||||
|
||||
async function getPage({
|
||||
url,
|
||||
variables,
|
||||
config,
|
||||
preview,
|
||||
}: {
|
||||
url?: string
|
||||
variables: PageVariables
|
||||
config?: ShopifyConfig
|
||||
preview?: boolean
|
||||
}): Promise<GetPageResult> {
|
||||
config = getConfig(config)
|
||||
return {}
|
||||
}
|
||||
|
||||
export default getPage
|
51
framework/shopify/api/utils/fetch-graphql-api.ts
Normal file
51
framework/shopify/api/utils/fetch-graphql-api.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { CommerceAPIFetchOptions } from '@commerce/api'
|
||||
import { FetcherError } from '@commerce/utils/errors'
|
||||
import { getConfig } from '../index'
|
||||
|
||||
export interface GraphQLFetcherResult<Data = any> {
|
||||
data: Data
|
||||
res: Response
|
||||
}
|
||||
export type GraphQLFetcher<
|
||||
Data extends GraphQLFetcherResult = GraphQLFetcherResult,
|
||||
Variables = any
|
||||
> = (
|
||||
query: string,
|
||||
queryData?: CommerceAPIFetchOptions<Variables>,
|
||||
fetchOptions?: RequestInit
|
||||
) => Promise<Data>
|
||||
|
||||
const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
query: string,
|
||||
{ variables } = {},
|
||||
fetchOptions
|
||||
) => {
|
||||
const config = getConfig()
|
||||
const url = `https://${config.commerceUrl}/api/2020-10/graphql.json`
|
||||
|
||||
const res = await fetch(url, {
|
||||
...fetchOptions,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Shopify-Storefront-Access-Token': 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 Shopify API' }],
|
||||
status: res.status,
|
||||
})
|
||||
}
|
||||
|
||||
return { data: json.data, res }
|
||||
}
|
||||
|
||||
export default fetchGraphqlApi
|
2
framework/shopify/api/wishlist/index.tsx
Normal file
2
framework/shopify/api/wishlist/index.tsx
Normal file
@@ -0,0 +1,2 @@
|
||||
export type WishlistItem = { product: any; id: number }
|
||||
export default function () {}
|
Reference in New Issue
Block a user