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:
Catalin Pinte
2022-10-30 20:41:21 +02:00
committed by GitHub
parent a5b367a747
commit c75b0fc001
316 changed files with 2482 additions and 2176 deletions

View File

@@ -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",

View File

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

View File

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

View File

@@ -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',
},
}
}

View File

@@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,9 +30,7 @@ export default function getAllPagesOperation({
{ variables },
{
...(locale && {
headers: {
'Accept-Language': locale,
},
'Accept-Language': locale,
}),
}
)

View File

@@ -39,9 +39,7 @@ export default function getAllProductsOperation({
{ variables },
{
...(locale && {
headers: {
'Accept-Language': locale,
},
'Accept-Language': locale,
}),
}
)

View File

@@ -28,9 +28,7 @@ export default function getPageOperation({
{ variables },
{
...(locale && {
headers: {
'Accept-Language': locale,
},
'Accept-Language': locale,
}),
}
)

View File

@@ -32,9 +32,7 @@ export default function getProductOperation({
{ variables },
{
...(locale && {
headers: {
'Accept-Language': locale,
},
'Accept-Language': locale,
}),
}
)

View File

@@ -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)

View File

@@ -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({

View File

@@ -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
}

View File

@@ -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(

View File

@@ -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
}

View File

@@ -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',