mirror of
https://github.com/vercel/commerce.git
synced 2025-07-23 04:36:49 +00:00
Dynamic API routes (#836)
* Add dynamic API endpoints * Add missing dependency * Update api handlers * Updates * Fix build errors * Update package.json * Add checkout endpoint parser & update errors * Update tsconfig.json * Update cart.ts * Update parser * Update errors.ts * Update errors.ts * Move to Edge runtime * Revert to local * Fix switchable runtimes * Make nodejs default runtime * Update pnpm-lock.yaml * Update handlers * Fix build errors * Change headers
This commit is contained in:
@@ -50,10 +50,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/commerce": "workspace:*",
|
||||
"@vercel/fetch": "^6.2.0",
|
||||
"js-cookie": "^3.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"node-fetch": "^2.6.7"
|
||||
"lodash.debounce": "^4.0.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^12",
|
||||
|
@@ -1 +0,0 @@
|
||||
export default function (_commerce: any) {}
|
@@ -1 +0,0 @@
|
||||
export default function (_commerce: any) {}
|
@@ -6,9 +6,11 @@ export type CheckoutAPI = GetAPISchema<CommerceAPI, CheckoutSchema>
|
||||
|
||||
export type CheckoutEndpoint = CheckoutAPI['endpoint']
|
||||
|
||||
const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({ req, res, config }) => {
|
||||
try {
|
||||
const html = `
|
||||
const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
||||
req,
|
||||
config,
|
||||
}) => {
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -30,16 +32,11 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({ req, r
|
||||
</html>
|
||||
`
|
||||
|
||||
res.status(200)
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
res.write(html)
|
||||
res.end()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
const message = 'An unexpected error ocurred'
|
||||
|
||||
res.status(500).json({ data: null, errors: [{ message }] })
|
||||
return {
|
||||
html,
|
||||
headers: {
|
||||
'Content-Type': 'text/html',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1 +0,0 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
@@ -1 +0,0 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
@@ -1 +0,0 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
12
packages/saleor/src/api/endpoints/index.ts
Normal file
12
packages/saleor/src/api/endpoints/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { Provider, SaleorAPI } from '..'
|
||||
|
||||
import createEndpoints from '@vercel/commerce/api/endpoints'
|
||||
import checkout from './checkout'
|
||||
|
||||
const endpoints = {
|
||||
checkout,
|
||||
}
|
||||
|
||||
export default function saleorAPI(commerce: SaleorAPI) {
|
||||
return createEndpoints<Provider>(commerce, endpoints)
|
||||
}
|
@@ -1 +0,0 @@
|
||||
export default function (_commerce: any) {}
|
@@ -1 +0,0 @@
|
||||
export default function (_commerce: any) {}
|
@@ -1 +0,0 @@
|
||||
export default function (_commerce: any) {}
|
@@ -1 +0,0 @@
|
||||
export default function (_commerce: any) {}
|
@@ -30,9 +30,7 @@ export default function getAllPagesOperation({
|
||||
{ variables },
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
'Accept-Language': locale,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
@@ -39,9 +39,7 @@ export default function getAllProductsOperation({
|
||||
{ variables },
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
'Accept-Language': locale,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
@@ -28,9 +28,7 @@ export default function getPageOperation({
|
||||
{ variables },
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
'Accept-Language': locale,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
@@ -32,9 +32,7 @@ export default function getProductOperation({
|
||||
{ variables },
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
'Accept-Language': locale,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
@@ -1,11 +1,12 @@
|
||||
import type { ServerResponse } from 'http'
|
||||
import type { OperationContext } from '@vercel/commerce/api/operations'
|
||||
import type { Provider, SaleorConfig } from '..'
|
||||
import { throwUserErrors } from '../../utils'
|
||||
|
||||
import * as Mutation from '../../utils/mutations'
|
||||
|
||||
export default function loginOperation({ commerce }: OperationContext<Provider>) {
|
||||
export default function loginOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function login({
|
||||
query = Mutation.SessionCreate,
|
||||
variables,
|
||||
@@ -13,7 +14,7 @@ export default function loginOperation({ commerce }: OperationContext<Provider>)
|
||||
}: {
|
||||
query?: string
|
||||
variables: any
|
||||
res: ServerResponse
|
||||
res: Response
|
||||
config?: SaleorConfig
|
||||
}): Promise<any> {
|
||||
config = commerce.getConfig(config)
|
||||
|
@@ -1,23 +1,25 @@
|
||||
import type { GraphQLFetcher } from '@vercel/commerce/api'
|
||||
import fetch from './fetch'
|
||||
|
||||
import { API_URL } from '../../const'
|
||||
import { getError } from '../../utils/handle-fetch-response'
|
||||
import { getCommerceApi } from '..'
|
||||
import { getToken } from '../../utils/index'
|
||||
|
||||
const fetchGraphqlApi: GraphQLFetcher = async (query: string, { variables } = {}, fetchOptions) => {
|
||||
const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
query: string,
|
||||
{ variables } = {},
|
||||
headers?: HeadersInit
|
||||
) => {
|
||||
const config = getCommerceApi().getConfig()
|
||||
const token = getToken()
|
||||
|
||||
const res = await fetch(API_URL!, {
|
||||
...fetchOptions,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(token && {
|
||||
Authorization: `Bearer ${token}`,
|
||||
}),
|
||||
...fetchOptions?.headers,
|
||||
...headers,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
@@ -1,22 +0,0 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default function isAllowedMethod(req: NextApiRequest, res: NextApiResponse, allowedMethods: string[]) {
|
||||
const methods = allowedMethods.includes('OPTIONS') ? allowedMethods : [...allowedMethods, 'OPTIONS']
|
||||
|
||||
if (!req.method || !methods.includes(req.method)) {
|
||||
res.status(405)
|
||||
res.setHeader('Allow', methods.join(', '))
|
||||
res.end()
|
||||
return false
|
||||
}
|
||||
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.status(200)
|
||||
res.setHeader('Allow', methods.join(', '))
|
||||
res.setHeader('Content-Length', '0')
|
||||
res.end()
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
@@ -2,7 +2,12 @@ import { Fetcher } from '@vercel/commerce/utils/types'
|
||||
import { API_URL } from './const'
|
||||
import { getToken, handleFetchResponse } from './utils'
|
||||
|
||||
const fetcher: Fetcher = async ({ url = API_URL, method = 'POST', variables, query }) => {
|
||||
const fetcher: Fetcher = async ({
|
||||
url = API_URL,
|
||||
method = 'POST',
|
||||
variables,
|
||||
query,
|
||||
}) => {
|
||||
const token = getToken()
|
||||
|
||||
return handleFetchResponse(
|
||||
|
@@ -12,8 +12,8 @@ export default useSearch as UseSearch<typeof handler>
|
||||
|
||||
export type SearchProductsInput = {
|
||||
search?: string
|
||||
categoryId?: string | number
|
||||
brandId?: string | number
|
||||
categoryId?: string
|
||||
brandId?: string
|
||||
sort?: string
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,12 @@
|
||||
import { getSortVariables } from './get-sort-variables'
|
||||
import type { SearchProductsInput } from '../product/use-search'
|
||||
|
||||
export const getSearchVariables = ({ brandId, search, categoryId, sort }: SearchProductsInput) => {
|
||||
export const getSearchVariables = ({
|
||||
brandId,
|
||||
search,
|
||||
categoryId,
|
||||
sort,
|
||||
}: SearchProductsInput) => {
|
||||
const sortBy = {
|
||||
field: 'NAME',
|
||||
direction: 'ASC',
|
||||
|
Reference in New Issue
Block a user