diff --git a/packages/next/src/rsc/data/handleFetchError.ts b/packages/next/src/rsc/data/handleFetchError.ts index 4299b5e9a..668d2d32a 100644 --- a/packages/next/src/rsc/data/handleFetchError.ts +++ b/packages/next/src/rsc/data/handleFetchError.ts @@ -1,8 +1,8 @@ -import { LOGTYPE, fetchRedirect, getHeadstartWPConfig, log } from '@headstartwp/core'; +import { HeadlessConfig, LOGTYPE, fetchRedirect, log } from '@headstartwp/core'; import { notFound, permanentRedirect, redirect } from 'next/navigation'; -export async function handleFetchError(error: Error, path = '') { - const { redirectStrategy, sourceUrl, debug } = getHeadstartWPConfig(); +export async function handleFetchError(error: Error, config: HeadlessConfig, path = '') { + const { redirectStrategy, sourceUrl, debug } = config; if (debug?.devMode) { log(LOGTYPE.INFO, '[handleError] error', error.name, error.message); diff --git a/packages/next/src/rsc/data/queries/__tests__/prepareQuery.ts b/packages/next/src/rsc/data/queries/__tests__/prepareQuery.ts new file mode 100644 index 000000000..cbebfce97 --- /dev/null +++ b/packages/next/src/rsc/data/queries/__tests__/prepareQuery.ts @@ -0,0 +1,84 @@ +import { setHeadstartWPConfig } from '@headstartwp/core'; +import { prepareQuery } from '../prepareQuery'; + +describe('prepareQuery', () => { + beforeAll(() => { + setHeadstartWPConfig({ + sites: [ + { + sourceUrl: 'https://backend1.com', + hostUrl: 'https://site1.com', + }, + { + sourceUrl: 'https://backend2.com', + hostUrl: 'https://site2.com', + }, + ], + }); + }); + + it('converts path to string', () => { + expect( + prepareQuery({ routeParams: { path: ['2020', '05', '07', 'post-name'] } }), + ).toMatchObject({ + path: '/2020/05/07/post-name', + }); + + expect(prepareQuery({ routeParams: { path: '/2020/05/07/post-name' } })).toMatchObject({ + path: '/2020/05/07/post-name', + }); + }); + + it('default headers to no-store', () => { + expect(prepareQuery({})).toMatchObject({ + options: { + headers: { + cache: 'no-store', + }, + }, + }); + }); + + it('gets site config based on site param', () => { + expect( + prepareQuery({ + routeParams: { site: 'site1.com' }, + }), + ).toMatchObject({ + config: { + sourceUrl: 'https://backend1.com', + hostUrl: 'https://site1.com', + }, + }); + + expect( + prepareQuery({ + routeParams: { site: 'site2.com' }, + }), + ).toMatchObject({ + config: { + sourceUrl: 'https://backend2.com', + hostUrl: 'https://site2.com', + }, + }); + + expect( + prepareQuery({ + routeParams: { site: 'site2.com', path: ['post-name'] }, + }), + ).toMatchObject({ + path: '/post-name', + config: { + sourceUrl: 'https://backend2.com', + hostUrl: 'https://site2.com', + }, + }); + + // this one should throw + expect(() => + prepareQuery({ + routeParams: { site: 'site3.com', path: ['post-name'] }, + }), + ).toThrow('Sub site not found, make sure to add site3.com to headstartwp.config.js'); + }); +}); diff --git a/packages/next/src/rsc/data/queries/__tests__/queryPost.ts b/packages/next/src/rsc/data/queries/__tests__/queryPost.ts new file mode 100644 index 000000000..a19efd4d4 --- /dev/null +++ b/packages/next/src/rsc/data/queries/__tests__/queryPost.ts @@ -0,0 +1,16 @@ +import { queryPost } from '../queryPost'; + +describe('queryPosts', () => { + it('fetches posts', async () => { + const { data } = await queryPost({ + routeParams: { + path: ['2020', '05', '07', 'modi-qui-dignissimos-sed-assumenda-sint-iusto'], + }, + params: { + matchCurrentPath: false, + }, + }); + + expect(data.post.slug).toBe('modi-qui-dignissimos-sed-assumenda-sint-iusto'); + }); +}); diff --git a/packages/next/src/rsc/data/queries/__tests__/queryPosts.ts b/packages/next/src/rsc/data/queries/__tests__/queryPosts.ts new file mode 100644 index 000000000..44c70f18c --- /dev/null +++ b/packages/next/src/rsc/data/queries/__tests__/queryPosts.ts @@ -0,0 +1,13 @@ +import { queryPosts } from '../queryPosts'; + +describe('queryPosts', () => { + it('fetches posts', async () => { + const { data } = await queryPosts({ + params: { + per_page: 2, + }, + }); + + expect(data.posts).toHaveLength(2); + }); +}); diff --git a/packages/next/src/rsc/data/queries/prepareQuery.ts b/packages/next/src/rsc/data/queries/prepareQuery.ts index 033cac73f..79d067977 100644 --- a/packages/next/src/rsc/data/queries/prepareQuery.ts +++ b/packages/next/src/rsc/data/queries/prepareQuery.ts @@ -1,8 +1,16 @@ -import { HeadlessConfig, getSiteByHost } from '@headstartwp/core'; +import { + FrameworkError, + HeadlessConfig, + getHeadstartWPConfig, + getSiteByHost, +} from '@headstartwp/core'; +import deepmerge from 'deepmerge'; import { convertToPath } from '../../../data/convertToPath'; import type { NextQueryProps } from './types'; +const { all: merge } = deepmerge; + export function prepareQuery

( query: NextQueryProps

, _config: HeadlessConfig | undefined = undefined, @@ -13,17 +21,27 @@ export function prepareQuery

( const siteConfig = routeParams?.site ? getSiteByHost(routeParams?.site) : null; if (routeParams?.site && !siteConfig) { - // improve this - throw new Error('Sub site not found'); + throw new FrameworkError( + `Sub site not found, make sure to add ${routeParams?.site} to headstartwp.config.js`, + ); } - const config = siteConfig ?? _config; + const options = merge['options']>([ + { + headers: { + cache: 'no-store', + }, + }, + rest.options ?? {}, + ]); + const config = siteConfig ?? _config; const pathname = Array.isArray(path) ? convertToPath(path) : path; return { ...rest, + options, path: pathname, - config, + config: config ?? getHeadstartWPConfig(), }; } diff --git a/packages/next/src/rsc/data/queries/queryAppSettings.ts b/packages/next/src/rsc/data/queries/queryAppSettings.ts index 301498512..dd479da4e 100644 --- a/packages/next/src/rsc/data/queries/queryAppSettings.ts +++ b/packages/next/src/rsc/data/queries/queryAppSettings.ts @@ -9,15 +9,13 @@ export async function queryAppSettings< >(q: NextQueryProps

, _config: HeadlessConfig | undefined = undefined) { const { config, ...query } = prepareQuery

(q, _config); - // TODO: do we need to handle errors? - try { const result = await fetchAppSettings(query, config); return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; } diff --git a/packages/next/src/rsc/data/queries/queryAuthorArchive.ts b/packages/next/src/rsc/data/queries/queryAuthorArchive.ts index 16cf9680f..d41b18d2c 100644 --- a/packages/next/src/rsc/data/queries/queryAuthorArchive.ts +++ b/packages/next/src/rsc/data/queries/queryAuthorArchive.ts @@ -20,7 +20,7 @@ export async function queryAuthorArchive< return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; } diff --git a/packages/next/src/rsc/data/queries/queryPost.ts b/packages/next/src/rsc/data/queries/queryPost.ts index 7344656fc..ec1994deb 100644 --- a/packages/next/src/rsc/data/queries/queryPost.ts +++ b/packages/next/src/rsc/data/queries/queryPost.ts @@ -15,7 +15,7 @@ export async function queryPost< return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; } diff --git a/packages/next/src/rsc/data/queries/queryPostOrPosts.ts b/packages/next/src/rsc/data/queries/queryPostOrPosts.ts index 50b60ff36..b3c553dbc 100644 --- a/packages/next/src/rsc/data/queries/queryPostOrPosts.ts +++ b/packages/next/src/rsc/data/queries/queryPostOrPosts.ts @@ -15,7 +15,7 @@ export async function queryPostOrPosts< return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; } diff --git a/packages/next/src/rsc/data/queries/queryPosts.ts b/packages/next/src/rsc/data/queries/queryPosts.ts index c745e9e32..330c33a4c 100644 --- a/packages/next/src/rsc/data/queries/queryPosts.ts +++ b/packages/next/src/rsc/data/queries/queryPosts.ts @@ -15,7 +15,7 @@ export async function queryPosts< return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; } diff --git a/packages/next/src/rsc/data/queries/querySearch.ts b/packages/next/src/rsc/data/queries/querySearch.ts index 15088628d..cc1b55604 100644 --- a/packages/next/src/rsc/data/queries/querySearch.ts +++ b/packages/next/src/rsc/data/queries/querySearch.ts @@ -21,7 +21,7 @@ export async function querySearch< return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; } diff --git a/packages/next/src/rsc/data/queries/queryTerms.ts b/packages/next/src/rsc/data/queries/queryTerms.ts index f417b57fd..de7781266 100644 --- a/packages/next/src/rsc/data/queries/queryTerms.ts +++ b/packages/next/src/rsc/data/queries/queryTerms.ts @@ -9,14 +9,13 @@ export async function queryTerms< >(q: NextQueryProps

, _config: HeadlessConfig | undefined = undefined) { const { config, ...query } = prepareQuery

(q, _config); - // TODO does this one need to fetch handle errors? try { const result = await fetchTerms(query, config); return result; } catch (error) { if (error instanceof Error) { - handleFetchError(error, query.path); + handleFetchError(error, config, query.path); } throw error; }