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:
Peter Mekhaeil
2021-02-12 22:14:16 +08:00
committed by GitHub
parent 85f429c115
commit 300d04c1ac
39 changed files with 1245 additions and 2 deletions

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View File

@@ -0,0 +1 @@
export default function () {}

View 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)
}

View 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

View 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

View 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

View File

@@ -0,0 +1,2 @@
export type WishlistItem = { product: any; id: number }
export default function () {}