-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into docs-graphql-starter-updates
- Loading branch information
Showing
65 changed files
with
1,669 additions
and
562 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# See https://next-drupal.org/docs/environment-variables | ||
|
||
# Required | ||
NEXT_PUBLIC_DRUPAL_BASE_URL=https://site.example.com | ||
NEXT_IMAGE_DOMAIN=site.example.com | ||
|
||
# Authentication | ||
DRUPAL_CLIENT_ID=Retrieve this from /admin/config/services/consumer | ||
DRUPAL_CLIENT_SECRET=Retrieve this from /admin/config/services/consumer | ||
|
||
# Required for On-demand Revalidation | ||
DRUPAL_REVALIDATE_SECRET=Retrieve this from /admin/config/services/next |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "next/core-web-vitals", | ||
"root": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# IDE files | ||
/.idea | ||
/.vscode | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
v20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Ignore everything. | ||
/* | ||
|
||
# Format most files in the root directory. | ||
!/*.js | ||
!/*.ts | ||
!/*.md | ||
!/*.json | ||
# But ignore some. | ||
/package.json | ||
/package-lock.json | ||
/CHANGELOG.md | ||
|
||
# Don't ignore these nested directories. | ||
!/app | ||
!/components | ||
!/lib | ||
!/pages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"semi": false, | ||
"trailingComma": "es5" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Change Log | ||
|
||
All notable changes to this project will be documented in this file. | ||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# example-router-migration | ||
|
||
Next.js recommends using their new App Router over the legacy Pages Router. The [full router migration guide](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration) is available in the Next.js documentation. | ||
|
||
The new App Router is also designed to facilitate sites that need to migrate from the Pages Router in a piecemeal fashion rather than all at once. | ||
|
||
This codebase is an example of a `next-drupal` site that is in the middle of a Next.js Pages to App Router migration. | ||
|
||
## Piecemeal router migration steps | ||
|
||
### Initial migration | ||
|
||
1. Update the `next-drupal` package to the latest 2.x version. | ||
2. Update the `next` module on your Drupal site to the latest 2.x version. | ||
1. The most recent version is available at https://www.drupal.org/project/next | ||
2. Run your Drupal site’s /update.php script. | ||
3. Migrate from Preview Mode to Draft mode. Preview mode only works with the legacy Pages Router. Draft mode works with both routers. | ||
1. Update the `/pages/api/preview.ts` file to match the one in this Git repo. | ||
2. Update the `/pages/api/exit-preview.ts` file to match the one in this Git repo. | ||
3. Delete your `/pages/api/revalidate.ts` file. | ||
4. Create a `/app/api` directory and add all the files from this Git repo’s `/app/api` directory. | ||
|
||
### Piecemeal migration | ||
|
||
Follow [Next.js’ router migration guide](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration). | ||
|
||
Over time, you will be moving all the files from `/pages` to `/app`. However, these JavaScript files should remain in the `/pages` directory to prevent Preview/Draft Mode from breaking: | ||
|
||
- `/pages/api/exit-preview.ts` | ||
- `/pages/api/preview.ts` | ||
|
||
### Final migration steps | ||
|
||
1. Turn off the legacy Preview Mode. | ||
1. Go to the Next.js site configuration on your Drupal site at `/admin/config/services/next`. | ||
2. For each Next.js configuration, change the end of the URL in the “Draft URL (or Preview URL)” setting from `preview` to `draft`, e.g. `https://example.com/api/preview` to `https://example.com/api/draft`. | ||
2. Delete the last files in your `/pages` directory: | ||
- `/pages/api/exit-preview.ts` | ||
- `/pages/api/preview.ts` | ||
|
||
## License | ||
|
||
Licensed under the [MIT license](https://github.com/chapter-three/next-drupal/blob/master/LICENSE). |
115 changes: 115 additions & 0 deletions
115
examples/example-router-migration/app/[...slug]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { draftMode } from "next/headers" | ||
import { notFound } from "next/navigation" | ||
import { getDraftData } from "next-drupal/draft" | ||
import { Article } from "@/components/drupal/Article" | ||
import { BasicPage } from "@/components/drupal/BasicPage" | ||
import { drupal } from "@/lib/drupal" | ||
import type { Metadata, ResolvingMetadata } from "next" | ||
import type { DrupalNode, JsonApiParams } from "next-drupal" | ||
|
||
async function getNode(slug: string[]) { | ||
const path = slug.join("/") | ||
|
||
const params: JsonApiParams = {} | ||
|
||
const draftData = getDraftData() | ||
|
||
if (draftData.slug === `/${path}`) { | ||
params.resourceVersion = draftData.resourceVersion | ||
} | ||
|
||
// Translating the path also allows us to discover the entity type. | ||
const translatedPath = await drupal.translatePath(path) | ||
|
||
if (!translatedPath) { | ||
throw new Error("Resource not found", { cause: "NotFound" }) | ||
} | ||
|
||
const type = translatedPath.jsonapi?.resourceName! | ||
const uuid = translatedPath.entity.uuid | ||
|
||
if (type === "node--article") { | ||
params.include = "field_image,uid" | ||
} | ||
|
||
const resource = await drupal.getResource<DrupalNode>(type, uuid, { | ||
params, | ||
}) | ||
|
||
if (!resource) { | ||
throw new Error( | ||
`Failed to fetch resource: ${translatedPath?.jsonapi?.individual}`, | ||
{ | ||
cause: "DrupalError", | ||
} | ||
) | ||
} | ||
|
||
return resource | ||
} | ||
|
||
type NodePageParams = { | ||
slug: string[] | ||
} | ||
type NodePageProps = { | ||
params: NodePageParams | ||
searchParams: { [key: string]: string | string[] | undefined } | ||
} | ||
|
||
export async function generateMetadata( | ||
{ params: { slug } }: NodePageProps, | ||
parent: ResolvingMetadata | ||
): Promise<Metadata> { | ||
let node | ||
try { | ||
node = await getNode(slug) | ||
} catch (e) { | ||
// If we fail to fetch the node, don't return any metadata. | ||
return {} | ||
} | ||
|
||
return { | ||
title: node.title, | ||
} | ||
} | ||
|
||
const RESOURCE_TYPES = ["node--page", "node--article"] | ||
|
||
export async function generateStaticParams(): Promise<NodePageParams[]> { | ||
// TODO: Replace getStaticPathsFromContext() usage since there is no context. | ||
const paths = await drupal.getStaticPathsFromContext(RESOURCE_TYPES, {}) | ||
// console.log( | ||
// "generateStaticParams", | ||
// paths.map(({ params }) => params) | ||
// ) | ||
return paths.map((path: string | { params: NodePageParams }) => | ||
typeof path === "string" ? { slug: [] } : path?.params | ||
) | ||
} | ||
|
||
export default async function NodePage({ | ||
params: { slug }, | ||
searchParams, | ||
}: NodePageProps) { | ||
const isDraftMode = draftMode().isEnabled | ||
|
||
let node | ||
try { | ||
node = await getNode(slug) | ||
} catch (error) { | ||
// If getNode throws an error, tell Next.js the path is 404. | ||
notFound() | ||
} | ||
|
||
// If we're not in draft mode and the resource is not published, return a 404. | ||
if (!isDraftMode && node?.status === false) { | ||
notFound() | ||
} | ||
|
||
return ( | ||
<> | ||
{node.type === "node--page" && <BasicPage node={node} />} | ||
{node.type === "node--article" && <Article node={node} />} | ||
</> | ||
) | ||
} |
6 changes: 6 additions & 0 deletions
6
examples/example-router-migration/app/api/disable-draft/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { disableDraftMode } from "next-drupal/draft" | ||
import type { NextRequest } from "next/server" | ||
|
||
export async function GET(request: NextRequest) { | ||
return disableDraftMode() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { drupal } from "@/lib/drupal" | ||
import { enableDraftMode } from "next-drupal/draft" | ||
import type { NextRequest } from "next/server" | ||
|
||
export async function GET(request: NextRequest): Promise<Response | never> { | ||
return enableDraftMode(request, drupal) | ||
} |
28 changes: 28 additions & 0 deletions
28
examples/example-router-migration/app/api/revalidate/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { revalidatePath } from "next/cache" | ||
import type { NextRequest } from "next/server" | ||
|
||
async function handler(request: NextRequest) { | ||
const searchParams = request.nextUrl.searchParams | ||
const slug = searchParams.get("slug") | ||
const secret = searchParams.get("secret") | ||
|
||
// Validate secret. | ||
if (secret !== process.env.DRUPAL_REVALIDATE_SECRET) { | ||
return new Response("Invalid secret.", { status: 401 }) | ||
} | ||
|
||
// Validate slug. | ||
if (!slug) { | ||
return new Response("Invalid slug.", { status: 400 }) | ||
} | ||
|
||
try { | ||
revalidatePath(slug) | ||
|
||
return new Response("Revalidated.") | ||
} catch (error) { | ||
return new Response((error as Error).message, { status: 500 }) | ||
} | ||
} | ||
|
||
export { handler as GET, handler as POST } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { DraftAlert } from "@/components/misc/DraftAlert" | ||
import { HeaderNav } from "@/components/navigation/HeaderNav" | ||
import type { Metadata } from "next" | ||
import type { ReactNode } from "react" | ||
|
||
import "@/styles/globals.css" | ||
|
||
export const metadata: Metadata = { | ||
title: { | ||
default: "Next.js for Drupal", | ||
template: "%s | Next.js for Drupal", | ||
}, | ||
description: "A Next.js site powered by a Drupal backend.", | ||
icons: { | ||
icon: "/favicon.ico", | ||
}, | ||
} | ||
|
||
export default function RootLayout({ | ||
// Layouts must accept a children prop. | ||
// This will be populated with nested layouts or pages | ||
children, | ||
}: { | ||
children: ReactNode | ||
}) { | ||
return ( | ||
<html lang="en"> | ||
<body> | ||
<DraftAlert /> | ||
<div className="max-w-screen-md px-6 mx-auto"> | ||
<HeaderNav /> | ||
<main className="container py-10 mx-auto">{children}</main> | ||
</div> | ||
</body> | ||
</html> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { ArticleTeaser } from "@/components/drupal/ArticleTeaser" | ||
import { Link } from "@/components/navigation/Link" | ||
import { drupal } from "@/lib/drupal" | ||
import type { Metadata } from "next" | ||
import type { DrupalNode } from "next-drupal" | ||
|
||
export const metadata: Metadata = { | ||
description: "A Next.js site powered by a Drupal backend.", | ||
} | ||
|
||
export default async function Home() { | ||
const nodes = await drupal.getResourceCollection<DrupalNode[]>( | ||
"node--article", | ||
{ | ||
params: { | ||
"filter[status]": 1, | ||
"fields[node--article]": "title,path,field_image,uid,created", | ||
include: "field_image,uid", | ||
sort: "-created", | ||
}, | ||
} | ||
) | ||
|
||
return ( | ||
<> | ||
<h1 className="mb-2 text-6xl font-black leading-6"> | ||
Latest Articles. | ||
<br /> | ||
<small className="text-xl"> | ||
<em>Using the App Router</em> | ||
</small> | ||
</h1> | ||
<p className="mb-10"> | ||
Switch to{" "} | ||
<Link href="/pages-router" className="underline hover:text-blue-600"> | ||
Pages Router | ||
</Link> | ||
</p> | ||
{nodes?.length ? ( | ||
nodes.map((node) => ( | ||
<div key={node.id}> | ||
<ArticleTeaser node={node} /> | ||
<hr className="my-20" /> | ||
</div> | ||
)) | ||
) : ( | ||
<p className="py-4">No nodes found</p> | ||
)} | ||
</> | ||
) | ||
} |
Oops, something went wrong.