From d67f2cfff6cbf4e5bcd977cc545d4222d6acdea2 Mon Sep 17 00:00:00 2001 From: Marco Monti Date: Tue, 9 Jul 2024 12:48:00 +0200 Subject: [PATCH 1/3] docs(next-drupal): updated docs --- www/config/docs.ts | 40 ++--- www/config/tutorials.ts | 6 +- www/content/docs/authentication.mdx | 103 ++++++----- www/content/docs/cache.mdx | 21 ++- www/content/docs/client.mdx | 12 +- www/content/docs/configuration.mdx | 75 +++++--- www/content/docs/creating-resources.mdx | 18 +- www/content/docs/deleting-resources.mdx | 14 +- www/content/docs/deserializer.mdx | 31 ++++ www/content/docs/draft-mode.mdx | 29 ++++ www/content/docs/environment-variables.mdx | 21 ++- www/content/docs/fetcher.mdx | 23 ++- www/content/docs/fetching-resources.mdx | 34 +--- www/content/docs/index.mdx | 14 +- www/content/docs/pages.mdx | 161 +++++++----------- www/content/docs/preview-mode.mdx | 26 --- www/content/docs/reference/buildEndpoint.mdx | 59 +++++++ www/content/docs/reference/buildurl.mdx | 4 +- .../reference/constructpathfromsegment.mdx | 79 +++++++++ .../docs/reference/createfileresource.mdx | 2 +- www/content/docs/reference/createresource.mdx | 2 +- www/content/docs/reference/deleteresource.mdx | 2 +- www/content/docs/reference/deserialize.mdx | 6 +- www/content/docs/reference/fetch.mdx | 5 + www/content/docs/reference/getaccesstoken.mdx | 10 +- .../docs/reference/getauthorizationheader.mdx | 31 ++++ .../reference/getentryforresourcetype.mdx | 40 ----- www/content/docs/reference/getmenu.mdx | 37 +++- .../docs/reference/getpathfromcontext.mdx | 32 ---- www/content/docs/reference/getresource.mdx | 30 +++- .../docs/reference/getresourcebypath.mdx | 33 +++- .../docs/reference/getresourcecollection.mdx | 22 +++ .../getresourcecollectionfromcontext.mdx | 78 --------- .../getresourcecollectionpathsegments.mdx | 99 +++++++++++ .../docs/reference/getresourcefromcontext.mdx | 138 --------------- www/content/docs/reference/getsearch.mdx | 6 + .../reference/getstaticpathsfromcontext.mdx | 59 ------- www/content/docs/reference/getview.mdx | 22 +++ www/content/docs/reference/preview.mdx | 43 ----- www/content/docs/reference/translatepath.mdx | 10 +- .../reference/translatepathfromcontext.mdx | 42 ----- www/content/docs/reference/updateresource.mdx | 2 +- www/content/docs/serializer.mdx | 32 ---- www/content/docs/typescript.mdx | 47 ++++- www/content/docs/updating-resources.mdx | 18 +- www/content/guides/jsonapi-params.mdx | 7 +- .../configure-content-types.mdx | 0 .../configure-preview-routes.mdx | 0 .../create-oauth-client.mdx | 0 .../create-site.mdx | 0 .../{preview-mode => draft-mode}/done.mdx | 0 www/content/tutorials/draft-mode/index.mdx | 10 ++ .../on-demand-revalidation/index.mdx | 2 +- www/content/tutorials/preview-mode/index.mdx | 10 -- www/next.config.js | 6 +- 55 files changed, 837 insertions(+), 816 deletions(-) create mode 100644 www/content/docs/deserializer.mdx create mode 100644 www/content/docs/draft-mode.mdx delete mode 100644 www/content/docs/preview-mode.mdx create mode 100644 www/content/docs/reference/buildEndpoint.mdx create mode 100644 www/content/docs/reference/constructpathfromsegment.mdx create mode 100644 www/content/docs/reference/getauthorizationheader.mdx delete mode 100644 www/content/docs/reference/getentryforresourcetype.mdx delete mode 100644 www/content/docs/reference/getpathfromcontext.mdx delete mode 100644 www/content/docs/reference/getresourcecollectionfromcontext.mdx create mode 100644 www/content/docs/reference/getresourcecollectionpathsegments.mdx delete mode 100644 www/content/docs/reference/getresourcefromcontext.mdx delete mode 100644 www/content/docs/reference/getstaticpathsfromcontext.mdx delete mode 100644 www/content/docs/reference/preview.mdx delete mode 100644 www/content/docs/reference/translatepathfromcontext.mdx delete mode 100644 www/content/docs/serializer.mdx rename www/content/tutorials/{preview-mode => draft-mode}/configure-content-types.mdx (100%) rename www/content/tutorials/{preview-mode => draft-mode}/configure-preview-routes.mdx (100%) rename www/content/tutorials/{preview-mode => draft-mode}/create-oauth-client.mdx (100%) rename www/content/tutorials/{preview-mode => draft-mode}/create-site.mdx (100%) rename www/content/tutorials/{preview-mode => draft-mode}/done.mdx (100%) create mode 100644 www/content/tutorials/draft-mode/index.mdx delete mode 100644 www/content/tutorials/preview-mode/index.mdx diff --git a/www/config/docs.ts b/www/config/docs.ts index 7c4360e23..b4f70cb01 100644 --- a/www/config/docs.ts +++ b/www/config/docs.ts @@ -49,8 +49,8 @@ export const docsConfig: DocsConfig = { href: "/docs/environment-variables", }, { - title: "Preview Mode", - href: "/docs/preview-mode", + title: "Draft Mode", + href: "/docs/draft-mode", }, { title: "TypeScript", @@ -108,8 +108,8 @@ export const docsConfig: DocsConfig = { href: "/docs/fetcher", }, { - title: "Serializer", - href: "/docs/serializer", + title: "Deserializer", + href: "/docs/deserializer", }, { title: "Caching", @@ -124,10 +124,6 @@ export const docsConfig: DocsConfig = { title: "getResource", href: "/docs/reference/getresource", }, - { - title: "getResourceFromContext", - href: "/docs/reference/getresourcefromcontext", - }, { title: "getResourceByPath", href: "/docs/reference/getresourcebypath", @@ -136,10 +132,6 @@ export const docsConfig: DocsConfig = { title: "getResourceCollection", href: "/docs/reference/getresourcecollection", }, - { - title: "getResourceCollectionFromContext", - href: "/docs/reference/getresourcecollectionfromcontext", - }, { title: "createResource", href: "/docs/reference/createresource", @@ -157,28 +149,20 @@ export const docsConfig: DocsConfig = { href: "/docs/reference/deleteresource", }, { - title: "getStaticPathsFromContext", - href: "/docs/reference/getstaticpathsfromcontext", + title: "getResourceCollectionPathSegments", + href: "/docs/reference/getresourcecollectionpathsegments", }, { title: "translatePath", href: "/docs/reference/translatepath", }, { - title: "translatePathFromContext", - href: "/docs/reference/translatepathfromcontext", - }, - { - title: "getPathFromContext", - href: "/docs/reference/getpathfromcontext", - }, - { - title: "getEntryForResourceType", - href: "/docs/reference/getentryforresourcetype", + title: "constructPathFromSegment", + href: "/docs/reference/constructpathfromsegment", }, { - title: "preview", - href: "/docs/reference/preview", + title: "buildEndpoint", + href: "/docs/reference/buildEndpoint", }, { title: "getAccessToken", @@ -208,6 +192,10 @@ export const docsConfig: DocsConfig = { title: "deserialize", href: "/docs/reference/deserialize", }, + { + title: "getAuthorizationHeader", + href: "/docs/reference/getauthorizationheader", + }, ], }, { diff --git a/www/config/tutorials.ts b/www/config/tutorials.ts index 9e868286a..3046d74f9 100644 --- a/www/config/tutorials.ts +++ b/www/config/tutorials.ts @@ -12,9 +12,9 @@ export const tutorialsConfig = [ items: [], }, { - title: "Preview Mode", - excerpt: "Implement Preview Mode for Entity Types.", - url: "/learn/preview-mode", + title: "Draft Mode", + excerpt: "Implement Draft Mode for Entity Types.", + url: "/learn/draft-mode", items: [], }, { diff --git a/www/content/docs/authentication.mdx b/www/content/docs/authentication.mdx index 765ba8bb3..89df6e708 100644 --- a/www/content/docs/authentication.mdx +++ b/www/content/docs/authentication.mdx @@ -1,9 +1,9 @@ --- title: Authentication -excerpt: Making authenticated requests with DrupalClient. +excerpt: Making authenticated requests with NextDrupal. --- -The `DrupalClient` works with several auth types. You can use **Bearer** tokens, **Basic** tokens or bring your own authorization headers. +The `NextDrupal` client works with several auth types. You can use **Bearer** tokens, **Basic** tokens or bring your own authorization headers. Authentication can be set globally on the client or custom per method. @@ -16,9 +16,9 @@ This is the default authentication configured on the client. **This is used most of the time for fetching and building static pages.** ```ts title=lib/drupal.ts -import { DrupalClient } from "next-drupal" +import { NextDrupal } from "next-drupal" -export const drupal = new DrupalClient( +export const drupal = new NextDrupal( process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { auth: // Configure the global auth here. @@ -59,15 +59,12 @@ You need to enable the `simple_oauth` module on Drupal. ```ts title=lib/drupal.ts // Client -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - auth: { - clientId: process.env.DRUPAL_CLIENT_ID, - clientSecret: process.env.DRUPAL_CLIENT_SECRET, - }, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + auth: { + clientId: process.env.DRUPAL_CLIENT_ID, + clientSecret: process.env.DRUPAL_CLIENT_SECRET, + }, +}) // Method const article = drupal.getResource( @@ -82,26 +79,23 @@ const article = drupal.getResource( ) ``` -`DrupalClient` will fetch **Bearer** token and handle expiration for you. +`NextDrupal` client will fetch **Bearer** token and handle expiration for you. If you need to customize the OAuth URL you can use the `url` option. ```ts title=lib/drupal.ts -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - auth: { - clientId: process.env.DRUPAL_CLIENT_ID, - clientSecret: process.env.DRUPAL_CLIENT_SECRET, - // highlight-start - url: `/oauth2/token`, - // highlight-end - }, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + auth: { + clientId: process.env.DRUPAL_CLIENT_ID, + clientSecret: process.env.DRUPAL_CLIENT_SECRET, + // highlight-start + url: `/oauth2/token`, + // highlight-end + }, +}) ``` -By default, `DrupalClient` uses `/oauth/token` as the default URL. +By default, `NextDrupal` uses `/oauth/token` as the default URL. --- @@ -117,15 +111,12 @@ You need to enable the `basic_auth` module on Drupal. ```ts // Client. -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - auth: { - username: process.env.DRUPAL_USERNAME, - password: process.env.DRUPAL_PASSWORD, - }, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + auth: { + username: process.env.DRUPAL_USERNAME, + password: process.env.DRUPAL_PASSWORD, + }, +}) // Method const articles = await drupal.getResourceCollection("node--article", { @@ -144,14 +135,11 @@ You can also provide a custom callback for authentication. The callback must ret ```ts // Client -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - auth: () => { - // Do something and return an Authorization header. - }, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + auth: () => { + // Do something and return an Authorization header. + }, +}) // Method const users = await drupal.getResourceCollection("user--user", { @@ -167,16 +155,13 @@ You can also pass in an access token. ```ts // Client -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - auth: { - access_token: "ECYM594IlARGc3S8KgBHvTpki0rDtWx6...", - token_type: "Bearer", - expires_in: 3600, - }, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + auth: { + access_token: "ECYM594IlARGc3S8KgBHvTpki0rDtWx6...", + token_type: "Bearer", + expires_in: 3600, + }, +}) // Method const articles = await drupal.getResourceCollection("node--article", { @@ -192,13 +177,21 @@ const articles = await drupal.getResourceCollection("node--article", { If you're using [NextAuth](https://next-auth.js.org) you can use the results from `getSession`: + + ```ts import { getSession } from "next-auth/react" const session = getSession(...) // Client -export const drupal = new DrupalClient( +export const drupal = new NextDrupal( process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { auth: session.accessToken, diff --git a/www/content/docs/cache.mdx b/www/content/docs/cache.mdx index 93aae1cb8..99b7f51ac 100644 --- a/www/content/docs/cache.mdx +++ b/www/content/docs/cache.mdx @@ -3,7 +3,7 @@ title: Caching excerpt: Using a custom cache for resources. --- -The `DrupalClient` has support for caching resources. +The `NextDrupal` has support for caching resources. This is handy when dealing with global data: you can fetch data once and re-use during builds. @@ -11,6 +11,14 @@ You can provide your own cache implementation using the [`cache`](/docs/configur --- + + ## Example Here's an example on how you can use Redis to cache resources. @@ -22,7 +30,7 @@ Note: as of `next-drupal 1.3.0`, only `getResource` and `getMenu` support cachin ```ts title=lib/drupal.ts -import { DrupalClient, DataCache } from "next-drupal" +import { NextDrupal, DataCache } from "next-drupal" import Redis from "ioredis" const redis = new Redis(process.env.REDIS_URL) @@ -37,12 +45,9 @@ export const redisCache: DataCache = { }, } -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - cache: redisCache, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + cache: redisCache, +}) ``` Now when you make a `getResource` or `getMenu` call you can tell the client to cache and re-use responses. diff --git a/www/content/docs/client.mdx b/www/content/docs/client.mdx index 23f3dafd0..ed25b0a74 100644 --- a/www/content/docs/client.mdx +++ b/www/content/docs/client.mdx @@ -1,11 +1,11 @@ --- -title: Drupal Client +title: NextDrupal Client excerpt: A powerful JSON:API client for Drupal. --- -The `DrupalClient` is a powerful JSON:API client that ships with helpers for working with Drupal data. +The `NextDrupal` is a powerful JSON:API client that ships with helpers for working with Drupal data. -You can use the `DrupalClient` to fetch JSON:API data from Drupal to build static pages. +You can use the `NextDrupal` client to fetch JSON:API data from Drupal to build static pages. It also comes with full support for JSON:API write operations which means you can create JSON:API resources from Next.js to Drupal. @@ -27,10 +27,10 @@ It also comes with full support for JSON:API write operations which means you ca ## Usage ```ts -import { DrupalClient } from "next-drupal" +import { NextDrupal } from "next-drupal" -// Create a new DrupalClient. -const drupal = new DrupalClient("https://example.com") +// Create a new NextDrupal client. +const drupal = new NextDrupal("https://example.com") // Fetch articles. const articles = await drupal.getResourceCollection("node--article") diff --git a/www/content/docs/configuration.mdx b/www/content/docs/configuration.mdx index e46e7cd98..26c3b21e9 100644 --- a/www/content/docs/configuration.mdx +++ b/www/content/docs/configuration.mdx @@ -1,19 +1,19 @@ --- title: Configuration -excerpt: Initialization and options for DrupalClient. +excerpt: Initialization and options for NextDrupal client. --- ## Initialization -To create a new `DrupalClient`, use the following initialization: +To create a new `NextDrupal`, use the following initialization: ```ts -import { DrupalClient } from "next-drupal" +import { NextDrupal } from "next-drupal" -const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL) +const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL) ``` -Where `NEXT_PUBLIC_DRUPAL_BASE_URL` is the URL to your Drupal site defined as an [enviroment variable](/docs/enviroment-variables). +Where `NEXT_PUBLIC_DRUPAL_BASE_URL` is the URL to your Drupal site defined as an [environment variable](/docs/environment-variables). ```txt title=.env.local NEXT_PUBLIC_DRUPAL_BASE_URL=http://example.com @@ -33,7 +33,7 @@ Additional options can be passed during initialization to customize the behavior The JSON:API prefix to use. If you are using the [JSON:API Extras](https://www.drupal.org/project/jsonapi_extras) module, you can customize the JSON:API prefix and set the custom value here. ```ts -new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { apiPrefix: "/api", }) ``` @@ -48,7 +48,7 @@ new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { Use this to set the path for your front page. This path will resolve to `/` on your Next.js site. ```ts -new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { frontPage: "/front", }) ``` @@ -66,26 +66,28 @@ You can find more info about using a custom auth [here](/docs/authentication). --- -### serializer +### deserializer - **Default value**: Built-in - **Required**: No -Override the default data serializer. You can use this to add your own JSON:API data deserializer. +Override the default data deserializer. You can use this to add your own JSON:API data deserializer. ```ts import { Deserializer } from "jsonapi-serializer" -const customSerializer = new Deserializer({ +const jsonDeserializer = new Deserializer({ keyForAttribute: "camelCase", }) -new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { - serializer: customSerializer, +const customDeserializer = jsonSerializer.deserialize.bind(jsonSerializer) + +new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + deserializer: customDeserializer, }) ``` -You can find more info about using a custom serializer [here](/docs/serializer). +You can find more info about using a custom deserializer [here](/docs/deserializer). --- @@ -112,7 +114,7 @@ const customFetcher = (url, options) => { }) } -new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { fetcher: customFetcher, }) ``` @@ -123,6 +125,14 @@ You can find more info about using a custom fetcher [here](/docs/fetcher). ### cache + + - **Default value**: `null` - **Required**: No @@ -144,7 +154,7 @@ export const redisCache: DataCache = { }, } -new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { cache: redisCache, }) ``` @@ -171,16 +181,13 @@ Set whether the client should use authenticated requests by default. If set to ` --- -### useDefaultResourceTypeEntry - -- **Default value**: `false` -- **Required**: No + ### headers @@ -190,7 +197,7 @@ If your resources follow the `entity_type--bundle` naming convention, you can sa Set custom headers for the fetcher. ```ts -new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { headers: { "Content-Type": "application/json", }, @@ -217,3 +224,21 @@ Use this to turn on the built-in logger. If you would like to replace with your . --- + +### throwJsonApiErrors + +- **Default value**: `true` +- **Required**: No + +JSON:API errors are thrown in non-production environments by default. The errors are shown in the Next.js overlay. Use this to turn it off. + +--- + +### useDefaultEndpoint + +- **Default value**: `true` +- **Required**: No + +By default, the resource endpoint will be based on the resource name. If you turn this off, a JSON:API request will retrieve the resource's endpoint url. + +--- diff --git a/www/content/docs/creating-resources.mdx b/www/content/docs/creating-resources.mdx index 3c4c3f887..bd3719410 100644 --- a/www/content/docs/creating-resources.mdx +++ b/www/content/docs/creating-resources.mdx @@ -1,6 +1,6 @@ --- title: Creating Resources (POST) -excerpt: How to create JSON:API resources using DrupalClient. +excerpt: How to create JSON:API resources using NextDrupal client. --- @@ -9,13 +9,23 @@ The `createResource` and `createFileResource` helpers are available in `next-dru -The `DrupalClient` ships with a `createResource` and a `createFileResource` methods for creating JSON:API resources. + + +If you're working with JSON:API, be mindful to select the option: + +`Accept all JSON:API create, read, update, and delete operations.` + +on the following path: `/admin/config/services/jsonapi` on Drupal. + + + +The `NextDrupal` client ships with a `createResource` and a `createFileResource` methods for creating JSON:API resources. --- ## createResource -### Create Resource +#### Create Resource Create an article with a title and a body. @@ -33,7 +43,7 @@ const article = await drupal.createResource("node--article", { }) ``` -### Create Resource with Relationships +#### Create Resource with Relationships Create an article with a media field. diff --git a/www/content/docs/deleting-resources.mdx b/www/content/docs/deleting-resources.mdx index 75db53d86..79a55e994 100644 --- a/www/content/docs/deleting-resources.mdx +++ b/www/content/docs/deleting-resources.mdx @@ -1,6 +1,6 @@ --- title: Deleting Resources (DELETE) -excerpt: How to delete JSON:API resources using DrupalClient. +excerpt: How to delete JSON:API resources using NextDrupal. --- @@ -9,7 +9,17 @@ The `deleteResource` helper is available in `next-drupal ^1.4.0`. -The `DrupalClient` ships with a `deleteResource` method for deleting JSON:API resources. + + +If you're working with JSON:API, be mindful to select the option: + +`Accept all JSON:API create, read, update, and delete operations.` + +on the following path: `/admin/config/services/jsonapi` on Drupal. + + + +The `NextDrupal` client ships with a `deleteResource` method for deleting JSON:API resources. --- diff --git a/www/content/docs/deserializer.mdx b/www/content/docs/deserializer.mdx new file mode 100644 index 000000000..50a81197b --- /dev/null +++ b/www/content/docs/deserializer.mdx @@ -0,0 +1,31 @@ +--- +title: Deserializer +excerpt: Using a custom deserializer with NextDrupal. +--- + +The `NextDrupal` uses [jsona](https://github.com/olosegres/jsona) as the default deserializer for serializing and deserializing JSON:API data. + +You can provide your own using the [`deserializer`](/docs/client/configuration#deserializer) option. + +--- + +## Example + +Here's how you can replace the default deserializer with [jsonapi-serializer](https://github.com/SeyZ/jsonapi-serializer). + +```ts title=lib/drupal.ts +import { NextDrupal } from "next-drupal" +import { Deserializer } from "jsonapi-serializer" + +// Create a custom deserializer. +const jsonDeserializer = new Deserializer({ + keyForAttribute: "camelCase", +}) + +const customDeserializer = jsonDeserializer.deserialize.bind(jsonDeserializer) + +// Pass the custom deserializer to the client. +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + deserializer: customDeserializer, +}) +``` diff --git a/www/content/docs/draft-mode.mdx b/www/content/docs/draft-mode.mdx new file mode 100644 index 000000000..8e6215ecb --- /dev/null +++ b/www/content/docs/draft-mode.mdx @@ -0,0 +1,29 @@ +--- +title: Draft Mode +excerpt: Using draft mode with NextDrupal client. +--- + +To implement draft mode, configure entity types on Drupal. See the guide [here](/learn/draft-mode). + +1. Implement `/app/api/draft/route.ts`. + +```ts title=app/api/draft/route.ts +import { drupal } from "@/lib/drupal" +import { enableDraftMode } from "next-drupal/draft" +import type { NextRequest } from "next/server" + +export async function GET(request: NextRequest): Promise { + return enableDraftMode(request, drupal) +} +``` + +2. Implement `/app/api/disable-draft/route.ts` + +```ts title=app/api/disable-draft/route.ts +import { disableDraftMode } from "next-drupal/draft" +import type { NextRequest } from "next/server" + +export async function GET(request: NextRequest) { + return disableDraftMode() +} +``` diff --git a/www/content/docs/environment-variables.mdx b/www/content/docs/environment-variables.mdx index 62e9e45bd..7799a2932 100644 --- a/www/content/docs/environment-variables.mdx +++ b/www/content/docs/environment-variables.mdx @@ -28,7 +28,7 @@ DRUPAL_FRONT_PAGE= ## Required -These environment variables are required for initializing a new `DrupalClient`. +These environment variables are required for initializing a new `NextDrupal` client. | Name | Description | | ----------------------------- | :------------------------------------------------------------------------------------------------------------------------- | @@ -36,7 +36,7 @@ These environment variables are required for initializing a new `DrupalClient`. | `NEXT_IMAGE_DOMAIN` | The domain name for [next/image](https://nextjs.org/docs/basic-features/image-optimization#domains). Example: `drupal.org` | ```ts -const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL) +const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL) ``` --- @@ -49,15 +49,18 @@ Environment variables required for on-demand revalidation. | -------------------------- | :------------------------------------------------------------------------------------------------ | | `DRUPAL_REVALIDATE_SECRET` | The secret for [on-demand revalidation](/docs/on-demand-revalidation). Example: `U2Y5bbkKJ08Ua8F` | -```ts title=pages/api/revalidate.ts -export default async function handler(request, response) { - const secret = request.query.secret as string +```ts title=app/api/revalidate/route.ts +async function handler(request: NextRequest) { + const searchParams = request.nextUrl.searchParams + const secret = searchParams.get("secret") // Validate secret. if (secret !== process.env.DRUPAL_REVALIDATE_SECRET) { - return response.status(401).json({ message: "Invalid secret." }) + return new Response("Invalid secret.", { status: 401 }) } } + +export { handler as GET, handler as POST } ``` --- @@ -70,7 +73,7 @@ export default async function handler(request, response) { | `DRUPAL_CLIENT_SECRET` | The OAuth client secret. Example: `3#9h$2DU#8qKb6&` | ```ts -const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { auth: { clientId: process.env.DRUPAL_CLIENT_ID, clientSecret: process.env.DRUPAL_CLIENT_SECRET, @@ -88,7 +91,7 @@ const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { | `DRUPAL_PASSWORD` | The Drupal password. Example: `password` | ```ts -const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { auth: { username: process.env.DRUPAL_USERNAME, password: process.env.DRUPAL_PASSWORD, @@ -121,7 +124,7 @@ const nodes = await drupal.getResourceCollection( ``` ```ts title=DRUPAL_FRONT_PAGE -const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { +const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { frontPage: process.env.DRUPAL_FRONT_PAGE, }) ``` diff --git a/www/content/docs/fetcher.mdx b/www/content/docs/fetcher.mdx index ba5d9f940..e124e5cb4 100644 --- a/www/content/docs/fetcher.mdx +++ b/www/content/docs/fetcher.mdx @@ -1,9 +1,17 @@ --- title: Fetcher -excerpt: Using a custom fetcher with DrupalClient. +excerpt: Using a custom fetcher with NextDrupal. --- -The `DrupalClient` uses the polyfilled `fetch` from Next.js as the default fetcher. + + +The `NextDrupal` uses the polyfilled `fetch` from Next.js as the default fetcher. You can provide your own using the [`fetcher`](/docs/configuration#fetcher) option. @@ -20,7 +28,7 @@ We're using **cross-fetch** instead of **node-fetch** because it is compatible w ```ts title=lib/drupal.ts -import { DrupalClient } from "next-drupal" +import { NextDrupal } from "next-drupal" import crossFetch from "cross-fetch" // Create a custom fetcher. @@ -39,10 +47,7 @@ const customFetcher = (url, options) => { } // Pass the custom fetcher to the client. -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - fetcher: customFetcher, - } -) +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + fetcher: customFetcher, +}) ``` diff --git a/www/content/docs/fetching-resources.mdx b/www/content/docs/fetching-resources.mdx index db72cc0fd..7c8aab964 100644 --- a/www/content/docs/fetching-resources.mdx +++ b/www/content/docs/fetching-resources.mdx @@ -1,9 +1,9 @@ --- title: Fetching Resources (GET) -excerpt: How to fetch JSON:API resources using DrupalClient. +excerpt: How to fetch JSON:API resources using NextDrupal client. --- -The `DrupalClient` ships with helpers to fetch JSON:API data from Drupal. +The `NextDrupal` client ships with helpers to fetch JSON:API data from Drupal. You can fetch a single resource, `getResource` or a collection of resources, `getResourceCollection`. @@ -59,17 +59,15 @@ See the API reference for [getResource](/docs/reference/getresource). --- -## getResourceFromContext +## getResourceByPath -Fetch an article in `getStaticProps/getServerSideProps` with context. - -If you're using [internationalization](https://nextjs.org/docs/advanced-features/i18n-routing), this will automatically fetch the localized resource using the `locale` set in context. +Fetch an article by path. ```ts -const article = await drupal.getResourceFromContext("node--article", context) +const article = await drupal.getResourceByPath("/blog/slug-for-article") ``` -See the API reference for [getResourceFromContext](/docs/reference/getresourcefromcontext). +See the API reference for [getResourceByPath](/docs/reference/getresourcebypath). --- @@ -96,23 +94,6 @@ See the API reference for [getResourceCollection](/docs/reference/getresourcecol --- -## getResourceCollectionFromContext - -Fetch articles in `getStaticProps/getServerSideProps` with context. - -If you're using [internationalization](https://nextjs.org/docs/advanced-features/i18n-routing), this will automatically fetch localized resources using the `locale` set in context. - -```ts -const articles = await drupal.getResourceCollectionFromContext( - "node--article", - context -) -``` - -See the API reference for [getResourceCollectionFromContext](/docs/reference/getresourcecollectionfromcontext). - ---- - ## getMenu @@ -188,6 +169,9 @@ const article = await drupal.getResourceCollection( ) ``` + diff --git a/www/content/docs/index.mdx b/www/content/docs/index.mdx index f7348c1e4..85ce2b7e1 100644 --- a/www/content/docs/index.mdx +++ b/www/content/docs/index.mdx @@ -5,7 +5,15 @@ excerpt: Next-generation front end for your Drupal site. Welcome to the next-drupal documentation. -This documentation covers `next-drupal 1.3+`. +This documentation covers `next-drupal 2.0`. + + If you're using an older version, you can find the documentation [here](https://v1.next-drupal.org). @@ -31,7 +39,7 @@ npx create-next-app -e https://github.com/chapter-three/next-drupal-basic-starte - DrupalClient + NextDrupal

A powerful JSON:API client for Drupal.

@@ -47,6 +55,6 @@ npx create-next-app -e https://github.com/chapter-three/next-drupal-basic-starte API Reference -

API Reference for DrupalClient.

+

API Reference for NextDrupal client.

diff --git a/www/content/docs/pages.mdx b/www/content/docs/pages.mdx index b008da721..026dda7b1 100644 --- a/www/content/docs/pages.mdx +++ b/www/content/docs/pages.mdx @@ -3,9 +3,17 @@ title: Building Pages excerpt: How to build pages using JSON:API resources from Drupal. --- -In Next.js, you fetch server-side data in either `getStaticProps` or `getServerSideProps`. Data is then fed to your pages for pre-rendering. +In Next.js V14, data fetching has evolved significantly from previous versions. Instead of using `getStaticProps` and `getServerSideProps` you now use the native `fetch` function enhanced by Next.js to handle server-side data fetching. This allows you to configure caching and revalidation directly within your fetch requests. These can be used in Server Components, Route Handlers, and Server Actions. You can read more about it [here](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating) -The `DrupalClient` provides several functions to help you query JSON:API resources from Drupal. +The `NextDrupal` client provides several functions to help you query JSON:API resources from Drupal and manage these revalidation options on the `fetch` request level. + + --- @@ -22,30 +30,21 @@ const node = await drupal.getResource( A full page would look like this: -```tsx title=pages/about.tsx -// node will be populated at build time by getStaticProps -export default function AboutPage({ node }) { - return ( -
-

{node.title}

- // ... -
- ) -} - -export async function getStaticProps() { +```tsx title=app/about/page.tsx +// page will be generated at build time +export default function AboutPage() { // Fetch the node from Drupal. const node = await drupal.getResource( "node--page", "07464e9f-9221-4a4f-b7f2-01389408e6c8" ) - // Pass the node as props to the AboutPage. - return { - props: { - node, - }, - } + return ( +
+

{node.title}

+ // ... +
+ ) } ``` @@ -53,19 +52,34 @@ export async function getStaticProps() { ## Dynamic pages -You can use Next.js [dynamic route](https://nextjs.org/docs/basic-features/pages#pages-with-dynamic-routes) to build static pages for Drupal entity types. +You can use Next.js [dynamic route](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) to build static pages for Drupal entity types. + +Start by creating a page at `/app/[...slug]/page.tsx`, where `[...slug]` maps to the **path alias** for an entity type (or content type) in Drupal. + +This means `/app/[...slug]/page.tsx` will handle all pages with the following aliases: `/about`, `/team`, `/another/path` ...etc. + +To build static pages, there is a built-in function we need to use: -Start by creating a page at `/pages/[...slug].tsx`, where `[...slug]` maps to the **path alias** for an entity type (or content type) in Drupal. +`generateStaticParams`: to tell Next.js all the routes that we want to have pre-rendered at build time. -This means `/pages/[...slug].tsx` will handle all pages with the following aliases: `/about`, `/team`, `/another/path` ...etc. +```tsx title=app/[...slug]/page.tsx -To build static pages, there are two functions we need to implement: +export async function generateStaticParams() { + // Build paths for all `node--page`. + const resources = await drupal.getResourceCollectionPathSegments( + "node--page" + ); + return resources.map((resource) => slug: resource.segments); +} +export default function Page({ params }) { + const {slug} = params; -1. `getStaticPaths`: to tell Next.js all the routes that we want to be rendered. -2. `getStaticProps`: to fetch data for pages. + // Construct drupal path based on params + const drupalPath = drupal.constructPathFromSegment(slug) + + // Fetch the node based on drupal path. + const node = drupal.getResourceByPath(drupalPath) -```tsx title=pages/[...slug].tsx -export default function Page({ node }) { return (

{node.title}

@@ -73,85 +87,37 @@ export default function Page({ node }) {
) } - -export async function getStaticPaths(context) { - // Build paths for all `node--page`. - return { - paths: await drupal.getStaticPathsFromContext("node--page", context), - fallback: false, - } -} - -export async function getStaticProps(context) { - // Fetch the node based on the context. - // next-drupal automatically handles the slug value. - const node = await drupal.getResourceFromContext("node--page", context) - - return { - props: { - node, - }, - } -} ``` --- ## Advanced Example -In the example above, we used `pages/[...slug].tsx` to build static pages for `node--page`. +In the example above, we used `app/[...slug]/page.tsx` to build static pages for `node--page`. We can go a step further and handle all node types (or any entity types) in one page. -To do that, we're going to use `translatePathFromContext` which returns info about the resource type based on `slug` value in `context`. +To do that, we're going to use `translatePath` which returns info about the resource type based on `slug` value in `params`. -```tsx -export async function getStaticProps(context) { - const path = await drupal.translatePathFromContext(context) +Let's update `app/[...slug]/page.tsx` to handle both `node--page` and `node--article`. - // Get the resource type. - const type = path.jsonapi.resourceName - - if (type === "node--article") { - // Build custom JSON:API query for article. - } - - if (type === "node--page") { - // Build custom JSON:API query for page. - } -} -``` - -Let's update `pages/[...slug].tsx` to handle both `node--page` and `node--article`. - -```tsx title=pages/[...slug].tsx +```tsx title=app/[...slug]/page.tsx import { DrupalJsonApiParams } from "drupal-jsonapi-params" -export default function Page({ node }) { - if (node.type === "node--page") { - return - } - - if (node.type === "node--article") { - return - } +export async function generateStaticParams() { + // Build paths for all `node--page` and `node--article`. - return null + const resources = await drupal.getResourceCollectionPathSegments( + ["node--page", "node--article"] + ); + return resources.map((resource) => slug: resource.segments); } -export async function getStaticPaths(context) { - // Build paths for all `node--page` and `node--article`. - return { - paths: await drupal.getStaticPathsFromContext( - ["node--page", "node--article"], - context - ), - fallback: false, - } -} -export async function getStaticProps(context) { - const path = await drupal.translatePathFromContext(context) +export default function Page({ params }) { + const {slug} = params; + + const path = drupal.translatePath(slug) // Get the resource type. const type = path.jsonapi.resourceName @@ -168,15 +134,20 @@ export async function getStaticProps(context) { params.addFields("node--article", ["title", "path", "body", "uid"]) } - const node = await drupal.getResourceFromContext(type, context, { + const node = await drupal.getResourceByPath(path, { params: params.getQueryObject(), }) - return { - props: { - node, - }, + // Render different Components based on Node type + if (node.type === "node--page") { + return } + + if (node.type === "node--article") { + return + } + + return null } ``` diff --git a/www/content/docs/preview-mode.mdx b/www/content/docs/preview-mode.mdx deleted file mode 100644 index 46f3d021b..000000000 --- a/www/content/docs/preview-mode.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Preview Mode -excerpt: Using preview mode with DrupalClient. ---- - -To implement preview mode, configure entity types on Drupal. See the guide [here](/learn/preview-mode). - -1. Implement `/pages/api/preview.ts`. - -```ts title=pages/api/preview.ts -import { drupal } from "lib/drupal" - -export default async function handler(req, res) { - return await drupal.preview(req, res) -} -``` - -2. Implement `/pages/api/exit-preview.ts` - -```ts title=pages/api/exit-preview.ts -export default function exit(_, res) { - res.clearPreviewData() - res.writeHead(307, { Location: "/" }) - res.end() -} -``` diff --git a/www/content/docs/reference/buildEndpoint.mdx b/www/content/docs/reference/buildEndpoint.mdx new file mode 100644 index 000000000..9369ae809 --- /dev/null +++ b/www/content/docs/reference/buildEndpoint.mdx @@ -0,0 +1,59 @@ +--- +title: buildEndpoint +excerpt: Get the JSON:API entry for a resource type. +--- + +```ts +const url = await drupal.buildEndpoint({ + locale, + resourceType, + path, + searchParams +}): Promise +``` + +- `type: string` + - Optional + - The resource type. Example: `node--article`. +- `locale: string` + - Optional + - The locale to fetch the index. Example: `es` or `fr`. +- `path: string` + - Optional + - The path to fetch. Example: `test`. +- `searchParams: string | Record | URLSearchParams | JsonApiParams` + - Optional + - Search params. Example: `{ bar: "baz" }`. + +--- + +## Notes + +By default, when retrieving resources in `getResource` or `getResourceCollection`, the `NextDrupal` client make a request to Drupal to fetch the JSON:API resource entry. + +Example: if you provide `node--article`, `NextDrupal` will make a request to `http://example.com/jsonapi/node/article`. + +If you would like to infer the entry from the resource type, use the [`useDefaultResourceTypeEntry`](/docs/configuration#usedefaultresourcetypeentry) option. + +```ts +const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + useDefaultResourceTypeEntry: true, +}) +``` + +--- + +## Examples + +```ts +// https://example.com/jsonapi/node/article. +const url = await drupal.buildEndpoint({ resourceType: `node--article` }) +``` + + diff --git a/www/content/docs/reference/buildurl.mdx b/www/content/docs/reference/buildurl.mdx index 672c2c075..18d5a5983 100644 --- a/www/content/docs/reference/buildurl.mdx +++ b/www/content/docs/reference/buildurl.mdx @@ -4,13 +4,13 @@ excerpt: A helper for building Url with query params. --- ```ts -const url = drupal.buildUrl(path, params?): URL +const url = drupal.buildUrl(path, searchParams?): URL ``` - `path: string` - **Required** - The path for the url. Example: "/example" -- `params: string | Record | URLSearchParams | JsonApiParams` +- `searchParams: string | Record | URLSearchParams | JsonApiParams` - Optional --- diff --git a/www/content/docs/reference/constructpathfromsegment.mdx b/www/content/docs/reference/constructpathfromsegment.mdx new file mode 100644 index 000000000..b744484d3 --- /dev/null +++ b/www/content/docs/reference/constructpathfromsegment.mdx @@ -0,0 +1,79 @@ +--- +title: constructPathFromSegment +excerpt: Returns a Drupal path given an array of Next.js path segments, path prefix and locale. +--- + +```ts +const slug = drupal.constructPathFromSegment( + segment, + options?: { + pathPrefix, + locale, + defaultLocale + } +): string +``` + +- `segment: string | string[]` +- `options` + - Optional + - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. + - `locale: string`: The locale to fetch the resource in. + - `defaultLocale: string`: The default locale of the site. + +--- + +## Examples + +- Get the path (slug) from `en/news/article-1`. + +```ts + +const path = drupal.constructPathFromSegment('article-1', { + locale: 'en', + pathPrefix: '/news' +}) + +`path` will result in: `/en/news/article-1` + +``` + +This might be useful when trying to get the full path of the `params` object coming from `generateStaticParams`. +Ex: `app/[lang]/[...slug]/page.tsx` + +```tsx +export async function generateStaticParams() { + const apiParams = new DrupalJsonApiParams() + const params = apiParams + .addFields("node--landing_page", ["status", "path", "changed"]) + .addSort("changed", "DESC") + .addFilter("status", "1") + + const paths = await drupalClient.getResourceCollectionPathSegments( + ["node--landing_page"], + { + params: params.getQueryObject(), + defaultLocale: "en", + locales: ["en", "es"], + } + ) + + return paths.map((path) => { + return { + slug: path.segments, + lang: path.locale, + } + }) +} + +export default async function LandingPage({ params }) { + const { slug, lang } = params + + const path = drupal.constructPathFromSegment(slug, { locale: lang }) + + // If slug = ['segment-1', 'segment-2'] and lang = 'en' + // path will result in '/en/segment-1/segment-2' + + // ... +} +``` diff --git a/www/content/docs/reference/createfileresource.mdx b/www/content/docs/reference/createfileresource.mdx index 9a5ef598e..f321df656 100644 --- a/www/content/docs/reference/createfileresource.mdx +++ b/www/content/docs/reference/createfileresource.mdx @@ -28,7 +28,7 @@ const resource = await drupal.createFileResource( - `options` - Optional - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - `deserialize: boolean`: Set to false to return the raw JSON:API response. diff --git a/www/content/docs/reference/createresource.mdx b/www/content/docs/reference/createresource.mdx index 88f93c867..49cfd475a 100644 --- a/www/content/docs/reference/createresource.mdx +++ b/www/content/docs/reference/createresource.mdx @@ -33,7 +33,7 @@ const resource = await drupal.createResource( - `options` - Optional - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - `deserialize: boolean`: Set to false to return the raw JSON:API response. diff --git a/www/content/docs/reference/deleteresource.mdx b/www/content/docs/reference/deleteresource.mdx index 8cc4ff2be..22520bda9 100644 --- a/www/content/docs/reference/deleteresource.mdx +++ b/www/content/docs/reference/deleteresource.mdx @@ -21,7 +21,7 @@ const deleted = await drupal.deleteResource( - The resource id. Example `a50ffee7-ba94-46c9-9705-f9f8f440db94`. - `options` - Optional - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. diff --git a/www/content/docs/reference/deserialize.mdx b/www/content/docs/reference/deserialize.mdx index a4a027947..5613f4e48 100644 --- a/www/content/docs/reference/deserialize.mdx +++ b/www/content/docs/reference/deserialize.mdx @@ -7,10 +7,10 @@ excerpt: A helper for deserializing JSON:API resources. const resource = drupal.deserialize(body, options?) ``` -- `body: JsonApiResponse` +- `body` - **Required** - The raw JSON:API response. -- `body` +- `options` - Optional - Options for the deserializer. @@ -18,7 +18,7 @@ const resource = drupal.deserialize(body, options?) ## Notes -- To provide your own custom deserializer, see the [serializer docs](/docs/serializer). +- To provide your own custom deserializer, see the [deserializer docs](/docs/deserializer). --- diff --git a/www/content/docs/reference/fetch.mdx b/www/content/docs/reference/fetch.mdx index 924b9fe63..304ada6ab 100644 --- a/www/content/docs/reference/fetch.mdx +++ b/www/content/docs/reference/fetch.mdx @@ -14,6 +14,11 @@ const response = await drupal.fetch(input, init?): Promise - Optional - The fetch options with `withAuth`. - If `withAuth` is set, `fetch` will fetch an `Authorization` header before making the request. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- diff --git a/www/content/docs/reference/getaccesstoken.mdx b/www/content/docs/reference/getaccesstoken.mdx index b63f81485..8e7773a12 100644 --- a/www/content/docs/reference/getaccesstoken.mdx +++ b/www/content/docs/reference/getaccesstoken.mdx @@ -4,19 +4,21 @@ excerpt: Retrieve an access token. --- ```ts -const token = await drupal.getAccessToken(options?: { +const token = await drupal.getAccessToken(clientIdSecret?: { clientId, clientSecret, - url? + url?, + scope? }): Promise ``` -- `options` +- `clientIdSecret` - Optional - - If options is not provided, `DrupalClient` will use the `clientId` and `clientSecret` configured in `auth`. + - If `clientIdSecret` is not provided, `NextDrupal` will use the `clientId` and `clientSecret` configured in `auth`. - `clientId: string`: The oauth client id. - `clientSecret: string`: The oauth client secret. - `url: string`: The oauth url. Default: `/oauth/token`. + - `scope: string` --- diff --git a/www/content/docs/reference/getauthorizationheader.mdx b/www/content/docs/reference/getauthorizationheader.mdx new file mode 100644 index 000000000..a776e06d1 --- /dev/null +++ b/www/content/docs/reference/getauthorizationheader.mdx @@ -0,0 +1,31 @@ +--- +title: getAuthorizationHeader +excerpt: Returns an authorization header based on an authentication method. +--- + +```ts +const paths = await drupal.getAuthorizationHeader( + auth +): Promise +``` + +- `auth: NextDrupalAuth` + - **Required** + - A supported authentication method. See [auth](/docs/authentication) + +--- + +## Examples + +- Auth method: `Bearer`. For this, you need a `clientId` and `clientSecret` + +```ts +const auth = { + clientId: process.env.DRUPAL_CLIENT_ID, + clientSecret: process.env.DRUPAL_CLIENT_SECRET, +} + +const authorizationHeader = await drupal.getAuthorizationHeader(auth) + +// authorizationHeader = Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjM ......... +``` diff --git a/www/content/docs/reference/getentryforresourcetype.mdx b/www/content/docs/reference/getentryforresourcetype.mdx deleted file mode 100644 index 25ac6248a..000000000 --- a/www/content/docs/reference/getentryforresourcetype.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: getEntryForResourceType -excerpt: Get the JSON:API entry for a resource type. ---- - -```ts -const url = await drupal.getEntryForResourceType(type, locale?): Promise -``` - -- `type: string` - - **Required** - - The resource type. Example: `node--article`. -- `locale: string` - - Optional - - The locale to fetch the index. Example: `es` or `fr`. - ---- - -## Notes - -By default, when retrieving resources in `getResource` or `getResourceCollection`, the `DrupalClient` make a request to Drupal to fetch the JSON:API resource entry.. - -Example: if you provide `node--article`, `DrupalClient` will make a request to `http://example.com/jsonapi/node/article`. - -If you would like to infer the entry from the resource type, use the [`useDefaultResourceTypeEntry`](/docs/configuration#usedefaultresourcetypeentry) option. - -```ts -const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { - useDefaultResourceTypeEntry: true, -}) -``` - ---- - -## Examples - -```ts -// https://example.com/jsonapi/node/article. -const url = await drupal.getEntryForResourceType(`node--article`) -``` diff --git a/www/content/docs/reference/getmenu.mdx b/www/content/docs/reference/getmenu.mdx index d598914e1..f3f4971a6 100644 --- a/www/content/docs/reference/getmenu.mdx +++ b/www/content/docs/reference/getmenu.mdx @@ -10,15 +10,17 @@ You need to install the [JSON:API Menu Items](https://www.drupal.org/project/jso
```ts -const resource = await drupal.getResource( - name, +const resource = await drupal.getMenu( + menuName, options?: { params, withAuth, deserialize, locale, defaultLocale, - withCache + withCache, + cacheKey, + next } ): Promise<{ items: T[] @@ -26,13 +28,13 @@ const resource = await drupal.getResource( }> ``` -- `name: string` +- `menuName: string` - **Required** - The name of the menu. Example: `main` or `footer`. - `options` - Optional - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - `deserialize: boolean`: Set to false to return the raw JSON:API response. @@ -40,14 +42,19 @@ const resource = await drupal.getResource( - `defaultLocale: string`: The default locale of the site. - `withCache: boolean`: Set `withCache` if you want to store and retrieve the menu from cache. - `cacheKey: string`: The cache key to use. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- ## Notes - `getMenu` returns: - - `items`: An array of `DrupalMenuLinkContent`. - - `tree`: An array of `DrupalMenuLinkContent` with children nested to match the hierarchy from Drupal. + - `items`: An array of `DrupalMenuItem`. + - `tree`: An array of `DrupalMenuItem` with children nested to match the hierarchy from Drupal. --- @@ -67,3 +74,19 @@ const menu = await drupal.getMenu("main", { cacheKey: "menu--main", }) ``` + + + +- Get the `main` menu with tag-based revalidation. + +```ts +const menu = await drupal.getMenu("main", { + next: { tags: ["main--menu"] }, // revalidates resource when calling `revalidateTag('main--menu')` +}) +``` diff --git a/www/content/docs/reference/getpathfromcontext.mdx b/www/content/docs/reference/getpathfromcontext.mdx deleted file mode 100644 index cb847abd4..000000000 --- a/www/content/docs/reference/getpathfromcontext.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: getPathFromContext -excerpt: Return the path (slug) from getStaticProps or getServerSideProps context. ---- - -```ts -const slug = drupal.getPathFromContext( - context, - options?: { - pathPrefix, - } -): string -``` - -- `context: GetStaticPropsContext | GetServerSidePropsContext` - - **Required** - - The context from `getStaticProps` or `getServerSideProps`. -- `options` - - Optional - - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. - ---- - -## Examples - -- Get the path (slug) from `getStaticProps` context. - -```ts -export async function getStaticProps(context) { - const slug = await drupal.getPathFromContext(context) -} -``` diff --git a/www/content/docs/reference/getresource.mdx b/www/content/docs/reference/getresource.mdx index 5d6a8a4be..dcceb2078 100644 --- a/www/content/docs/reference/getresource.mdx +++ b/www/content/docs/reference/getresource.mdx @@ -14,6 +14,7 @@ const resource = await drupal.getResource( locale, defaultLocale, withCache, + next } ): Promise ``` @@ -27,7 +28,7 @@ const resource = await drupal.getResource( - `options` - Optional - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - `deserialize: boolean`: Set to false to return the raw JSON:API response. @@ -35,6 +36,11 @@ const resource = await drupal.getResource( - `defaultLocale: string`: The default locale of the site. - `withCache: boolean`: Set `withCache` if you want to store and retrieve the resource from cache. - `cacheKey: string`: The cache key to use. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- @@ -79,12 +85,32 @@ const { data, meta, links } = await drupal.getResource( ```ts const id = "07464e9f-9221-4a4f-b7f2-01389408e6c8" -const menu = await drupal.getResource("node--article", id, { +const article = await drupal.getResource("node--article", id, { withCache: true, cacheKey: `node--article:${id}`, }) ``` +- Get a page resource with time-based revalidation. + +```ts +const id = "07464e9f-9221-4a4f-b7f2-01389408e6c8" + +const node = await drupal.getResource("node--page", id, { + next: { revalidate: 3600 }, // revalidate every hour +}) +``` + +- Get a page resource with tag-based revalidation. + +```ts +const id = "07464e9f-9221-4a4f-b7f2-01389408e6c8" + +const node = await drupal.getResource("node--page", id, { + next: { tags: ["page"] }, // revalidates resource when calling `revalidateTag('page')` +}) +``` + --- ## TypeScript diff --git a/www/content/docs/reference/getresourcebypath.mdx b/www/content/docs/reference/getresourcebypath.mdx index e94fe2a82..86c6450a9 100644 --- a/www/content/docs/reference/getresourcebypath.mdx +++ b/www/content/docs/reference/getresourcebypath.mdx @@ -13,6 +13,7 @@ const resource = await drupal.getResourceByPath( locale, defaultLocale, isVersionable, + next, } ): Promise ``` @@ -23,13 +24,18 @@ const resource = await drupal.getResourceByPath( - `options` - Optional - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the resource in. - `defaultLocale: string`: The default locale of the site. - `isVersionable: boolean`: Set to true if you're fetching the revision for a resource. _Automatically set to true for node entity types_. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- @@ -58,6 +64,31 @@ const { data, meta, links } = await drupal.getResourceByPath( ) ``` +- Get the `es` translation for a page. + +```ts +const node = await drupal.getResourceByPath("/blog/slug-for-article", { + locale: "es", + defaultLocale: "en", +}) +``` + +- Get a page resource by path with time-based revalidation. + +```ts +const node = await drupal.getResourceByPath("/blog/slug-for-article", { + next: { revalidate: 3600 }, // revalidate every hour +}) +``` + +- Get a page resource by path with tag-based revalidation. + +```ts +const node = await drupal.getResourceByPath("/blog/slug-for-article", { + next: { tags: ["page"] }, // revalidates resource when calling `revalidateTag('page')` +}) +``` + --- ## TypeScript diff --git a/www/content/docs/reference/getresourcecollection.mdx b/www/content/docs/reference/getresourcecollection.mdx index 99290e165..0ce08f9ed 100644 --- a/www/content/docs/reference/getresourcecollection.mdx +++ b/www/content/docs/reference/getresourcecollection.mdx @@ -12,6 +12,7 @@ const resource = await drupal.getResourceCollection( deserialize, locale, defaultLocale, + next, } ): Promise ``` @@ -28,6 +29,11 @@ const resource = await drupal.getResourceCollection( - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the resource in. - `defaultLocale: string`: The default locale of the site. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- @@ -57,6 +63,22 @@ const { data, meta, links } = await drupal.getResourceCollection("node--page", { }) ``` +- Get articles with time-based revalidation. + +```ts +const articles = await drupal.getResourceCollection("node--article", { + next: { revalidate: 3600 }, // revalidate every hour +}) +``` + +- Get articles with tag-based revalidation. + +```ts +const articles = await drupal.getResourceCollection("node--article", { + next: { tags: ["articles"] }, // revalidates resource when calling `revalidateTag('articles')` +}) +``` + --- ## TypeScript diff --git a/www/content/docs/reference/getresourcecollectionfromcontext.mdx b/www/content/docs/reference/getresourcecollectionfromcontext.mdx deleted file mode 100644 index 4a0714316..000000000 --- a/www/content/docs/reference/getresourcecollectionfromcontext.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: getResourceCollectionFromContext -excerpt: Fetch a collection of resources from getStaticProps or getServerSideProps context. ---- - -```ts -const resource = await drupal.getResourceCollectionFromContext( - type, - context, - options?: { - params, - withAuth, - deserialize, - locale, - defaultLocale, - } -): Promise -``` - -- `type: string` - - **Required** - - The resource type. Example: `node--article` or `user--user`. -- `context: GetStaticPropsContext | GetServerSidePropsContext` - - **Required** - - The context from `getStaticProps` or `getServerSideProps`. -- `options` - - Optional - - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: - - Set the authentication method to use. See the [authentication docs](/docs/authentication). - - Set to `true` to use the authentication method configured on the client. - - `deserialize: boolean`: Set to false to return the raw JSON:API response. - - `locale: string`: The locale to fetch the resource in. - - `defaultLocale: string`: The default locale of the site. - ---- - -## Notes - -- The localized resources will be fetched based on the `locale` and `defaultLocale` values from `context`. - ---- - -## Examples - -- Get all articles from context. - -```ts title=pages/[[...slug]].tsx -export async function getStaticProps(context) { - const articles = await drupal.getResourceCollectionFromContext( - "node--article", - context - ) - - return { - props: { - articles, - }, - } -} -``` - ---- - -## TypeScript - -- Using `DrupalNode` for a node entity type. - -```ts -import { DrupalNode } from "next-drupal" - -const nodes = await drupal.getResourceCollectionFromContext( - "node--article", - context -) -``` - -See the [TypeScript docs](/docs/typescript) for more built-in types. diff --git a/www/content/docs/reference/getresourcecollectionpathsegments.mdx b/www/content/docs/reference/getresourcecollectionpathsegments.mdx new file mode 100644 index 000000000..af4f22f6b --- /dev/null +++ b/www/content/docs/reference/getresourcecollectionpathsegments.mdx @@ -0,0 +1,99 @@ +--- +title: getResourceCollectionPathSegments +excerpt: Returns an array of Drupal path-related data that can be used to provide a static list for generateStaticParams. +--- + +```ts +const paths = await drupal.getResourceCollectionPathSegments( + types, + options?: { + params, + withAuth, + pathPrefix, + locale, + defaultLocale, + next, + + } +): Promise<{ + path: string + type: string + locale: Locale + segments: string[] + }[]> +``` + +- `types: string | string[]` + - **Required** + - The resource types. Example: `node--article` or `["taxonomy_term--tags", "user--user"]`. +- `options` + - Optional + - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. + - `withAuth: boolean | NextDrupalAuth`: + - Set the authentication method to use. See the [authentication docs](/docs/authentication). + - Set to `true` to use the authentication method configured on the client. + - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. + - `locale: string`: The locale to fetch the resource in. + - `defaultLocale: string`: The default locale of the site. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` + +--- + +## Examples + +- When used in `app/[...slug]/page.tsx` the `[...slug]` Dynamic Segment indicates that + `generateStaticParams()` is expected to return an array of objects with a `slug` property + containing an array of strings. + +```ts +export async function generateStaticParams(): Promise { + const resources = await drupal.getResourceCollectionPathSegments([ + "node--page", + "node--article", + ]) + + return resources.map((resource) => { + return { + slug: resource.segments, + } + }) +} +``` + +- When used in `app/[slug]/blog/[category]/[...slug]/page.tsx` file, `generateStaticParams()` + is expected to return an array of objects with a `lang` string, a `category` string and a `slug` array of strings. + +````ts +export async function generateStaticParams(): Promise { + const resources = await drupal.getResourceCollectionPathSegments( + ["node--article"], + { + // The pathPrefix will be removed from the returned path segments array. + pathPrefix: "/blog", + // The list of locales to return. + locales: ["en", "es"], + // The default locale. + defaultLocale: "en", + } + ); + + return resources.map((resource) => { + // NOTE: Because `pathPrefix` was set to "/blog", + // "blog" will not be included in the segments array. + + // Grab the first item from the segments array to get + // the needed "category" param. + const category = resource.segments.unshift(); + + return { + lang: resource.locale, + category, + slug: resource.segments, + }; + }) +}``` +```` diff --git a/www/content/docs/reference/getresourcefromcontext.mdx b/www/content/docs/reference/getresourcefromcontext.mdx deleted file mode 100644 index 347616a71..000000000 --- a/www/content/docs/reference/getresourcefromcontext.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: getResourceFromContext -excerpt: Fetch a resource from getStaticProps or getServerSideProps context. ---- - -```ts -const resource = await drupal.getResourceFromContext( - input, - context, - options?: { - params, - withAuth, - deserialize, - locale, - defaultLocale, - pathPrefix, - isVersionable, - } -): Promise -``` - -- `input: string | DrupalTranslatedPath` - - **Required** - - The resource type `node--article` or the translated path from `translatePathFromContext`. -- `context: GetStaticPropsContext | GetServerSidePropsContext` - - **Required** - - The context from `getStaticProps` or `getServerSideProps`. -- `options` - - Optional - - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: - - Set the authentication method to use. See the [authentication docs](/docs/authentication). - - Set to `true` to use the authentication method configured on the client. - - `deserialize: boolean`: Set to false to return the raw JSON:API response. - - `locale: string`: The locale to fetch the resource in. - - `defaultLocale: string`: The default locale of the site. - - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. - - `isVersionable: boolean`: Set to true if you're fetching the revision for a resource. _Automatically set to true for node entity types_. - ---- - -## Notes - -- The localized resource will be fetched based on the `locale` and `defaultLocale` values from `context`. - -- If you pass in a `DrupalTranslatedPath` for input, `getResourceFromContext` will take the `type` and `id` from the path and make a `getResource` call to Drupal. - -```ts -export async function getStaticProps(context) { - const path = await drupal.translatePathFromContext(context) - - const node = await drupal.getResourceFromContext(path, context) - - return { - props: { - node, - }, - } -} -``` - -- If you pass in a `string` inout, such as `node--article`, `getResourceFromContext` will make a subrequest call to Drupal to translate the path and then fetch the resource. - - You will need both the [Subrequests](https://drupal.org/project/subrequests) and [Decoupled Router](https://drupal.org/project/decoupled_router) modules. - -```ts -export async function getStaticProps(context) { - const node = await drupal.getResourceFromContext("node--article", context) - - return { - props: { - node, - }, - } -} -``` - ---- - -## Examples - -- Fetch a resource from context. - -```ts title=pages/[[...slug]].tsx -export async function getStaticProps(context) { - const node = await drupal.getResourceFromContext("node--page", context) - - return { - props: { - node, - }, - } -} -``` - -- Fetch a resource from context in a sub directory. - -```ts title=pages/articles/[[...slug]].tsx -export async function getStaticProps(context) { - const node = await drupal.getResourceFromContext("node--page", context, { - pathPrefix: "/articles", - }) - - return { - props: { - node, - }, - } -} -``` - ---- - -## TypeScript - -- Using `DrupalNode` for a node entity type. - -```ts -import { DrupalNode } from "next-drupal" - -const node = await drupal.getResourceFromContext( - "node--page", - context -) -``` - -- Using `DrupalTaxonomyTerm` for a taxonomy term entity type. - -```ts -import { DrupalTaxonomyTerm } from "next-drupal" - -const term = await drupal.getResourceFromContext( - "taxonomy_term--tags", - context -) -``` - -See the [TypeScript docs](/docs/typescript) for more built-in types. diff --git a/www/content/docs/reference/getsearch.mdx b/www/content/docs/reference/getsearch.mdx index 4eef21ad3..146659f2d 100644 --- a/www/content/docs/reference/getsearch.mdx +++ b/www/content/docs/reference/getsearch.mdx @@ -18,6 +18,7 @@ const resources = await drupal.getSearchIndex( deserialize, locale, defaultLocale, + next } ): Promise ``` @@ -34,6 +35,11 @@ const resources = await drupal.getSearchIndex( - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the view in. - `defaultLocale: string`: The default locale of the site. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- diff --git a/www/content/docs/reference/getstaticpathsfromcontext.mdx b/www/content/docs/reference/getstaticpathsfromcontext.mdx deleted file mode 100644 index 165fba37b..000000000 --- a/www/content/docs/reference/getstaticpathsfromcontext.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: getStaticPathsFromContext -excerpt: Return paths for getStaticPaths. ---- - -```ts -const paths = await drupal.getStaticPathsFromContext( - types, - context, - options?: { - params, - withAuth, - pathPrefix, - } -): Promise["paths"]> -``` - -- `types: string | string[]` - - **Required** - - The resource types. Example: `node--article` or `["taxonomy_term--tags", "user--user"]`. -- `context: GetStaticPathsContext` - - **Required** - - The context from `getStaticPaths`. -- `options` - - Optional - - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: - - Set the authentication method to use. See the [authentication docs](/docs/authentication). - - Set to `true` to use the authentication method configured on the client. - - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. - ---- - -## Examples - -- Return static paths for `node--page` resources. - -```ts -export async function getStaticPaths(context) { - return { - paths: await drupal.getStaticPathsFromContext("node--page", context), - fallback: "blocking", - } -} -``` - -- Return static paths for `node--page` and `node--article` resources. - -```ts -export async function getStaticPaths(context) { - return { - paths: await drupal.getStaticPathsFromContext( - ["node--page", "node--article"], - context - ), - fallback: "blocking", - } -} -``` diff --git a/www/content/docs/reference/getview.mdx b/www/content/docs/reference/getview.mdx index f16eddeb6..d1a337156 100644 --- a/www/content/docs/reference/getview.mdx +++ b/www/content/docs/reference/getview.mdx @@ -18,6 +18,7 @@ const view = await drupal.getView( deserialize, locale, defaultLocale, + next } ): Promise> ``` @@ -34,6 +35,11 @@ const view = await drupal.getView( - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the view in. - `defaultLocale: string`: The default locale of the site. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- @@ -57,6 +63,22 @@ const view = await drupal.getView("articles--promoted", { }) ``` +- Get a view with time-based revalidation. + +```ts +const view = await drupal.getView("articles--promoted", { + next: { revalidate: 3600 }, // revalidate every hour` +}) +``` + +- Get a view with tag-based revalidation. + +```ts +const view = await drupal.getView("articles--promoted", { + next: { tags: ["article-view"] }, // revalidates resource when calling `revalidateTag('article-view')` +}) +``` + --- ## TypeScript diff --git a/www/content/docs/reference/preview.mdx b/www/content/docs/reference/preview.mdx deleted file mode 100644 index f5ef8b677..000000000 --- a/www/content/docs/reference/preview.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: preview -excerpt: Handle preview mode for resources. ---- - -```ts -await drupal.preview(request, response, options?: { - errorMessages?: { - secret, - slug, - } -}): Promise -``` - -- `request: NextApiRequest` - - **Required** - - The `request` from an API route. -- `response: NextApiResponse` - - **Required** - - The `response` from an API route. -- `options` - - Optional - - `errorMessages`: - - `secret`: The error message to display for an invalid secret. - - `slug`: The error message to display for an invalid slug. - ---- - -## Notes - -- The `preview` method should be called in an API route. - ---- - -## Examples - -```ts title=pages/api/preview.ts -import { drupal } from "lib/drupal" - -export default async function handler(req, res) { - return await drupal.preview(req, res) -} -``` diff --git a/www/content/docs/reference/translatepath.mdx b/www/content/docs/reference/translatepath.mdx index 84aa0f53d..0613f510d 100644 --- a/www/content/docs/reference/translatepath.mdx +++ b/www/content/docs/reference/translatepath.mdx @@ -8,8 +8,9 @@ const path = await drupal.translatePath( path, options?: { withAuth, + next } -): Promise +): Promise ``` - `path: string` @@ -17,9 +18,14 @@ const path = await drupal.translatePath( - The resource path. Example: `/blog/slug-for-article`. - `options` - Optional - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. + - `next: NextFetchRequestConfig` + - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). + Ex: `next: { revalidate: 3600 } // revalidate resource every hour` + - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). + Ex: `next: { tags: ['resource-tag'] }` --- diff --git a/www/content/docs/reference/translatepathfromcontext.mdx b/www/content/docs/reference/translatepathfromcontext.mdx deleted file mode 100644 index d78233315..000000000 --- a/www/content/docs/reference/translatepathfromcontext.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: translatePathFromContext -excerpt: Fetch info about a Drupal path from getStaticProps or getServerSideProps context. ---- - -```ts -const path = await drupal.translatePathFromContext( - context, - options?: { - withAuth, - pathPrefix, - } -): Promise -``` - -- `context: GetStaticPropsContext | GetServerSidePropsContext` - - **Required** - - The context from `getStaticProps` or `getServerSideProps`. -- `options` - - Optional - - `withAuth: boolean | DrupalClientAuth`: - - Set the authentication method to use. See the [authentication docs](/docs/authentication). - - Set to `true` to use the authentication method configured on the client. - - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. - ---- - -## Notes - -- The [Decoupled Router](https://drupal.org/project/decoupled_router) module is required. - ---- - -## Examples - -- Get info about a path from `getStaticProps` context. - -```ts -export async function getStaticProps(context) { - const path = await drupal.translatePathFromContext(context) -} -``` diff --git a/www/content/docs/reference/updateresource.mdx b/www/content/docs/reference/updateresource.mdx index db26de983..e46cf8be8 100644 --- a/www/content/docs/reference/updateresource.mdx +++ b/www/content/docs/reference/updateresource.mdx @@ -28,7 +28,7 @@ const resource = await drupal.updateResource( - `options` - Optional - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. - - `withAuth: boolean | DrupalClientAuth`: + - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - `deserialize: boolean`: Set to false to return the raw JSON:API response. diff --git a/www/content/docs/serializer.mdx b/www/content/docs/serializer.mdx deleted file mode 100644 index 1afd0bea2..000000000 --- a/www/content/docs/serializer.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Serializer -excerpt: Using a custom serializer with DrupalClient. ---- - -The `DrupalClient` uses [jsona](https://github.com/olosegres/jsona) as the default serializer for serializing and deserializing JSON:API data. - -You can provide your own using the [`serializer`](/docs/client/configuration#serializer) option. - ---- - -## Example - -Here's how you can replace the default serializer with [jsonapi-serializer](https://github.com/SeyZ/jsonapi-serializer). - -```ts title=lib/drupal.ts -import { DrupalClient } from "next-drupal" -import { Deserializer } from "jsonapi-serializer" - -// Create a custom serializer. -const customSerializer = new Deserializer({ - keyForAttribute: "camelCase", -}) - -// Pass the custom serializer to the client. -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - serializer: customSerializer, - } -) -``` diff --git a/www/content/docs/typescript.mdx b/www/content/docs/typescript.mdx index de8b06134..12f29fe7c 100644 --- a/www/content/docs/typescript.mdx +++ b/www/content/docs/typescript.mdx @@ -1,9 +1,9 @@ --- title: TypeScript -excerpt: Using built-in types with DrupalClient. +excerpt: Using built-in types with NextDrupal client. --- -Every helper method for the `DrupalClient` has full TypeScript support. +Every helper method for the `NextDrupal` client has full TypeScript support. The `next-drupal` module ships with some default basic types you can use. @@ -132,10 +132,10 @@ export interface DrupalParagraph extends JsonApiResource { --- -### PathAlias +### DrupalPathAlias ```ts -export type PathAlias = { +export type DrupalPathAlias = { alias: string pid: number langcode: string @@ -144,18 +144,18 @@ export type PathAlias = { --- -### DrupalMenuLinkContent +### DrupalMenuItem ```ts -export interface DrupalMenuLinkContent { +export interface DrupalMenuItem { description: string enabled: boolean expanded: boolean - id: string + id: DrupalMenuItemId menu_name: string meta: Record options: Record - parent: string + parent: DrupalMenuItemId provider: string route: { name: string @@ -165,8 +165,10 @@ export interface DrupalMenuLinkContent { type: string url: string weight: string - items?: DrupalMenuLinkContent[] + items?: DrupalMenuItem[] } + +export type DrupalMenuItemId = string ``` --- @@ -204,6 +206,33 @@ export interface DrupalTranslatedPath { --- +### DrupalSearchApiJsonApiResponse + +```ts +export interface DrupalSearchApiJsonApiResponse extends JsonApiResponse { + meta: JsonApiResponse["meta"] & { + facets?: DrupalSearchApiFacet[] + } +} + +export interface DrupalSearchApiFacet { + id: string + label?: string + path?: string + terms?: { + url: string + values: { + value: string + label: string + active?: boolean + count?: number + } + }[] +} +``` + +--- + ## Extending Types To extend the built-in types, create a file at `types/drupal.d.ts` and extend the types as follows. diff --git a/www/content/docs/updating-resources.mdx b/www/content/docs/updating-resources.mdx index f1d6f4e9a..2032e2328 100644 --- a/www/content/docs/updating-resources.mdx +++ b/www/content/docs/updating-resources.mdx @@ -1,6 +1,6 @@ --- title: Updating Resources (PATCH) -excerpt: How to update JSON:API resources using DrupalClient. +excerpt: How to update JSON:API resources using NextDrupal client. --- @@ -9,13 +9,23 @@ The `updateResource` helper is available in `next-drupal ^1.4.0`. -The `DrupalClient` ships with a `updateResource` method for updating JSON:API resources. + + +If you're working with JSON:API, be mindful to select the option: + +`Accept all JSON:API create, read, update, and delete operations.` + +on the following path: `/admin/config/services/jsonapi` on Drupal. + + + +The `NextDrupal` client ships with a `updateResource` method for updating JSON:API resources. --- ## updateResource -### Update Resource +#### Update Resource ```ts const article = await drupal.updateResource( @@ -31,7 +41,7 @@ const article = await drupal.updateResource( ) ``` -### Update Resource with Relationships +#### Update Resource with Relationships ```ts const article = await drupal.updateResource( diff --git a/www/content/guides/jsonapi-params.mdx b/www/content/guides/jsonapi-params.mdx index 903fa9508..f3f7419b5 100644 --- a/www/content/guides/jsonapi-params.mdx +++ b/www/content/guides/jsonapi-params.mdx @@ -21,18 +21,17 @@ yarn add drupal-jsonapi-params import { DrupalNode } from "next-drupal" import { DrupalJsonApiParams } from "drupal-jsonapi-params" -export async function getStaticProps(context) { +export default async function ArticlePage() { // highlight-start const params = new DrupalJsonApiParams() - .addFields("node--blog_post", ["title", "path", "body", "uid"]) + .addFields("node--article", ["title", "path", "body", "uid"]) .addFilter("status", "1") .addInclude(["uid.user_picture"]) .addSort("created", "DESC") // highlight-end - const articles = await drupal.getResourceCollectionFromContext( + const article = await drupal.getResourceCollection( "node--article", - context, { params: params.getQueryObject(), // highlight-line } diff --git a/www/content/tutorials/preview-mode/configure-content-types.mdx b/www/content/tutorials/draft-mode/configure-content-types.mdx similarity index 100% rename from www/content/tutorials/preview-mode/configure-content-types.mdx rename to www/content/tutorials/draft-mode/configure-content-types.mdx diff --git a/www/content/tutorials/preview-mode/configure-preview-routes.mdx b/www/content/tutorials/draft-mode/configure-preview-routes.mdx similarity index 100% rename from www/content/tutorials/preview-mode/configure-preview-routes.mdx rename to www/content/tutorials/draft-mode/configure-preview-routes.mdx diff --git a/www/content/tutorials/preview-mode/create-oauth-client.mdx b/www/content/tutorials/draft-mode/create-oauth-client.mdx similarity index 100% rename from www/content/tutorials/preview-mode/create-oauth-client.mdx rename to www/content/tutorials/draft-mode/create-oauth-client.mdx diff --git a/www/content/tutorials/preview-mode/create-site.mdx b/www/content/tutorials/draft-mode/create-site.mdx similarity index 100% rename from www/content/tutorials/preview-mode/create-site.mdx rename to www/content/tutorials/draft-mode/create-site.mdx diff --git a/www/content/tutorials/preview-mode/done.mdx b/www/content/tutorials/draft-mode/done.mdx similarity index 100% rename from www/content/tutorials/preview-mode/done.mdx rename to www/content/tutorials/draft-mode/done.mdx diff --git a/www/content/tutorials/draft-mode/index.mdx b/www/content/tutorials/draft-mode/index.mdx new file mode 100644 index 000000000..23ebdb68b --- /dev/null +++ b/www/content/tutorials/draft-mode/index.mdx @@ -0,0 +1,10 @@ +--- +title: Draft Mode +excerpt: Enable draft mode for content types. +weight: 100 +group: Draft Mode +--- + +The Next.js module, paired with the `next-drupal` plugin, makes it easy to create [Next.js draft routes](https://nextjs.org/docs/app/building-your-application/configuring/draft-mode). + +To handle draft routes, we need to create a Next.js site on Drupal and configure authentication. diff --git a/www/content/tutorials/on-demand-revalidation/index.mdx b/www/content/tutorials/on-demand-revalidation/index.mdx index c8a7f329b..b6966acf1 100644 --- a/www/content/tutorials/on-demand-revalidation/index.mdx +++ b/www/content/tutorials/on-demand-revalidation/index.mdx @@ -5,6 +5,6 @@ weight: 300 group: On-demand Revalidation --- -[On-demand Revalidation](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration#on-demand-revalidation) makes it easy to update your Next.js site when content on Drupal is created, updated or deleted. +[On-demand Revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation) makes it easy to update your Next.js site when content on Drupal is created, updated or deleted. Starting with `v1.6.0`, Next.js for Drupal supports On-demand Revalidation configurable per entity types. diff --git a/www/content/tutorials/preview-mode/index.mdx b/www/content/tutorials/preview-mode/index.mdx deleted file mode 100644 index efa24661e..000000000 --- a/www/content/tutorials/preview-mode/index.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Preview Mode -excerpt: Enable preview mode for content types. -weight: 100 -group: Preview Mode ---- - -The Next.js module, paired with the `next-drupal` plugin, makes it easy to create [Next.js preview routes](https://nextjs.org/docs/advanced-features/preview-mode). - -To handle preview routes, we need to create a Next.js site on Drupal and configure authentication. diff --git a/www/next.config.js b/www/next.config.js index c68883db7..47b3c7b7f 100644 --- a/www/next.config.js +++ b/www/next.config.js @@ -48,8 +48,8 @@ module.exports = { permanent: true, }, { - source: "/docs/client/serializer", - destination: "/docs/serializer", + source: "/docs/client/deserializer", + destination: "/docs/deserializer", permanent: true, }, { @@ -74,7 +74,7 @@ module.exports = { }, { source: "/docs/client/preview-mode", - destination: "/docs/preview-mode", + destination: "/docs/draft-mode", permanent: true, }, { From 6c0e38950320143fd2bdf9fb3bf463d14f65fe86 Mon Sep 17 00:00:00 2001 From: Marco Monti Date: Thu, 11 Jul 2024 10:41:50 +0200 Subject: [PATCH 2/3] docs(next-drupal): updated learn section --- .../draft-mode/configure-content-types.mdx | 10 ++--- .../draft-mode/configure-draft-routes.mdx | 39 +++++++++++++++++ .../draft-mode/configure-preview-routes.mdx | 43 ------------------- .../draft-mode/create-oauth-client.mdx | 27 ++++++------ .../tutorials/draft-mode/create-site.mdx | 8 ++-- www/content/tutorials/draft-mode/done.mdx | 4 +- www/content/tutorials/graphql/index.mdx | 2 +- .../configure-entity-types.mdx | 10 +++++ .../configure-revalidate-route.mdx | 37 ++++++++-------- .../quick-start/configure-path-aliases.mdx | 2 +- www/content/tutorials/quick-start/index.mdx | 2 +- 11 files changed, 93 insertions(+), 91 deletions(-) create mode 100644 www/content/tutorials/draft-mode/configure-draft-routes.mdx delete mode 100644 www/content/tutorials/draft-mode/configure-preview-routes.mdx diff --git a/www/content/tutorials/draft-mode/configure-content-types.mdx b/www/content/tutorials/draft-mode/configure-content-types.mdx index 0efbe0588..1bb3ab761 100644 --- a/www/content/tutorials/draft-mode/configure-content-types.mdx +++ b/www/content/tutorials/draft-mode/configure-content-types.mdx @@ -2,20 +2,20 @@ title: Configure Content Types excerpt: Configure preview for content types weight: 150 -group: Preview Mode +group: Draft Mode --- -Next, we need to configure preview mode for the content types. This will display an inline preview in an iframe when you visit the content pages. +Next, we need to configure draft mode for the content types. This will display an inline draft in an iframe when you visit the content pages. --- -## Configure Preview +## Configure Draft -To enable content preview inside Drupal, we need to configure a site resolver for the **Article** content type. +To enable content draft inside Drupal, we need to configure a site resolver for the **Article** content type. -A _site resolver_ tells Drupal how to resolve the preview URL for an entity. +A _site resolver_ tells Drupal how to resolve the draft URL for an entity. diff --git a/www/content/tutorials/draft-mode/configure-draft-routes.mdx b/www/content/tutorials/draft-mode/configure-draft-routes.mdx new file mode 100644 index 000000000..b10eee73e --- /dev/null +++ b/www/content/tutorials/draft-mode/configure-draft-routes.mdx @@ -0,0 +1,39 @@ +--- +title: Configure Draft Routes +excerpt: Draft routes in Next.js +weight: 140 +group: Draft Mode +--- + +Implement draft mode using two API routes. + + + +If you're using the Basic Starter, draft routes are already created for you. + + + +## /app/api/draft/route.ts + +```ts title=app/api/draft/route.ts +import { drupal } from "@/lib/drupal" +import { enableDraftMode } from "next-drupal/draft" +import type { NextRequest } from "next/server" + +export async function GET(request: NextRequest): Promise { + return enableDraftMode(request, drupal) +} +``` + +--- + +## /app/api/disable-draft/route.ts + +```ts title=app/api/disable-draft/route.ts +import { disableDraftMode } from "next-drupal/draft" +import type { NextRequest } from "next/server" + +export async function GET(request: NextRequest) { + return disableDraftMode() +} +``` diff --git a/www/content/tutorials/draft-mode/configure-preview-routes.mdx b/www/content/tutorials/draft-mode/configure-preview-routes.mdx deleted file mode 100644 index e49d7b3fd..000000000 --- a/www/content/tutorials/draft-mode/configure-preview-routes.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Configure Preview Routes -excerpt: Preview routes in Next.js -weight: 140 -group: Preview Mode ---- - -Implement preview mode using two API routes. - - - -If you're using the Basic Starter, preview routes are already created for you. - - - -## /pages/api/preview.ts - -```ts title=pages/api/preview.ts -import { NextApiRequest, NextApiResponse } from "next" - -import { drupal } from "lib/drupal" - -export default async function handler( - request: NextApiRequest, - response: NextApiResponse -) { - return await drupal.preview(request, response) -} -``` - ---- - -## /pages/api/exit-preview.ts - -```ts title=pages/api/exit-preview.ts -import { NextApiResponse } from "next" - -export default function exit(_, response: NextApiResponse) { - response.clearPreviewData() - response.writeHead(307, { Location: "/" }) - response.end() -} -``` diff --git a/www/content/tutorials/draft-mode/create-oauth-client.mdx b/www/content/tutorials/draft-mode/create-oauth-client.mdx index 7bb38b660..3983f9698 100644 --- a/www/content/tutorials/draft-mode/create-oauth-client.mdx +++ b/www/content/tutorials/draft-mode/create-oauth-client.mdx @@ -2,7 +2,7 @@ title: Create OAuth Client excerpt: Setup an OAuth client to be used for authenticated content. weight: 110 -group: Preview Mode +group: Draft Mode --- Before we can create an OAuth consumer, we need to create a new role and a user for OAuth scopes. @@ -38,7 +38,7 @@ We are assigning the _Bypass content access control_ permission to allow Next.js This scope is only going to be used when making authenticated requests from Next.js to Drupal. ```ts -const articles = await drupal.getResource( +const article = await drupal.getResource( "node--article", "dad82fe9-f2b7-463e-8c5f-02f73018d6cb", // highlight-start @@ -108,20 +108,17 @@ DRUPAL_CLIENT_SECRET= --- -## 7. Update DrupalClient +## 7. Update NextDrupal client. -Update the `DrupalClient` to use the **Bearer** authentication header. +Update the `NextDrupal` to use the **Bearer** authentication header. ```ts title=lib/drupal.ts -import { DrupalClient } from "next-drupal" - -export const drupal = new DrupalClient( - process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, - { - auth: { - clientId: process.env.DRUPAL_CLIENT_ID, - clientSecret: process.env.DRUPAL_CLIENT_SECRET, - }, - } -) +import { NextDrupal } from "next-drupal" + +export const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + auth: { + clientId: process.env.DRUPAL_CLIENT_ID, + clientSecret: process.env.DRUPAL_CLIENT_SECRET, + }, +}) ``` diff --git a/www/content/tutorials/draft-mode/create-site.mdx b/www/content/tutorials/draft-mode/create-site.mdx index fcc43a8f8..000616f19 100644 --- a/www/content/tutorials/draft-mode/create-site.mdx +++ b/www/content/tutorials/draft-mode/create-site.mdx @@ -2,10 +2,10 @@ title: Create Next.js site excerpt: Create a Next.js site on Drupal weight: 105 -group: Preview Mode +group: Draft Mode --- -Start by creating a Next.js site so that we can render the preview on Drupal. +Start by creating a Next.js site so that we can render the draft on Drupal. 1. Visit `/admin/config/services/next`. 2. Click **Add Next.js site**. @@ -13,8 +13,8 @@ Start by creating a Next.js site so that we can render the preview on Drupal. - **Label**: `Next.js` - **Base URL**: `http://localhost:3000` -- **Preview URL**: `http://localhost:3000/api/preview` -- **Preview secret**: `secret` +- **Draft URL (or Preview URL)**: `http://localhost:3000/api/draft` +- **Secret key**: `secret` diff --git a/www/content/tutorials/draft-mode/done.mdx b/www/content/tutorials/draft-mode/done.mdx index 19ff28660..a350ab534 100644 --- a/www/content/tutorials/draft-mode/done.mdx +++ b/www/content/tutorials/draft-mode/done.mdx @@ -1,10 +1,10 @@ --- title: Done weight: 160 -group: Preview Mode +group: Draft Mode --- -Congratulations. You have successfully configured preview mode for your content types. +Congratulations. You have successfully configured draft mode for your content types. You should see the iframe preview when you visit your content pages. diff --git a/www/content/tutorials/graphql/index.mdx b/www/content/tutorials/graphql/index.mdx index 6d1264202..a1659dc65 100644 --- a/www/content/tutorials/graphql/index.mdx +++ b/www/content/tutorials/graphql/index.mdx @@ -5,7 +5,7 @@ weight: 10 group: Quick Start (GraphQL) --- -This tutorial will help you get started with Next.js for Drupal using the [`DrupalClient`](/docs/client) and **GraphQL**. +This tutorial will help you get started with Next.js for Drupal using the [`NextDrupal`](/docs/client) and **GraphQL**. diff --git a/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx b/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx index 3cbc86819..79d463919 100644 --- a/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx +++ b/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx @@ -5,6 +5,16 @@ weight: 350 group: On-demand Revalidation --- + + Next, we need to configure on-demand revalidation for the entity types. To enable on-demand revalidation for an entity type, we need to configure a **revalidator** plugin. diff --git a/www/content/tutorials/on-demand-revalidation/configure-revalidate-route.mdx b/www/content/tutorials/on-demand-revalidation/configure-revalidate-route.mdx index 63bf6f073..303611bb8 100644 --- a/www/content/tutorials/on-demand-revalidation/configure-revalidate-route.mdx +++ b/www/content/tutorials/on-demand-revalidation/configure-revalidate-route.mdx @@ -5,7 +5,7 @@ weight: 360 group: On-demand Revalidation --- -Implement on-demand revalidation using an API routes at `/revalidate`. +Implement on-demand revalidation using an API route at `/revalidate`. @@ -13,36 +13,35 @@ If you're using the Basic Starter, revalidate route are already created for you. -## /pages/api/revalidate.ts +## /app/api/revalidate/route.ts -```ts title=pages/api/revalidate.ts -import { NextApiRequest, NextApiResponse } from "next" +```ts title=app/api/revalidate/route.ts +import { revalidatePath } from "next/cache" +import type { NextRequest } from "next/server" -export default async function handler( - request: NextApiRequest, - response: NextApiResponse -) { - let slug = request.query.slug as string - const secret = request.query.secret as string +async function handler(request: NextRequest) { + const searchParams = request.nextUrl.searchParams + const path = searchParams.get("path") + const secret = searchParams.get("secret") // Validate secret. if (secret !== process.env.DRUPAL_REVALIDATE_SECRET) { - return response.status(401).json({ message: "Invalid secret." }) + return new Response("Invalid secret.", { status: 401 }) } - // Validate slug. - if (!slug) { - return response.status(400).json({ message: "Invalid slug." }) + // Validate path. + if (!path) { + return new Response("Invalid path.", { status: 400 }) } try { - await response.revalidate(slug) + revalidatePath(path) - return response.json({}) + return new Response("Revalidated.") } catch (error) { - return response.status(404).json({ - message: error.message, - }) + return new Response((error as Error).message, { status: 500 }) } } + +export { handler as GET, handler as POST } ``` diff --git a/www/content/tutorials/quick-start/configure-path-aliases.mdx b/www/content/tutorials/quick-start/configure-path-aliases.mdx index e73b89d9a..86f9b4dfe 100644 --- a/www/content/tutorials/quick-start/configure-path-aliases.mdx +++ b/www/content/tutorials/quick-start/configure-path-aliases.mdx @@ -5,7 +5,7 @@ weight: 50 group: Quick Start --- -The `next-drupal` plugin uses paths to resolve resources for `getStaticProps`. To make this work, we need to configure path aliases for our content types. +The `next-drupal` plugin uses paths to resolve resources for the Next.js Frontend. To make this work, we need to configure path aliases for our content types. Let's add a pattern for the **Article** content type. diff --git a/www/content/tutorials/quick-start/index.mdx b/www/content/tutorials/quick-start/index.mdx index e777be58a..3c719d080 100644 --- a/www/content/tutorials/quick-start/index.mdx +++ b/www/content/tutorials/quick-start/index.mdx @@ -5,7 +5,7 @@ weight: 10 group: Quick Start --- -This tutorial will help you get started with Next.js for Drupal using the [`DrupalClient`](/docs/client) and **JSON:API**. +This tutorial will help you get started with Next.js for Drupal using the [`NextDrupal`](/docs/client) and **JSON:API**. From 239b578e86be352bb5e09e5ce17f2730d218c0b2 Mon Sep 17 00:00:00 2001 From: Marco Monti Date: Mon, 9 Sep 2024 12:34:23 +0200 Subject: [PATCH 3/3] docs(next-drupal): requested changes --- www/config/docs.ts | 2 +- www/content/docs/authentication.mdx | 8 - www/content/docs/cache.mdx | 10 +- www/content/docs/client.mdx | 4 +- www/content/docs/configuration.mdx | 18 +-- www/content/docs/creating-resources.mdx | 4 +- www/content/docs/deleting-resources.mdx | 2 +- www/content/docs/fetcher.mdx | 2 +- www/content/docs/fetching-resources.mdx | 7 - www/content/docs/pages.mdx | 21 ++- .../{buildEndpoint.mdx => buildendpoint.mdx} | 25 +++- www/content/docs/reference/fetch.mdx | 12 +- .../reference/getentryforresourcetype.mdx | 40 +++++ www/content/docs/reference/getmenu.mdx | 13 +- .../docs/reference/getpathfromcontext.mdx | 32 ++++ www/content/docs/reference/getresource.mdx | 13 +- .../docs/reference/getresourcebypath.mdx | 13 +- .../docs/reference/getresourcecollection.mdx | 13 +- .../getresourcecollectionfromcontext.mdx | 78 ++++++++++ .../getresourcecollectionpathsegments.mdx | 7 - .../docs/reference/getresourcefromcontext.mdx | 138 ++++++++++++++++++ www/content/docs/reference/getsearch.mdx | 6 - .../reference/getstaticpathsfromcontext.mdx | 59 ++++++++ www/content/docs/reference/getview.mdx | 22 --- www/content/docs/reference/preview.mdx | 43 ++++++ www/content/docs/reference/translatepath.mdx | 6 - .../reference/translatepathfromcontext.mdx | 42 ++++++ www/content/docs/serializer.mdx | 32 ++++ .../tutorials/draft-mode/create-site.mdx | 2 +- .../configure-entity-types.mdx | 10 -- www/content/tutorials/quick-start/index.mdx | 2 +- 31 files changed, 540 insertions(+), 146 deletions(-) rename www/content/docs/reference/{buildEndpoint.mdx => buildendpoint.mdx} (72%) create mode 100644 www/content/docs/reference/getentryforresourcetype.mdx create mode 100644 www/content/docs/reference/getpathfromcontext.mdx create mode 100644 www/content/docs/reference/getresourcecollectionfromcontext.mdx create mode 100644 www/content/docs/reference/getresourcefromcontext.mdx create mode 100644 www/content/docs/reference/getstaticpathsfromcontext.mdx create mode 100644 www/content/docs/reference/preview.mdx create mode 100644 www/content/docs/reference/translatepathfromcontext.mdx create mode 100644 www/content/docs/serializer.mdx diff --git a/www/config/docs.ts b/www/config/docs.ts index b4f70cb01..1bdbed9d7 100644 --- a/www/config/docs.ts +++ b/www/config/docs.ts @@ -162,7 +162,7 @@ export const docsConfig: DocsConfig = { }, { title: "buildEndpoint", - href: "/docs/reference/buildEndpoint", + href: "/docs/reference/buildendpoint", }, { title: "getAccessToken", diff --git a/www/content/docs/authentication.mdx b/www/content/docs/authentication.mdx index 89df6e708..76b5c6f10 100644 --- a/www/content/docs/authentication.mdx +++ b/www/content/docs/authentication.mdx @@ -177,14 +177,6 @@ const articles = await drupal.getResourceCollection("node--article", { If you're using [NextAuth](https://next-auth.js.org) you can use the results from `getSession`: - - ```ts import { getSession } from "next-auth/react" diff --git a/www/content/docs/cache.mdx b/www/content/docs/cache.mdx index 99b7f51ac..9089eadde 100644 --- a/www/content/docs/cache.mdx +++ b/www/content/docs/cache.mdx @@ -3,7 +3,7 @@ title: Caching excerpt: Using a custom cache for resources. --- -The `NextDrupal` has support for caching resources. +The `NextDrupal` client has support for caching resources. This is handy when dealing with global data: you can fetch data once and re-use during builds. @@ -11,14 +11,6 @@ You can provide your own cache implementation using the [`cache`](/docs/configur --- - - ## Example Here's an example on how you can use Redis to cache resources. diff --git a/www/content/docs/client.mdx b/www/content/docs/client.mdx index ed25b0a74..5e6290805 100644 --- a/www/content/docs/client.mdx +++ b/www/content/docs/client.mdx @@ -3,9 +3,9 @@ title: NextDrupal Client excerpt: A powerful JSON:API client for Drupal. --- -The `NextDrupal` is a powerful JSON:API client that ships with helpers for working with Drupal data. +The `NextDrupal` client is a powerful JSON:API client that ships with helpers for working with Drupal data. -You can use the `NextDrupal` client to fetch JSON:API data from Drupal to build static pages. +You can use the `NextDrupal` client to fetch JSON:API data from Drupal to build static pages in advance, or server render pages on-demand. It also comes with full support for JSON:API write operations which means you can create JSON:API resources from Next.js to Drupal. diff --git a/www/content/docs/configuration.mdx b/www/content/docs/configuration.mdx index 26c3b21e9..3e5293afa 100644 --- a/www/content/docs/configuration.mdx +++ b/www/content/docs/configuration.mdx @@ -5,7 +5,7 @@ excerpt: Initialization and options for NextDrupal client. ## Initialization -To create a new `NextDrupal`, use the following initialization: +To create a new `NextDrupal` client, use the following initialization: ```ts import { NextDrupal } from "next-drupal" @@ -125,14 +125,6 @@ You can find more info about using a custom fetcher [here](/docs/fetcher). ### cache - - - **Default value**: `null` - **Required**: No @@ -181,14 +173,6 @@ Set whether the client should use authenticated requests by default. If set to ` --- - - ### headers - **Default value**: `{ "Content-Type": "application/vnd.api+json", Accept: "application/vnd.api+json" }` diff --git a/www/content/docs/creating-resources.mdx b/www/content/docs/creating-resources.mdx index bd3719410..d3e56379c 100644 --- a/www/content/docs/creating-resources.mdx +++ b/www/content/docs/creating-resources.mdx @@ -15,11 +15,11 @@ If you're working with JSON:API, be mindful to select the option: `Accept all JSON:API create, read, update, and delete operations.` -on the following path: `/admin/config/services/jsonapi` on Drupal. +on the following path: `/admin/config/services/jsonapi` in Drupal. -The `NextDrupal` client ships with a `createResource` and a `createFileResource` methods for creating JSON:API resources. +The `NextDrupal` client ships with `createResource` and `createFileResource` methods for creating JSON:API resources. --- diff --git a/www/content/docs/deleting-resources.mdx b/www/content/docs/deleting-resources.mdx index 79a55e994..473180f52 100644 --- a/www/content/docs/deleting-resources.mdx +++ b/www/content/docs/deleting-resources.mdx @@ -15,7 +15,7 @@ If you're working with JSON:API, be mindful to select the option: `Accept all JSON:API create, read, update, and delete operations.` -on the following path: `/admin/config/services/jsonapi` on Drupal. +on the following path: `/admin/config/services/jsonapi` in Drupal. diff --git a/www/content/docs/fetcher.mdx b/www/content/docs/fetcher.mdx index e124e5cb4..99cc4ffb4 100644 --- a/www/content/docs/fetcher.mdx +++ b/www/content/docs/fetcher.mdx @@ -7,7 +7,7 @@ excerpt: Using a custom fetcher with NextDrupal. ************************************************************ * TODO: Remove this block before publishing. -* Comment: Not sure how a custom fetcher will work because of the caching options of the Nextjs extended fetch API +* Comment: In order to support a custom fetcher and handle caching withouth the native polyfilled fetch, 'unstable_cache' from next should be used, but also the NextDrupal client should support passing revalidate options. ************************************************************ --> diff --git a/www/content/docs/fetching-resources.mdx b/www/content/docs/fetching-resources.mdx index 7c8aab964..70cd6bb19 100644 --- a/www/content/docs/fetching-resources.mdx +++ b/www/content/docs/fetching-resources.mdx @@ -168,10 +168,3 @@ const article = await drupal.getResourceCollection( // highlight-end ) ``` - - diff --git a/www/content/docs/pages.mdx b/www/content/docs/pages.mdx index 026dda7b1..2102032cd 100644 --- a/www/content/docs/pages.mdx +++ b/www/content/docs/pages.mdx @@ -3,15 +3,20 @@ title: Building Pages excerpt: How to build pages using JSON:API resources from Drupal. --- -In Next.js V14, data fetching has evolved significantly from previous versions. Instead of using `getStaticProps` and `getServerSideProps` you now use the native `fetch` function enhanced by Next.js to handle server-side data fetching. This allows you to configure caching and revalidation directly within your fetch requests. These can be used in Server Components, Route Handlers, and Server Actions. You can read more about it [here](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating) +In Next.js V14, data fetching has evolved significantly from previous versions. Instead of using `getStaticProps` and `getServerSideProps` you now use the native `fetch` function enhanced by Next.js to handle server-side data fetching. -The `NextDrupal` client provides several functions to help you query JSON:API resources from Drupal and manage these revalidation options on the `fetch` request level. +The `NextDrupal` client provides several functions to help you query JSON:API resources from Drupal. @@ -52,7 +57,7 @@ export default function AboutPage() { ## Dynamic pages -You can use Next.js [dynamic route](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) to build static pages for Drupal entity types. +You can use Next.js [dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) to build static pages for Drupal entity types. Start by creating a page at `/app/[...slug]/page.tsx`, where `[...slug]` maps to the **path alias** for an entity type (or content type) in Drupal. @@ -134,17 +139,17 @@ export default function Page({ params }) { params.addFields("node--article", ["title", "path", "body", "uid"]) } - const node = await drupal.getResourceByPath(path, { + const node = await drupal.getResource(path, path.entity.uuid { params: params.getQueryObject(), }) - // Render different Components based on Node type + // Render different Components based on Node type. if (node.type === "node--page") { - return + return } if (node.type === "node--article") { - return + return } return null diff --git a/www/content/docs/reference/buildEndpoint.mdx b/www/content/docs/reference/buildendpoint.mdx similarity index 72% rename from www/content/docs/reference/buildEndpoint.mdx rename to www/content/docs/reference/buildendpoint.mdx index 9369ae809..bf051289c 100644 --- a/www/content/docs/reference/buildEndpoint.mdx +++ b/www/content/docs/reference/buildendpoint.mdx @@ -48,12 +48,23 @@ const drupal = new DrupalClient(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { ```ts // https://example.com/jsonapi/node/article. const url = await drupal.buildEndpoint({ resourceType: `node--article` }) -``` - +// https://example.com/jsonapi/en/node/article?include=field_image. +const url = await drupal.buildEndpoint({ + locale: `en`, + resourceType: `node--article`, + searchParams: `include=field_image`, +}) + +// https://example.com/jsonapi/en/views/articles/page_1. +const url = await drupal.buildEndpoint({ + locale: `en`, + path: `/views/articles/page_1`, +}) +``` diff --git a/www/content/docs/reference/fetch.mdx b/www/content/docs/reference/fetch.mdx index 304ada6ab..ae73e567b 100644 --- a/www/content/docs/reference/fetch.mdx +++ b/www/content/docs/reference/fetch.mdx @@ -14,11 +14,19 @@ const response = await drupal.fetch(input, init?): Promise - Optional - The fetch options with `withAuth`. - If `withAuth` is set, `fetch` will fetch an `Authorization` header before making the request. + + --- diff --git a/www/content/docs/reference/getentryforresourcetype.mdx b/www/content/docs/reference/getentryforresourcetype.mdx new file mode 100644 index 000000000..b9110c0fa --- /dev/null +++ b/www/content/docs/reference/getentryforresourcetype.mdx @@ -0,0 +1,40 @@ +--- +title: getEntryForResourceType +excerpt: Get the JSON:API entry for a resource type. +--- + +```ts +const url = await drupal.getEntryForResourceType(type, locale?): Promise +``` + +- `type: string` + - **Required** + - The resource type. Example: `node--article`. +- `locale: string` + - Optional + - The locale to fetch the index. Example: `es` or `fr`. + +--- + +## Notes + +By default, when retrieving resources in `getResource` or `getResourceCollection`, the `NextDrupalPages` make a request to Drupal to fetch the JSON:API resource entry.. + +Example: if you provide `node--article`, `NextDrupalPages` will make a request to `http://example.com/jsonapi/node/article`. + +If you would like to infer the entry from the resource type, use the [`useDefaultResourceTypeEntry`](/docs/configuration#usedefaultresourcetypeentry) option. + +```ts +const drupal = new NextDrupalPages(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, { + useDefaultResourceTypeEntry: true, +}) +``` + +--- + +## Examples + +```ts +// https://example.com/jsonapi/node/article. +const url = await drupal.getEntryForResourceType(`node--article`) +``` diff --git a/www/content/docs/reference/getmenu.mdx b/www/content/docs/reference/getmenu.mdx index f3f4971a6..521347953 100644 --- a/www/content/docs/reference/getmenu.mdx +++ b/www/content/docs/reference/getmenu.mdx @@ -20,7 +20,6 @@ const resource = await drupal.getMenu( defaultLocale, withCache, cacheKey, - next } ): Promise<{ items: T[] @@ -42,11 +41,6 @@ const resource = await drupal.getMenu( - `defaultLocale: string`: The default locale of the site. - `withCache: boolean`: Set `withCache` if you want to store and retrieve the menu from cache. - `cacheKey: string`: The cache key to use. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- @@ -79,10 +73,7 @@ const menu = await drupal.getMenu("main", { ************************************************************ * TODO: Remove this block before publishing. -* Comment: Don't know how this cache works with Nextjs caching system -************************************************************ ---> - +* Comment: commented example until revalidation props are supported. - Get the `main` menu with tag-based revalidation. ```ts @@ -90,3 +81,5 @@ const menu = await drupal.getMenu("main", { next: { tags: ["main--menu"] }, // revalidates resource when calling `revalidateTag('main--menu')` }) ``` +************************************************************ +--> diff --git a/www/content/docs/reference/getpathfromcontext.mdx b/www/content/docs/reference/getpathfromcontext.mdx new file mode 100644 index 000000000..cb847abd4 --- /dev/null +++ b/www/content/docs/reference/getpathfromcontext.mdx @@ -0,0 +1,32 @@ +--- +title: getPathFromContext +excerpt: Return the path (slug) from getStaticProps or getServerSideProps context. +--- + +```ts +const slug = drupal.getPathFromContext( + context, + options?: { + pathPrefix, + } +): string +``` + +- `context: GetStaticPropsContext | GetServerSidePropsContext` + - **Required** + - The context from `getStaticProps` or `getServerSideProps`. +- `options` + - Optional + - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. + +--- + +## Examples + +- Get the path (slug) from `getStaticProps` context. + +```ts +export async function getStaticProps(context) { + const slug = await drupal.getPathFromContext(context) +} +``` diff --git a/www/content/docs/reference/getresource.mdx b/www/content/docs/reference/getresource.mdx index dcceb2078..edc0d1da4 100644 --- a/www/content/docs/reference/getresource.mdx +++ b/www/content/docs/reference/getresource.mdx @@ -14,7 +14,6 @@ const resource = await drupal.getResource( locale, defaultLocale, withCache, - next } ): Promise ``` @@ -36,11 +35,6 @@ const resource = await drupal.getResource( - `defaultLocale: string`: The default locale of the site. - `withCache: boolean`: Set `withCache` if you want to store and retrieve the resource from cache. - `cacheKey: string`: The cache key to use. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- @@ -91,6 +85,11 @@ const article = await drupal.getResource("node--article", id, { }) ``` + --- diff --git a/www/content/docs/reference/getresourcebypath.mdx b/www/content/docs/reference/getresourcebypath.mdx index 86c6450a9..828033d9a 100644 --- a/www/content/docs/reference/getresourcebypath.mdx +++ b/www/content/docs/reference/getresourcebypath.mdx @@ -13,7 +13,6 @@ const resource = await drupal.getResourceByPath( locale, defaultLocale, isVersionable, - next, } ): Promise ``` @@ -31,11 +30,6 @@ const resource = await drupal.getResourceByPath( - `locale: string`: The locale to fetch the resource in. - `defaultLocale: string`: The default locale of the site. - `isVersionable: boolean`: Set to true if you're fetching the revision for a resource. _Automatically set to true for node entity types_. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- @@ -73,6 +67,11 @@ const node = await drupal.getResourceByPath("/blog/slug-for-article", { }) ``` + --- diff --git a/www/content/docs/reference/getresourcecollection.mdx b/www/content/docs/reference/getresourcecollection.mdx index 0ce08f9ed..a73f557ad 100644 --- a/www/content/docs/reference/getresourcecollection.mdx +++ b/www/content/docs/reference/getresourcecollection.mdx @@ -12,7 +12,6 @@ const resource = await drupal.getResourceCollection( deserialize, locale, defaultLocale, - next, } ): Promise ``` @@ -29,11 +28,6 @@ const resource = await drupal.getResourceCollection( - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the resource in. - `defaultLocale: string`: The default locale of the site. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- @@ -63,6 +57,11 @@ const { data, meta, links } = await drupal.getResourceCollection("node--page", { }) ``` + --- diff --git a/www/content/docs/reference/getresourcecollectionfromcontext.mdx b/www/content/docs/reference/getresourcecollectionfromcontext.mdx new file mode 100644 index 000000000..da579209c --- /dev/null +++ b/www/content/docs/reference/getresourcecollectionfromcontext.mdx @@ -0,0 +1,78 @@ +--- +title: getResourceCollectionFromContext +excerpt: Fetch a collection of resources from getStaticProps or getServerSideProps context. +--- + +```ts +const resource = await drupal.getResourceCollectionFromContext( + type, + context, + options?: { + params, + withAuth, + deserialize, + locale, + defaultLocale, + } +): Promise +``` + +- `type: string` + - **Required** + - The resource type. Example: `node--article` or `user--user`. +- `context: GetStaticPropsContext | GetServerSidePropsContext` + - **Required** + - The context from `getStaticProps` or `getServerSideProps`. +- `options` + - Optional + - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. + - `withAuth: boolean | NextDrupalAuth`: + - Set the authentication method to use. See the [authentication docs](/docs/authentication). + - Set to `true` to use the authentication method configured on the client. + - `deserialize: boolean`: Set to false to return the raw JSON:API response. + - `locale: string`: The locale to fetch the resource in. + - `defaultLocale: string`: The default locale of the site. + +--- + +## Notes + +- The localized resources will be fetched based on the `locale` and `defaultLocale` values from `context`. + +--- + +## Examples + +- Get all articles from context. + +```ts title=pages/[[...slug]].tsx +export async function getStaticProps(context) { + const articles = await drupal.getResourceCollectionFromContext( + "node--article", + context + ) + + return { + props: { + articles, + }, + } +} +``` + +--- + +## TypeScript + +- Using `DrupalNode` for a node entity type. + +```ts +import { DrupalNode } from "next-drupal" + +const nodes = await drupal.getResourceCollectionFromContext( + "node--article", + context +) +``` + +See the [TypeScript docs](/docs/typescript) for more built-in types. diff --git a/www/content/docs/reference/getresourcecollectionpathsegments.mdx b/www/content/docs/reference/getresourcecollectionpathsegments.mdx index af4f22f6b..2c0e51b2a 100644 --- a/www/content/docs/reference/getresourcecollectionpathsegments.mdx +++ b/www/content/docs/reference/getresourcecollectionpathsegments.mdx @@ -12,8 +12,6 @@ const paths = await drupal.getResourceCollectionPathSegments( pathPrefix, locale, defaultLocale, - next, - } ): Promise<{ path: string @@ -35,11 +33,6 @@ const paths = await drupal.getResourceCollectionPathSegments( - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. - `locale: string`: The locale to fetch the resource in. - `defaultLocale: string`: The default locale of the site. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- diff --git a/www/content/docs/reference/getresourcefromcontext.mdx b/www/content/docs/reference/getresourcefromcontext.mdx new file mode 100644 index 000000000..f317f7016 --- /dev/null +++ b/www/content/docs/reference/getresourcefromcontext.mdx @@ -0,0 +1,138 @@ +--- +title: getResourceFromContext +excerpt: Fetch a resource from getStaticProps or getServerSideProps context. +--- + +```ts +const resource = await drupal.getResourceFromContext( + input, + context, + options?: { + params, + withAuth, + deserialize, + locale, + defaultLocale, + pathPrefix, + isVersionable, + } +): Promise +``` + +- `input: string | DrupalTranslatedPath` + - **Required** + - The resource type `node--article` or the translated path from `translatePathFromContext`. +- `context: GetStaticPropsContext | GetServerSidePropsContext` + - **Required** + - The context from `getStaticProps` or `getServerSideProps`. +- `options` + - Optional + - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. + - `withAuth: boolean | NextDrupalAuth`: + - Set the authentication method to use. See the [authentication docs](/docs/authentication). + - Set to `true` to use the authentication method configured on the client. + - `deserialize: boolean`: Set to false to return the raw JSON:API response. + - `locale: string`: The locale to fetch the resource in. + - `defaultLocale: string`: The default locale of the site. + - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. + - `isVersionable: boolean`: Set to true if you're fetching the revision for a resource. _Automatically set to true for node entity types_. + +--- + +## Notes + +- The localized resource will be fetched based on the `locale` and `defaultLocale` values from `context`. + +- If you pass in a `DrupalTranslatedPath` for input, `getResourceFromContext` will take the `type` and `id` from the path and make a `getResource` call to Drupal. + +```ts +export async function getStaticProps(context) { + const path = await drupal.translatePathFromContext(context) + + const node = await drupal.getResourceFromContext(path, context) + + return { + props: { + node, + }, + } +} +``` + +- If you pass in a `string` inout, such as `node--article`, `getResourceFromContext` will make a subrequest call to Drupal to translate the path and then fetch the resource. + + You will need both the [Subrequests](https://drupal.org/project/subrequests) and [Decoupled Router](https://drupal.org/project/decoupled_router) modules. + +```ts +export async function getStaticProps(context) { + const node = await drupal.getResourceFromContext("node--article", context) + + return { + props: { + node, + }, + } +} +``` + +--- + +## Examples + +- Fetch a resource from context. + +```ts title=pages/[[...slug]].tsx +export async function getStaticProps(context) { + const node = await drupal.getResourceFromContext("node--page", context) + + return { + props: { + node, + }, + } +} +``` + +- Fetch a resource from context in a sub directory. + +```ts title=pages/articles/[[...slug]].tsx +export async function getStaticProps(context) { + const node = await drupal.getResourceFromContext("node--page", context, { + pathPrefix: "/articles", + }) + + return { + props: { + node, + }, + } +} +``` + +--- + +## TypeScript + +- Using `DrupalNode` for a node entity type. + +```ts +import { DrupalNode } from "next-drupal" + +const node = await drupal.getResourceFromContext( + "node--page", + context +) +``` + +- Using `DrupalTaxonomyTerm` for a taxonomy term entity type. + +```ts +import { DrupalTaxonomyTerm } from "next-drupal" + +const term = await drupal.getResourceFromContext( + "taxonomy_term--tags", + context +) +``` + +See the [TypeScript docs](/docs/typescript) for more built-in types. diff --git a/www/content/docs/reference/getsearch.mdx b/www/content/docs/reference/getsearch.mdx index 146659f2d..4eef21ad3 100644 --- a/www/content/docs/reference/getsearch.mdx +++ b/www/content/docs/reference/getsearch.mdx @@ -18,7 +18,6 @@ const resources = await drupal.getSearchIndex( deserialize, locale, defaultLocale, - next } ): Promise ``` @@ -35,11 +34,6 @@ const resources = await drupal.getSearchIndex( - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the view in. - `defaultLocale: string`: The default locale of the site. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- diff --git a/www/content/docs/reference/getstaticpathsfromcontext.mdx b/www/content/docs/reference/getstaticpathsfromcontext.mdx new file mode 100644 index 000000000..a0b7d4af7 --- /dev/null +++ b/www/content/docs/reference/getstaticpathsfromcontext.mdx @@ -0,0 +1,59 @@ +--- +title: getStaticPathsFromContext +excerpt: Return paths for getStaticPaths. +--- + +```ts +const paths = await drupal.getStaticPathsFromContext( + types, + context, + options?: { + params, + withAuth, + pathPrefix, + } +): Promise["paths"]> +``` + +- `types: string | string[]` + - **Required** + - The resource types. Example: `node--article` or `["taxonomy_term--tags", "user--user"]`. +- `context: GetStaticPathsContext` + - **Required** + - The context from `getStaticPaths`. +- `options` + - Optional + - `params: JsonApiParams`: JSON:API params such as `filter`, `fields`, `include` or `sort`. + - `withAuth: boolean | NextDrupalAuth`: + - Set the authentication method to use. See the [authentication docs](/docs/authentication). + - Set to `true` to use the authentication method configured on the client. + - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. + +--- + +## Examples + +- Return static paths for `node--page` resources. + +```ts +export async function getStaticPaths(context) { + return { + paths: await drupal.getStaticPathsFromContext("node--page", context), + fallback: "blocking", + } +} +``` + +- Return static paths for `node--page` and `node--article` resources. + +```ts +export async function getStaticPaths(context) { + return { + paths: await drupal.getStaticPathsFromContext( + ["node--page", "node--article"], + context + ), + fallback: "blocking", + } +} +``` diff --git a/www/content/docs/reference/getview.mdx b/www/content/docs/reference/getview.mdx index d1a337156..f16eddeb6 100644 --- a/www/content/docs/reference/getview.mdx +++ b/www/content/docs/reference/getview.mdx @@ -18,7 +18,6 @@ const view = await drupal.getView( deserialize, locale, defaultLocale, - next } ): Promise> ``` @@ -35,11 +34,6 @@ const view = await drupal.getView( - `deserialize: boolean`: Set to false to return the raw JSON:API response. - `locale: string`: The locale to fetch the view in. - `defaultLocale: string`: The default locale of the site. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- @@ -63,22 +57,6 @@ const view = await drupal.getView("articles--promoted", { }) ``` -- Get a view with time-based revalidation. - -```ts -const view = await drupal.getView("articles--promoted", { - next: { revalidate: 3600 }, // revalidate every hour` -}) -``` - -- Get a view with tag-based revalidation. - -```ts -const view = await drupal.getView("articles--promoted", { - next: { tags: ["article-view"] }, // revalidates resource when calling `revalidateTag('article-view')` -}) -``` - --- ## TypeScript diff --git a/www/content/docs/reference/preview.mdx b/www/content/docs/reference/preview.mdx new file mode 100644 index 000000000..f5ef8b677 --- /dev/null +++ b/www/content/docs/reference/preview.mdx @@ -0,0 +1,43 @@ +--- +title: preview +excerpt: Handle preview mode for resources. +--- + +```ts +await drupal.preview(request, response, options?: { + errorMessages?: { + secret, + slug, + } +}): Promise +``` + +- `request: NextApiRequest` + - **Required** + - The `request` from an API route. +- `response: NextApiResponse` + - **Required** + - The `response` from an API route. +- `options` + - Optional + - `errorMessages`: + - `secret`: The error message to display for an invalid secret. + - `slug`: The error message to display for an invalid slug. + +--- + +## Notes + +- The `preview` method should be called in an API route. + +--- + +## Examples + +```ts title=pages/api/preview.ts +import { drupal } from "lib/drupal" + +export default async function handler(req, res) { + return await drupal.preview(req, res) +} +``` diff --git a/www/content/docs/reference/translatepath.mdx b/www/content/docs/reference/translatepath.mdx index 0613f510d..38d5b43ed 100644 --- a/www/content/docs/reference/translatepath.mdx +++ b/www/content/docs/reference/translatepath.mdx @@ -8,7 +8,6 @@ const path = await drupal.translatePath( path, options?: { withAuth, - next } ): Promise ``` @@ -21,11 +20,6 @@ const path = await drupal.translatePath( - `withAuth: boolean | NextDrupalAuth`: - Set the authentication method to use. See the [authentication docs](/docs/authentication). - Set to `true` to use the authentication method configured on the client. - - `next: NextFetchRequestConfig` - - Set the `revalidate` option in seconds to configure [Time-based revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation). - Ex: `next: { revalidate: 3600 } // revalidate resource every hour` - - Set the `tags` option to confiure [Tag-based On demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#on-demand-revalidation). - Ex: `next: { tags: ['resource-tag'] }` --- diff --git a/www/content/docs/reference/translatepathfromcontext.mdx b/www/content/docs/reference/translatepathfromcontext.mdx new file mode 100644 index 000000000..3d8d4c9e8 --- /dev/null +++ b/www/content/docs/reference/translatepathfromcontext.mdx @@ -0,0 +1,42 @@ +--- +title: translatePathFromContext +excerpt: Fetch info about a Drupal path from getStaticProps or getServerSideProps context. +--- + +```ts +const path = await drupal.translatePathFromContext( + context, + options?: { + withAuth, + pathPrefix, + } +): Promise +``` + +- `context: GetStaticPropsContext | GetServerSidePropsContext` + - **Required** + - The context from `getStaticProps` or `getServerSideProps`. +- `options` + - Optional + - `withAuth: boolean | NextDrupalAuth`: + - Set the authentication method to use. See the [authentication docs](/docs/authentication). + - Set to `true` to use the authentication method configured on the client. + - `pathPrefix: string`: Set the pathPrefix if you're calling from a subdir. Example: for `/articles/[...slug].tsx`, use `pathPrefix: "/articles"`. + +--- + +## Notes + +- The [Decoupled Router](https://drupal.org/project/decoupled_router) module is required. + +--- + +## Examples + +- Get info about a path from `getStaticProps` context. + +```ts +export async function getStaticProps(context) { + const path = await drupal.translatePathFromContext(context) +} +``` diff --git a/www/content/docs/serializer.mdx b/www/content/docs/serializer.mdx new file mode 100644 index 000000000..5596fa09d --- /dev/null +++ b/www/content/docs/serializer.mdx @@ -0,0 +1,32 @@ +--- +title: Serializer +excerpt: Using a custom serializer with DrupalClient. +--- + +The `NextDrupalPages` uses [jsona](https://github.com/olosegres/jsona) as the default serializer for serializing and deserializing JSON:API data. + +You can provide your own using the [`serializer`](/docs/client/configuration#serializer) option. + +--- + +## Example + +Here's how you can replace the default serializer with [jsonapi-serializer](https://github.com/SeyZ/jsonapi-serializer). + +```ts title=lib/drupal.ts +import { NextDrupalPages } from "next-drupal" +import { Deserializer } from "jsonapi-serializer" + +// Create a custom serializer. +const customSerializer = new Deserializer({ + keyForAttribute: "camelCase", +}) + +// Pass the custom serializer to the client. +export const drupal = new NextDrupalPages( + process.env.NEXT_PUBLIC_DRUPAL_BASE_URL, + { + serializer: customSerializer, + } +) +``` diff --git a/www/content/tutorials/draft-mode/create-site.mdx b/www/content/tutorials/draft-mode/create-site.mdx index 000616f19..8dc4cfe72 100644 --- a/www/content/tutorials/draft-mode/create-site.mdx +++ b/www/content/tutorials/draft-mode/create-site.mdx @@ -5,7 +5,7 @@ weight: 105 group: Draft Mode --- -Start by creating a Next.js site so that we can render the draft on Drupal. +Start by creating a Next.js site so that we can render the draft in Drupal. 1. Visit `/admin/config/services/next`. 2. Click **Add Next.js site**. diff --git a/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx b/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx index 79d463919..3cbc86819 100644 --- a/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx +++ b/www/content/tutorials/on-demand-revalidation/configure-entity-types.mdx @@ -5,16 +5,6 @@ weight: 350 group: On-demand Revalidation --- - - Next, we need to configure on-demand revalidation for the entity types. To enable on-demand revalidation for an entity type, we need to configure a **revalidator** plugin. diff --git a/www/content/tutorials/quick-start/index.mdx b/www/content/tutorials/quick-start/index.mdx index 3c719d080..205ce5de0 100644 --- a/www/content/tutorials/quick-start/index.mdx +++ b/www/content/tutorials/quick-start/index.mdx @@ -5,7 +5,7 @@ weight: 10 group: Quick Start --- -This tutorial will help you get started with Next.js for Drupal using the [`NextDrupal`](/docs/client) and **JSON:API**. +This tutorial will help you get started with Next.js for Drupal using the [`NextDrupal Client`](/docs/client) and **JSON:API**.