mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 15:06:59 +00:00
Initial api integration
Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
parent
bba842950c
commit
e3ad683cf2
3
packages/opencommerce/.env.template
Normal file
3
packages/opencommerce/.env.template
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
COMMERCE_PROVIDER=shopify
|
||||||
|
|
||||||
|
OPENCOMMERCE_STOREFRONT_API_URL=
|
2
packages/opencommerce/.prettierignore
Normal file
2
packages/opencommerce/.prettierignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
6
packages/opencommerce/.prettierrc
Normal file
6
packages/opencommerce/.prettierrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false
|
||||||
|
}
|
79
packages/opencommerce/package.json
Normal file
79
packages/opencommerce/package.json
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"name": "@vercel/commerce-opencommerce",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"release": "taskr release",
|
||||||
|
"build": "taskr build",
|
||||||
|
"dev": "taskr",
|
||||||
|
"types": "tsc --emitDeclarationOnly",
|
||||||
|
"prettier-fix": "prettier --write ."
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": "./dist/index.js",
|
||||||
|
"./*": [
|
||||||
|
"./dist/*.js",
|
||||||
|
"./dist/*/index.js"
|
||||||
|
],
|
||||||
|
"./next.config": "./dist/next.config.cjs"
|
||||||
|
},
|
||||||
|
"typesVersions": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"src/*",
|
||||||
|
"src/*/index"
|
||||||
|
],
|
||||||
|
"next.config": [
|
||||||
|
"dist/next.config.d.cts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"typesVersions": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"dist/*.d.ts",
|
||||||
|
"dist/*/index.d.ts"
|
||||||
|
],
|
||||||
|
"next.config": [
|
||||||
|
"dist/next.config.d.cts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vercel/commerce": "^0.0.1",
|
||||||
|
"@vercel/fetch": "^6.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": "^12",
|
||||||
|
"react": "^17",
|
||||||
|
"react-dom": "^17"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@taskr/clear": "^1.1.0",
|
||||||
|
"@taskr/esnext": "^1.1.0",
|
||||||
|
"@taskr/watch": "^1.1.0",
|
||||||
|
"@types/node": "^17.0.8",
|
||||||
|
"@types/react": "^17.0.38",
|
||||||
|
"lint-staged": "^12.1.7",
|
||||||
|
"next": "^12.0.8",
|
||||||
|
"prettier": "^2.5.1",
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"taskr": "^1.1.0",
|
||||||
|
"taskr-swc": "^0.0.1",
|
||||||
|
"typescript": "^4.5.4"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"**/*.{js,jsx,ts,tsx,json}": [
|
||||||
|
"prettier --write",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
1
packages/opencommerce/src/api/endpoints/cart.ts
Normal file
1
packages/opencommerce/src/api/endpoints/cart.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default function (_commerce: any) {}
|
40
packages/opencommerce/src/api/index.ts
Normal file
40
packages/opencommerce/src/api/index.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
CommerceAPI,
|
||||||
|
CommerceAPIConfig,
|
||||||
|
getCommerceApi as commerceApi,
|
||||||
|
} from '@vercel/commerce/api'
|
||||||
|
import createFetchGraphqlApi from './utils/fetch-grapql-api'
|
||||||
|
|
||||||
|
const API_URL = process.env.OPENCOMMERCE_STOREFRONT_API_URL
|
||||||
|
|
||||||
|
if (!API_URL) {
|
||||||
|
throw new Error(
|
||||||
|
`The environment variable OPENCOMMERCE_STOREFRONT_API_URL is missing and it's required to access your store`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OpenCommerceConfig extends CommerceAPIConfig {}
|
||||||
|
|
||||||
|
const ONE_DAY = 60 * 60 * 24
|
||||||
|
|
||||||
|
const config: OpenCommerceConfig = {
|
||||||
|
commerceUrl: `${API_URL}/graphql`,
|
||||||
|
apiToken: '',
|
||||||
|
customerCookie: 'opencommerce_customerToken',
|
||||||
|
cartCookie: 'opencommerce_cartId',
|
||||||
|
cartCookieMaxAge: ONE_DAY * 30,
|
||||||
|
fetch: createFetchGraphqlApi(() => getCommerceApi().getConfig()),
|
||||||
|
}
|
||||||
|
|
||||||
|
const operations = {}
|
||||||
|
export const provider = { config, operations }
|
||||||
|
|
||||||
|
export type Provider = typeof provider
|
||||||
|
|
||||||
|
export type OpenCommerceAPI<P extends Provider = Provider> = CommerceAPI<P>
|
||||||
|
|
||||||
|
export function getCommerceApi<P extends Provider>(
|
||||||
|
customProvider: P = provider as any
|
||||||
|
): OpenCommerceAPI<P> {
|
||||||
|
return commerceApi(customProvider)
|
||||||
|
}
|
59
packages/opencommerce/src/api/operations/get-all-products.ts
Normal file
59
packages/opencommerce/src/api/operations/get-all-products.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import type {
|
||||||
|
OperationContext,
|
||||||
|
OperationOptions,
|
||||||
|
} from '@vercel/commerce/api/operations'
|
||||||
|
import { GetAllProductsOperation } from '../../types/product'
|
||||||
|
import {
|
||||||
|
GetAllProductsQuery,
|
||||||
|
GetAllProductsQueryVariables,
|
||||||
|
Product as ShopifyProduct,
|
||||||
|
} from '../../../schema'
|
||||||
|
import type { ShopifyConfig, Provider } from '..'
|
||||||
|
import getAllProductsQuery from '../../utils/queries/get-all-products-query'
|
||||||
|
import { normalizeProduct } from '../../utils'
|
||||||
|
|
||||||
|
export default function getAllProductsOperation({
|
||||||
|
commerce,
|
||||||
|
}: OperationContext<Provider>) {
|
||||||
|
async function getAllProducts<T extends GetAllProductsOperation>(opts?: {
|
||||||
|
variables?: T['variables']
|
||||||
|
config?: Partial<ShopifyConfig>
|
||||||
|
preview?: boolean
|
||||||
|
}): Promise<T['data']>
|
||||||
|
|
||||||
|
async function getAllProducts<T extends GetAllProductsOperation>({
|
||||||
|
query = getAllProductsQuery,
|
||||||
|
variables,
|
||||||
|
config,
|
||||||
|
}: {
|
||||||
|
query?: string
|
||||||
|
variables?: T['variables']
|
||||||
|
config?: Partial<ShopifyConfig>
|
||||||
|
preview?: boolean
|
||||||
|
} = {}): Promise<T['data']> {
|
||||||
|
const { fetch, locale } = commerce.getConfig(config)
|
||||||
|
|
||||||
|
const { data } = await fetch<
|
||||||
|
GetAllProductsQuery,
|
||||||
|
GetAllProductsQueryVariables
|
||||||
|
>(
|
||||||
|
query,
|
||||||
|
{ variables },
|
||||||
|
{
|
||||||
|
...(locale && {
|
||||||
|
headers: {
|
||||||
|
'Accept-Language': locale,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
products: data.products.edges.map(({ node }) =>
|
||||||
|
normalizeProduct(node as ShopifyProduct)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAllProducts
|
||||||
|
}
|
39
packages/opencommerce/src/api/utils/fetch-grapql-api.ts
Normal file
39
packages/opencommerce/src/api/utils/fetch-grapql-api.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { FetcherError } from '@vercel/commerce/utils/errors'
|
||||||
|
import type { GraphQLFetcher } from '@vercel/commerce/api'
|
||||||
|
import type { OpenCommerceConfig } from '../index'
|
||||||
|
import fetch from './fetch'
|
||||||
|
|
||||||
|
const fetchGraphqlApi: (
|
||||||
|
getConfig: () => OpenCommerceConfig
|
||||||
|
) => GraphQLFetcher =
|
||||||
|
(getConfig) =>
|
||||||
|
async (query: string, { variables, preview } = {}, fetchOptions) => {
|
||||||
|
// log.warn(query)
|
||||||
|
const config = getConfig()
|
||||||
|
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
|
||||||
|
...fetchOptions,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...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 OpenCommerce API' },
|
||||||
|
],
|
||||||
|
status: res.status,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return { data: json.data, res }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default fetchGraphqlApi
|
3
packages/opencommerce/src/api/utils/fetch.ts
Normal file
3
packages/opencommerce/src/api/utils/fetch.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import vercelFetch from '@vercel/fetch'
|
||||||
|
|
||||||
|
export default vercelFetch()
|
10
packages/opencommerce/src/commerce.config.json
Normal file
10
packages/opencommerce/src/commerce.config.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"provider": "opencommerce",
|
||||||
|
"features": {
|
||||||
|
"wishlist": false,
|
||||||
|
"cart": true,
|
||||||
|
"search": true,
|
||||||
|
"customerAuth": false,
|
||||||
|
"customCheckout": true
|
||||||
|
}
|
||||||
|
}
|
0
packages/opencommerce/src/index.ts
Normal file
0
packages/opencommerce/src/index.ts
Normal file
8
packages/opencommerce/src/next.config.cjs
Normal file
8
packages/opencommerce/src/next.config.cjs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
const commerce = require('./commerce.config.json')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
commerce,
|
||||||
|
images: {
|
||||||
|
domains: ['localhost'],
|
||||||
|
},
|
||||||
|
}
|
0
packages/opencommerce/src/provider.ts
Normal file
0
packages/opencommerce/src/provider.ts
Normal file
20
packages/opencommerce/taskfile.js
Normal file
20
packages/opencommerce/taskfile.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export async function build(task, opts) {
|
||||||
|
await task
|
||||||
|
.source('src/**/*.+(ts|tsx|js)')
|
||||||
|
.swc({ dev: opts.dev, outDir: 'dist', baseUrl: 'src' })
|
||||||
|
.target('dist')
|
||||||
|
.source('src/**/*.+(cjs|json)')
|
||||||
|
.target('dist')
|
||||||
|
task.$.log('Compiled src files')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function release(task) {
|
||||||
|
await task.clear('dist').start('build')
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function dev(task) {
|
||||||
|
const opts = { dev: true }
|
||||||
|
await task.clear('dist')
|
||||||
|
await task.start('build', opts)
|
||||||
|
await task.watch('src/**/*.+(ts|tsx|js|cjs|json)', 'build', opts)
|
||||||
|
}
|
21
packages/opencommerce/tsconfig.json
Normal file
21
packages/opencommerce/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
"outDir": "dist",
|
||||||
|
"baseUrl": "src",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"declaration": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"incremental": true,
|
||||||
|
"jsx": "react-jsx"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user