diff --git a/framework/spree/api/utils/create-api-fetch.ts b/framework/spree/api/utils/create-api-fetch.ts index 68652aca2..e6c1f30e8 100644 --- a/framework/spree/api/utils/create-api-fetch.ts +++ b/framework/spree/api/utils/create-api-fetch.ts @@ -22,8 +22,9 @@ const createApiFetch: ( return async (url, queryData = {}, fetchOptions = {}) => { console.log( 'apiFetch called. query = ', - url, 'url = ', + url, + 'queryData = ', queryData, 'fetchOptions = ', fetchOptions diff --git a/framework/spree/fetcher.ts b/framework/spree/fetcher.ts index 48834cf32..882a6c2bf 100644 --- a/framework/spree/fetcher.ts +++ b/framework/spree/fetcher.ts @@ -9,12 +9,15 @@ import type { import { errors } from '@spree/storefront-api-v2-sdk' import { requireConfigValue } from './isomorphicConfig' import getSpreeSdkMethodFromEndpointPath from './utils/getSpreeSdkMethodFromEndpointPath' -// import { handleFetchResponse } from './utils' +import SpreeSdkMethodFromEndpointPathError from './errors/SpreeSdkMethodFromEndpointPathError' +import type { SpreeSdkVariables } from './types' +import { GraphQLFetcherResult } from '@commerce/api' const client = makeClient({ host: requireConfigValue('spreeApiHost') }) -const fetcher: Fetcher = async (requestOptions) => { - console.log('Fetcher called') +const fetcher: Fetcher, SpreeSdkVariables> = async ( + requestOptions +) => { // url?: string // query?: string // method?: string @@ -23,24 +26,36 @@ const fetcher: Fetcher = async (requestOptions) => { const { url, method, variables, query } = requestOptions const { locale, ...vars } = variables ?? {} - if (!url) { - // TODO: Create a custom type for this error. - throw new Error('Url not provider for fetcher.') - } - console.log( - `Fetching products using options: ${JSON.stringify(requestOptions)}.` + 'Fetcher called. Configuration: ', + 'url = ', + url, + 'requestOptions = ', + requestOptions ) - // TODO: Not best to use url for finding the method, but should be good enough for now. + if (!variables) { + throw new SpreeSdkMethodFromEndpointPathError( + `Required SpreeSdkVariables not provided.` + ) + } const storeResponse: ResultResponse = - await getSpreeSdkMethodFromEndpointPath(client, url)(...variables.args) // TODO: Not the best to use variables here as it's type is any. + await getSpreeSdkMethodFromEndpointPath( + client, + variables.methodPath + )(...variables.arguments) if (storeResponse.success()) { - return storeResponse.success() + return { + data: storeResponse.success(), + res: storeResponse as any, //FIXME: MUST BE fetch() RESPONSE instead of axios. + } } + // FIXME: Allow Spree SDK to use fetch instead of axios + // (https://github.com/spree/spree-storefront-api-v2-js-sdk/issues/189) + const storeResponseError = storeResponse.fail() if (storeResponseError instanceof errors.SpreeError) { @@ -50,8 +65,6 @@ const fetcher: Fetcher = async (requestOptions) => { throw storeResponseError } -// import { Fetcher } from '@commerce/utils/types' - // export const fetcher: Fetcher = async () => { // console.log('FETCHER') // const res = await fetch('./data.json') diff --git a/framework/spree/product/use-search.tsx b/framework/spree/product/use-search.tsx index 85bb68a77..f9d49df97 100644 --- a/framework/spree/product/use-search.tsx +++ b/framework/spree/product/use-search.tsx @@ -1,39 +1,72 @@ -import type { SWRHook, Fetcher } from '@commerce/utils/types' +import type { Fetcher, SWRHook } from '@commerce/utils/types' import useSearch from '@commerce/product/use-search' +import type { Product, SearchProductsHook } from '@commerce/types/product' import type { UseSearch } from '@commerce/product/use-search' +import normalizeProduct from '../utils/normalizeProduct' +import type { GraphQLFetcherResult } from '@commerce/api' +import { IProducts } from '@spree/storefront-api-v2-sdk/types/interfaces/Product' -export const handler: SWRHook = { +export const handler: SWRHook = { fetchOptions: { - url: 'client.products.list', // Add custom option for method name later + url: '__UNUSED__', query: '', }, async fetcher({ input, options, fetch }) { // This method is only needed if the options need to be modified before calling the generic fetcher (created in createFetcher). // TODO: Actually filter by input and query. - console.log( - `Calling useSearch fetcher with input: ${JSON.stringify( - input - )} and options: ${JSON.stringify(options)}.` + console.info( + 'useSearch fetcher called. Configuration: ', + 'input: ', + input, + 'options: ', + options ) - // FIXME: IMPLEMENT + const categoryOrBrandId = input.categoryId || input.brandId - return fetch({ - url: options.url, - variables: { args: [] }, // TODO: Actually provide args later. + const filter = categoryOrBrandId + ? { + filter: { + taxons: categoryOrBrandId, + }, + } + : {} + + const { data: spreeSuccessResponse } = await fetch< + GraphQLFetcherResult + >({ + variables: { + methodPath: 'products.list', + arguments: [ + { + include: 'variants,images,option_types,variants.option_values', + per_page: 50, + ...filter, + }, + ], + }, }) + + const normalizedProducts: Product[] = spreeSuccessResponse.data.map( + (spreeProduct) => normalizeProduct(spreeSuccessResponse, spreeProduct) + ) + + const found = spreeSuccessResponse.data.length > 0 + + return { products: normalizedProducts, found } }, // useHook is used for both, SWR and mutation requests to the store. // useHook is called in React components. For example, after clicking `Add to cart`. useHook: ({ useData }) => (input = {}) => { - console.log('useHook called') - // useData calls the fetcher method (above). // The difference between useHook and calling fetcher directly is // useHook accepts swrOptions. + + console.log('useSearch useHook called.') + return useData({ input: [ ['search', input.search],