diff --git a/.changeset/eighty-cheetahs-wonder.md b/.changeset/eighty-cheetahs-wonder.md new file mode 100644 index 000000000..446963a93 --- /dev/null +++ b/.changeset/eighty-cheetahs-wonder.md @@ -0,0 +1,5 @@ +--- +"@headstartwp/core": patch +--- + +Adding support for basic auth diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..2c41a4163 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,20 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "@headstartwp/core": "1.1.1", + "@10up/react-hooks": "1.2.3", + "@headstartwp/next": "1.1.3", + "@10up/next-redis-cache-provider": "0.1.5", + "@10up/headless-docs": "1.0.0", + "@10up/wp-multisite-i18n-nextjs": "0.2.0", + "@10up/wp-multisite-nextjs": "0.2.0", + "@10up/wp-nextjs": "0.2.0", + "@10up/wp-nextjs-ts": "0.2.1-next.2", + "@headstartwp/headstartwp": "1.0.9" + }, + "changesets": [ + "eighty-cheetahs-wonder", + "wild-pandas-tickle" + ] +} diff --git a/.changeset/wild-pandas-tickle.md b/.changeset/wild-pandas-tickle.md new file mode 100644 index 000000000..6ea8e1a01 --- /dev/null +++ b/.changeset/wild-pandas-tickle.md @@ -0,0 +1,5 @@ +--- +"@headstartwp/core": patch +--- + +Fix: fetchHookData with usePosts and throwIfNotFound set to false will crash the application if no results are found diff --git a/docs/documentation/01-Getting Started/headless-config.md b/docs/documentation/01-Getting Started/headless-config.md index 14bb9127c..a24a34e9b 100644 --- a/docs/documentation/01-Getting Started/headless-config.md +++ b/docs/documentation/01-Getting Started/headless-config.md @@ -99,7 +99,7 @@ After adding a custom taxonomy to the config, you will be able to filter posts b ```js usePost({ postType: ['book'], genre: 'action' }); -usePosts({ postType:'book', genre: 'action' perPage: 10 }); +usePosts({ postType:'book', genre: 'action', perPage: 10 }); useTerms({ taxonomy: 'genre' }); ``` diff --git a/docs/documentation/06-WordPress Integration/basic-auth.md b/docs/documentation/06-WordPress Integration/basic-auth.md new file mode 100644 index 000000000..cc9f6d63e --- /dev/null +++ b/docs/documentation/06-WordPress Integration/basic-auth.md @@ -0,0 +1,19 @@ +--- +slug: /wordpress-integration/basic-auth +--- + +# Basic Auth + +If WordPress is protected by Basic Auth (which is common during development) you can tell HeadstartWP the basic auth creds so that all +REST API requests include them. To do so, simply add the following env variables: + +``` +WP_BASIC_AUTH_USERNAME=username +WP_BASIC_AUTH_PASSWORD=password +``` + +:::caution +The above env variables will only be accessible server-side and therefore any client-side requests made directly to WordPress will fail. This happens because Next.js only includes env variables prefixed with `NEXT_PUBLIC_` in the browser bundle. + +If you want your client-side requests to work, prefix the above variables with `NEXT_PUBLIC_`. But note that the basic auth creds will be leaked to the public. +:::caution diff --git a/docs/static/img/documentation/getting-started/plugin-settings.png b/docs/static/img/documentation/getting-started/plugin-settings.png index 107eb3c87..6ef122389 100644 Binary files a/docs/static/img/documentation/getting-started/plugin-settings.png and b/docs/static/img/documentation/getting-started/plugin-settings.png differ diff --git a/package-lock.json b/package-lock.json index 300851db5..f0eb395e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,8 +31,8 @@ "turbo": "^1.9.3" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=18.0.0", + "npm": ">=9.0.0" } }, "node_modules/@10up/babel-preset-default": { @@ -4237,6 +4237,66 @@ "version": "13.4.4", "license": "MIT" }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", + "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", + "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", + "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", + "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@next/swc-linux-x64-gnu": { "version": "13.4.4", "cpu": [ @@ -4265,6 +4325,51 @@ "node": ">= 10" } }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", + "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", + "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", + "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "dev": true, @@ -21158,7 +21263,7 @@ }, "packages/core": { "name": "@headstartwp/core", - "version": "1.1.0-next.1", + "version": "1.1.1", "license": "MIT", "dependencies": { "@justinribeiro/lite-youtube": "^1.3.1", @@ -21549,10 +21654,10 @@ }, "packages/next": { "name": "@headstartwp/next", - "version": "1.1.0-next.1", + "version": "1.1.3", "license": "MIT", "dependencies": { - "@headstartwp/core": "^1.1.0-next.1", + "@headstartwp/core": "^1.1.1", "deepmerge": "^4.3.1", "loader-utils": "^3.2.0", "modify-source-webpack-plugin": "^4.1.0", @@ -21714,8 +21819,8 @@ "version": "0.2.0", "license": "GPL-2.0-or-later", "dependencies": { - "@headstartwp/core": "^1.1.0-next.1", - "@headstartwp/next": "^1.1.0-next.1", + "@headstartwp/core": "^1.1.1", + "@headstartwp/next": "^1.1.3", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -21734,8 +21839,8 @@ "eslint-plugin-import": "^2.26.0" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=18.0.0", + "npm": ">=9.0.0" } }, "projects/wp-multisite-nextjs": { @@ -21743,8 +21848,8 @@ "version": "0.2.0", "license": "GPL-2.0-or-later", "dependencies": { - "@headstartwp/core": "^1.1.0-next.1", - "@headstartwp/next": "^1.1.0-next.1", + "@headstartwp/core": "^1.1.1", + "@headstartwp/next": "^1.1.3", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -21763,8 +21868,8 @@ "eslint-plugin-import": "^2.26.0" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=18.0.0", + "npm": ">=9.0.0" } }, "projects/wp-nextjs": { @@ -21773,8 +21878,8 @@ "license": "GPL-2.0-or-later", "dependencies": { "@10up/next-redis-cache-provider": "^0.1.5", - "@headstartwp/core": "^1.1.0-next.1", - "@headstartwp/next": "^1.1.0-next.1", + "@headstartwp/core": "^1.1.1", + "@headstartwp/next": "^1.1.3", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -21793,8 +21898,8 @@ "eslint-plugin-import": "^2.26.0" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=18.0.0", + "npm": ">=9.0.0" } }, "projects/wp-nextjs-ts": { @@ -21802,8 +21907,8 @@ "version": "0.2.1-next.2", "license": "GPL-2.0-or-later", "dependencies": { - "@headstartwp/core": "^1.1.0-next.1", - "@headstartwp/next": "^1.1.0-next.1", + "@headstartwp/core": "^1.1.1", + "@headstartwp/next": "^1.1.3", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", @@ -21822,13 +21927,13 @@ "eslint-plugin-import": "^2.26.0" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=18.0.0", + "npm": ">=9.0.0" } }, "wp/headless-wp": { "name": "@headstartwp/headstartwp", - "version": "1.0.9-next.0", + "version": "1.0.9", "license": "GPL-2.0-or-later", "devDependencies": { "@wordpress/env": "^5.14.0" @@ -21836,111 +21941,6 @@ "engines": { "node": ">=16.0.0" } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", - "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", - "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", - "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", - "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", - "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", - "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", - "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } } } } diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index f53452637..5ffcc37e7 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,17 @@ # @headstartwp/core +## 1.1.2-next.1 + +### Patch Changes + +- 772c5f1c: Fix: fetchHookData with usePosts and throwIfNotFound set to false will crash the application if no results are found + +## 1.1.2-next.0 + +### Patch Changes + +- 15189a03: Adding support for basic auth + ## 1.1.1 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index ce3bb1bbc..321efa655 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@headstartwp/core", - "version": "1.1.1", + "version": "1.1.2-next.1", "description": "`@headstartwp/core` is the core package that houses framework-agnostic components and utilities for building headless sites with WordPress.", "homepage": "https://github.com/10up/headstartwp/blob/develop/packages/core/README.md", "license": "MIT", diff --git a/packages/core/src/data/api/fetch-utils.ts b/packages/core/src/data/api/fetch-utils.ts index b249b49d8..141d2b08e 100644 --- a/packages/core/src/data/api/fetch-utils.ts +++ b/packages/core/src/data/api/fetch-utils.ts @@ -48,12 +48,6 @@ export const apiGet = async ( args: { [index: string]: any } = {}, burstCache = false, ) => { - const headers = getAuthHeader(); - - if (headers) { - args.headers = headers; - } - const queryArgs = burstCache ? { cacheTime: new Date().getTime(), diff --git a/packages/core/src/data/strategies/AbstractFetchStrategy.ts b/packages/core/src/data/strategies/AbstractFetchStrategy.ts index 6d3136fc3..22711bb39 100644 --- a/packages/core/src/data/strategies/AbstractFetchStrategy.ts +++ b/packages/core/src/data/strategies/AbstractFetchStrategy.ts @@ -224,6 +224,27 @@ export abstract class AbstractFetchStrategy = {}) { + let bearerAuthHeader = ''; + if (options.bearerToken) { + bearerAuthHeader = `Bearer ${options.bearerToken}`; + } + + const basicAuthUsername = + process.env.WP_BASIC_AUTH_USERNAME ?? process.env.NEXT_PUBLIC_WP_BASIC_AUTH_USERNAME; + const basicAuthPassword = + process.env.WP_BASIC_AUTH_PASSWORD ?? process.env.NEXT_PUBLIC_WP_BASIC_AUTH_PASSWORD; + + if (basicAuthUsername && basicAuthPassword) { + const basicAuth = `Basic ${btoa(`${basicAuthUsername}:${basicAuthPassword}`)}`; + if (bearerAuthHeader) { + return `${basicAuth}, ${bearerAuthHeader}`; + } + return basicAuth; + } + return bearerAuthHeader; + } + /** * The default fetcher function * @@ -245,9 +266,13 @@ export abstract class AbstractFetchStrategy = { - result: result.json, + result: resultData, pageInfo: { totalPages: Number(result.headers['x-wp-totalpages']) || 0, totalItems: Number(result.headers['x-wp-total']) || 0, diff --git a/packages/core/src/data/strategies/SinglePostFetchStrategy.ts b/packages/core/src/data/strategies/SinglePostFetchStrategy.ts index bff3ca99f..fe36bf9d4 100644 --- a/packages/core/src/data/strategies/SinglePostFetchStrategy.ts +++ b/packages/core/src/data/strategies/SinglePostFetchStrategy.ts @@ -279,6 +279,8 @@ export class SinglePostFetchStrategy< options.bearerToken = params.authToken; } + const authHeader = this.getAuthHeader(options); + let error; if (params.revision && params.id) { try { @@ -286,7 +288,7 @@ export class SinglePostFetchStrategy< `${this.baseURL}${this.getEndpoint()}/revisions?per_page=1`, { headers: { - Authorization: `Bearer ${options.bearerToken}`, + Authorization: authHeader, }, }, burstCache, diff --git a/packages/core/src/data/strategies/__tests__/PostOrPostsFetchStrategy.ts b/packages/core/src/data/strategies/__tests__/PostOrPostsFetchStrategy.ts index b7e2fb993..9d12a92a3 100644 --- a/packages/core/src/data/strategies/__tests__/PostOrPostsFetchStrategy.ts +++ b/packages/core/src/data/strategies/__tests__/PostOrPostsFetchStrategy.ts @@ -243,7 +243,7 @@ describe('PostOrPostsFetchStrategy', () => { useWordPressPlugin: true, }); - const params = fetchStrategy.getParamsFromURL('/page/2'); + const params = fetchStrategy.getParamsFromURL('/page/1'); const response = await fetchStrategy.fetcher( '', merge(params, { priority: 'single', routeMatchStrategy: 'archive' }), @@ -257,7 +257,7 @@ describe('PostOrPostsFetchStrategy', () => { useWordPressPlugin: true, }); - let params = fetchStrategy.getParamsFromURL('/page/2'); + let params = fetchStrategy.getParamsFromURL('/page/1'); let response = await fetchStrategy.fetcher( '', merge(params, { priority: 'single', routeMatchStrategy: 'single' }), @@ -265,7 +265,7 @@ describe('PostOrPostsFetchStrategy', () => { expect(response.result.isSingle).toBeFalsy(); expect(response.result.isArchive).toBeTruthy(); - params = fetchStrategy.getParamsFromURL('/page/2'); + params = fetchStrategy.getParamsFromURL('/page/1'); response = await fetchStrategy.fetcher( '', merge(params, { priority: 'archive', routeMatchStrategy: 'single' }), diff --git a/packages/core/src/data/strategies/__tests__/SinglePostFetchStrategy.ts b/packages/core/src/data/strategies/__tests__/SinglePostFetchStrategy.ts index 76173a0a8..9c7a59c59 100644 --- a/packages/core/src/data/strategies/__tests__/SinglePostFetchStrategy.ts +++ b/packages/core/src/data/strategies/__tests__/SinglePostFetchStrategy.ts @@ -681,4 +681,66 @@ describe('SinglePostFetchStrategy', () => { result: {}, }); }); + + it('handles basic auth', async () => { + const samplePost = { title: 'test', id: 1, link: '/2021/10/post-name' }; + const sampleHeaders = { + 'x-wp-totalpages': 1, + 'x-wp-total': 1, + }; + + apiGetMock.mockResolvedValue({ + headers: sampleHeaders, + json: [samplePost], + }); + + process.env.WP_BASIC_AUTH_PASSWORD = 'test'; + process.env.WP_BASIC_AUTH_USERNAME = 'admin'; + + const params = fetchStrategy.getParamsFromURL('/2021/10/post-name'); + await fetchStrategy.fetcher(fetchStrategy.buildEndpointURL(params), params); + + expect(apiGetMock).toHaveBeenNthCalledWith( + 1, + '/wp-json/wp/v2/posts?slug=post-name', + { + headers: { + Authorization: 'Basic YWRtaW46dGVzdA==', + }, + }, + false, + ); + }); + + it('handles basic auth and bearer token', async () => { + const samplePost = { title: 'test', id: 1, link: '/2021/10/post-name' }; + const sampleHeaders = { + 'x-wp-totalpages': 1, + 'x-wp-total': 1, + }; + + apiGetMock.mockResolvedValue({ + headers: sampleHeaders, + json: [samplePost], + }); + + process.env.WP_BASIC_AUTH_PASSWORD = 'test'; + process.env.WP_BASIC_AUTH_USERNAME = 'admin'; + + const params = fetchStrategy.getParamsFromURL('/2021/10/post-name'); + await fetchStrategy.fetcher(fetchStrategy.buildEndpointURL(params), params, { + bearerToken: 'bearer token', + }); + + expect(apiGetMock).toHaveBeenNthCalledWith( + 1, + '/wp-json/wp/v2/posts?slug=post-name', + { + headers: { + Authorization: 'Basic YWRtaW46dGVzdA==, Bearer bearer token', + }, + }, + false, + ); + }); }); diff --git a/packages/core/src/react/hooks/__tests__/useFetchPosts.tsx b/packages/core/src/react/hooks/__tests__/useFetchPosts.tsx index b29da7aab..6a92b4768 100644 --- a/packages/core/src/react/hooks/__tests__/useFetchPosts.tsx +++ b/packages/core/src/react/hooks/__tests__/useFetchPosts.tsx @@ -189,6 +189,52 @@ describe('useFetchPosts', () => { }); }); + it('does not crash when not found but throwIfNotFound is set to false', async () => { + const { result } = renderHook( + () => + useFetchPosts( + { taxonomy: 'category' }, + { + fetchStrategyOptions: { + throwIfNotFound: false, + }, + }, + '/i-do-not-exist', + ), + { + wrapper, + }, + ); + + await waitFor(() => { + expect(result.current.error).toBeFalsy(); + expect(result.current.data?.posts.length).toBe(0); + }); + }); + + it('does not crash when invalid page param when throwIfNotFound is set to false', async () => { + const { result } = renderHook( + () => + useFetchPosts( + { taxonomy: 'category' }, + { + fetchStrategyOptions: { + throwIfNotFound: false, + }, + }, + '/news/page/10', + ), + { + wrapper, + }, + ); + + await waitFor(() => { + expect(result.current.error).toBeFalsy(); + expect(result.current.data?.posts.length).toBe(0); + }); + }); + describe('useFetchPosts types', () => { it('allows overriding types', () => { interface Book extends PostEntity { diff --git a/packages/core/test/server-handlers.ts b/packages/core/test/server-handlers.ts index 52c6d047e..24babafcb 100644 --- a/packages/core/test/server-handlers.ts +++ b/packages/core/test/server-handlers.ts @@ -47,6 +47,7 @@ const handlers = [ const search = query.get('search'); const slug = query.get('slug'); const perPage = Number(query.get('per_page') || 10); + const page = Number(query.get('page') || 1); const category = query.get('categories'); const author = query.get('author'); const embed = query.get('_embed'); @@ -107,8 +108,21 @@ const handlers = [ const totalResults = results.length; + if ((page - 1) * perPage > totalResults) { + return res( + ctx.json({ + code: 'rest_post_invalid_page_number', + message: + 'The page number requested is larger than the number of pages available.', + data: { + status: 400, + }, + }), + ); + } + if (perPage) { - results = results.slice(0, perPage); + results = results.slice((page - 1) * perPage, perPage); } return res( diff --git a/packages/next/CHANGELOG.md b/packages/next/CHANGELOG.md index 9f7f5c452..cb8454edb 100644 --- a/packages/next/CHANGELOG.md +++ b/packages/next/CHANGELOG.md @@ -1,5 +1,12 @@ # @headstartwp/next +## 1.1.4-next.0 + +### Patch Changes + +- Updated dependencies [15189a03] + - @headstartwp/core@1.1.2-next.0 + ## 1.1.3 ### Patch Changes diff --git a/packages/next/package.json b/packages/next/package.json index a2bd25947..3b334392a 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "@headstartwp/next", - "version": "1.1.3", + "version": "1.1.4-next.0", "description": "`@headstartwp/next` is the Next.js bindings for the headless framework.", "homepage": "https://github.com/10up/headstartwp/blob/develop/packages/next/README.md", "license": "MIT", @@ -49,7 +49,7 @@ }, "dependencies": { "deepmerge": "^4.3.1", - "@headstartwp/core": "^1.1.1", + "@headstartwp/core": "^1.1.2-next.0", "modify-source-webpack-plugin": "^4.1.0", "loader-utils": "^3.2.0", "schema-utils": "^4.0.0" diff --git a/projects/wp-multisite-i18n-nextjs/package.json b/projects/wp-multisite-i18n-nextjs/package.json index 78546a7a0..d71fdf3b4 100644 --- a/projects/wp-multisite-i18n-nextjs/package.json +++ b/projects/wp-multisite-i18n-nextjs/package.json @@ -14,8 +14,8 @@ "lint": "eslint ." }, "dependencies": { - "@headstartwp/core": "^1.1.1", - "@headstartwp/next": "^1.1.3", + "@headstartwp/core": "^1.1.2-next.1", + "@headstartwp/next": "^1.1.4-next.0", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", diff --git a/projects/wp-multisite-nextjs/package.json b/projects/wp-multisite-nextjs/package.json index c8142a3a1..e05596f71 100644 --- a/projects/wp-multisite-nextjs/package.json +++ b/projects/wp-multisite-nextjs/package.json @@ -14,8 +14,8 @@ "lint": "eslint ." }, "dependencies": { - "@headstartwp/core": "^1.1.1", - "@headstartwp/next": "^1.1.3", + "@headstartwp/core": "^1.1.2-next.1", + "@headstartwp/next": "^1.1.4-next.0", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", diff --git a/projects/wp-nextjs-ts/package.json b/projects/wp-nextjs-ts/package.json index c67f45df1..3941a522d 100644 --- a/projects/wp-nextjs-ts/package.json +++ b/projects/wp-nextjs-ts/package.json @@ -14,8 +14,8 @@ "lint": "eslint ." }, "dependencies": { - "@headstartwp/core": "^1.1.1", - "@headstartwp/next": "^1.1.3", + "@headstartwp/core": "^1.1.2-next.1", + "@headstartwp/next": "^1.1.4-next.0", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10", "@linaria/react": "^4.3.8", diff --git a/projects/wp-nextjs/package.json b/projects/wp-nextjs/package.json index ac41b2fe7..4a7caa6b9 100644 --- a/projects/wp-nextjs/package.json +++ b/projects/wp-nextjs/package.json @@ -14,8 +14,8 @@ "lint": "eslint ." }, "dependencies": { - "@headstartwp/core": "^1.1.1", - "@headstartwp/next": "^1.1.3", + "@headstartwp/core": "^1.1.2-next.1", + "@headstartwp/next": "^1.1.4-next.0", "@10up/next-redis-cache-provider": "^0.1.5", "@linaria/babel-preset": "^4.4.5", "@linaria/core": "^4.2.10",