Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add client utils to app router package #1659

Merged
merged 21 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/violet-taxis-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@faustwp/experimental-app-router': patch
---

Added: New util for fetching data on the client side. In a client component (`use client`), you can now use Apollo's `useQuery` to fetch data once your application is wrapped with the `<FaustProvider>` component. This new component is available via:

```tsx
import { FaustProvider } from '@faustwp/experimental-app-router/ssr';
```
22 changes: 9 additions & 13 deletions examples/next/app-router/app/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,23 @@ import { hasPreviewProps } from './hasPreviewProps';
import { PleaseLogin } from '@/components/please-login';

export default async function Page(props) {
const slug = props.params.slug;
const isPreview = hasPreviewProps(props);
const id = isPreview ? props.searchParams.p : props.params.slug;

let client = isPreview ? await getAuthClient() : await getClient();

if (!client) {
return <PleaseLogin />;
}

/**
* There is currently a bug in WPGraphQL where you can not query for previews
* using the contentNode type. This bug will need to be resolved for preview
* functionality in the below query to work properly. For now, it returns
* the production ready data for the given contentNode regardless if
* asPreview is true or false.
*
* @see https://github.com/wp-graphql/wp-graphql/issues/1673
*/
const { data } = await client.query({
query: gql`
query GetContentNode($uri: ID!, $asPreview: Boolean!) {
contentNode(id: $uri, idType: URI, asPreview: $asPreview) {
query GetContentNode(
$id: ID!
$idType: ContentNodeIdTypeEnum!
$asPreview: Boolean!
) {
contentNode(id: $id, idType: $idType, asPreview: $asPreview) {
... on NodeWithTitle {
title
}
Expand All @@ -37,7 +32,8 @@ export default async function Page(props) {
}
`,
variables: {
uri: slug,
id,
idType: isPreview ? 'DATABASE_ID' : 'URI',
asPreview: isPreview,
},
});
Expand Down
36 changes: 19 additions & 17 deletions examples/next/app-router/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { gql } from '@apollo/client';
import { getClient } from '@faustwp/experimental-app-router';
import Link from 'next/link';
import '@/faust.config.js';

import { FaustProvider } from '@faustwp/experimental-app-router/ssr';
export default async function RootLayout({ children }) {
const client = await getClient();

Expand Down Expand Up @@ -34,24 +34,26 @@ export default async function RootLayout({ children }) {
return (
<html lang="en">
<body>
<header>
<div>
<h1>
<Link href="/">{data.generalSettings.title}</Link>
</h1>
<FaustProvider>
<header>
<div>
<h1>
<Link href="/">{data.generalSettings.title}</Link>
</h1>

<h5>{data.generalSettings.description}</h5>
</div>
<h5>{data.generalSettings.description}</h5>
</div>

<ul>
{data.primaryMenuItems.nodes.map((node) => (
<li>
<Link href={node.uri}>{node.label}</Link>
</li>
))}
</ul>
</header>
{children}
<ul>
{data.primaryMenuItems.nodes.map((node) => (
<li>
<Link href={node.uri}>{node.label}</Link>
</li>
))}
</ul>
</header>
{children}
</FaustProvider>
</body>
</html>
);
Expand Down
22 changes: 22 additions & 0 deletions examples/next/app-router/app/making-client-queries/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import { gql, useQuery } from '@apollo/client';

/**
* You can make client side queries as well with Apollo's `useQuery` hook within
* a client component ('use client' directive). Just make sure the <FaustProvider>
* is wrapping the app (in app/layout.js)
*
*/

export default function Page() {
const { data } = useQuery(gql`
query MyQuery {
generalSettings {
title
}
}
`);

return <>{data?.generalSettings?.title}</>;
}
4 changes: 2 additions & 2 deletions examples/next/app-router/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"module": "ESNext",
"moduleResolution": "Bundler",
Comment on lines +16 to +17
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to use package exports in TypeScript, you must set moduleResolution to Node16, NodeNext, or Bundler. Since we don't want to enforce strict module resolution with file extensions, etc. on our users, we use Bundler since the other two require that strict behavior.

"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
Expand Down
79 changes: 42 additions & 37 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/experimental-app-router/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
roots: ['<rootDir>/tests'],

// Adds Jest support for TypeScript using ts-jest.
Expand Down
2 changes: 2 additions & 0 deletions packages/experimental-app-router/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"name": "@faustwp/experimental-app-router",
"type": "module",
"version": "0.2.1",
"description": "Experimental: A Faust package to support Next.js' App Router",
"exports": {
".": "./dist/index.js",
"./ssr": "./dist/ssr.js",
"./package.json": "./package.json"
},
"types": "dist/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import {
ApolloClient,
InMemoryCache,
ApolloLink,
InMemoryCacheConfig,
createHttpLink,
} from '@apollo/client';
// eslint-disable-next-line import/extensions
import { setContext } from '@apollo/client/link/context';
// eslint-disable-next-line import/extensions
import { registerApolloClient } from '@apollo/experimental-nextjs-app-support/rsc';
import { fetchAccessToken } from './server/auth/fetchAccessToken.js';
import { getConfig, getGraphqlEndpoint } from './faust-core-utils.js';
import { getConfig, getGraphqlEndpoint } from '../faust-core-utils.js';
import { fetchAccessToken } from '../server/auth/fetchAccessToken.js';

async function createFaustApolloClient(authenticated = false) {
export function createApolloConfig(
authenticated = false,
): [InMemoryCacheConfig, ApolloLink] {
const { possibleTypes } = getConfig();

const inMemoryCacheObject: InMemoryCacheConfig = {
Expand Down Expand Up @@ -56,28 +55,5 @@ async function createFaustApolloClient(authenticated = false) {
* we may set config differently than how we currently do it.
*/

return new ApolloClient({
cache: new InMemoryCache(inMemoryCacheObject),
link: linkChain,
});
}

export async function getClient() {
const faustApolloClient = await createFaustApolloClient(false);
const client = registerApolloClient(() => faustApolloClient);

return client.getClient();
}

export async function getAuthClient() {
const token = await fetchAccessToken();

if (!token) {
return null;
}

const faustApolloClient = await createFaustApolloClient(true);
const client = registerApolloClient(() => faustApolloClient);

return client.getClient();
return [inMemoryCacheObject, linkChain];
}
34 changes: 34 additions & 0 deletions packages/experimental-app-router/src/client/rsc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// eslint-disable-next-line import/extensions
import { ApolloClient, InMemoryCache } from '@apollo/client';
// eslint-disable-next-line import/extensions
import { registerApolloClient } from '@apollo/experimental-nextjs-app-support/rsc';
import { fetchAccessToken } from '../server/auth/fetchAccessToken.js';
import { createApolloConfig } from './config.js';

export function createRSCApolloClient(authenticated = false) {
const [inMemoryCacheObject, linkChain] = createApolloConfig(authenticated);
return new ApolloClient({
cache: new InMemoryCache(inMemoryCacheObject),
link: linkChain,
});
}

export async function getClient() {
const faustApolloClient = createRSCApolloClient(false);
const client = registerApolloClient(() => faustApolloClient);

return client.getClient();
}

export async function getAuthClient() {
const token = await fetchAccessToken();

if (!token) {
return null;
}

const faustApolloClient = createRSCApolloClient(true);
const client = registerApolloClient(() => faustApolloClient);

return client.getClient();
}
27 changes: 27 additions & 0 deletions packages/experimental-app-router/src/client/ssr.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client';

// eslint-disable-next-line import/extensions
import {
ApolloNextAppProvider,
NextSSRApolloClient,
NextSSRInMemoryCache,
// eslint-disable-next-line import/extensions
} from '@apollo/experimental-nextjs-app-support/ssr';
import React, { PropsWithChildren } from 'react';
import { createApolloConfig } from './config.js';

export function createSSRApolloClient(authenticated = false) {
const [inMemoryCacheObject, linkChain] = createApolloConfig(authenticated);
return new NextSSRApolloClient({
cache: new NextSSRInMemoryCache(inMemoryCacheObject),
link: linkChain,
});
}

export function FaustSSRProvider({ children }: PropsWithChildren<object>) {
return (
<ApolloNextAppProvider makeClient={() => createSSRApolloClient(false)}>
{children}
</ApolloNextAppProvider>
);
}
2 changes: 1 addition & 1 deletion packages/experimental-app-router/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { getClient, getAuthClient } from './client.js';
export { getClient, getAuthClient } from './client/rsc.js';
export { faustRouteHandler } from './server/routeHandler/index.js';
export { fetchAccessToken } from './server/auth/fetchAccessToken.js';
export { onLogout } from './server-actions/logoutAction.js';
Expand Down
Loading
Loading