Skip to content

Commit

Permalink
Updates Apollo Server Examples to use Apollo Server 4 & @as-integrati…
Browse files Browse the repository at this point in the history
…ons/next (#42771)

Closes #42769

## Description 

This PR address #42769 by updating the `api-routes-apollo-server`, `api-routes-apollo-server-and-client` and `api-routes-apollo-server-and-client-auth` examples to use Apollo Server 4 and [@as-integrations/next](https://github.com/apollo-server-integrations/apollo-server-integration-next), which is the Apollo Server Next integration package. The PR also updates the three examples to use Typescript. The functionality of the examples is the same.


## Documentation / Examples
- [X] Make sure the linting passes by running `pnpm build && pnpm lint`
- [X] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)


closes #33545
closes #30082
closes #21984
closes #10413
  • Loading branch information
idoob committed Nov 14, 2022
1 parent 0bc9446 commit 081b8fb
Show file tree
Hide file tree
Showing 39 changed files with 152 additions and 70 deletions.
@@ -1,6 +1,6 @@
# Apollo Server and Client Auth Example

[Apollo](https://www.apollographql.com/client/) is a GraphQL client that allows you to easily query the exact data you need from a GraphQL server. In addition to fetching and mutating data, Apollo analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run.
[Apollo](https://www.apollographql.com/client/) is a GraphQL client that allows you to easily query the exact data you need from a GraphQL server. In addition to fetching and mutating data, Apollo analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run. The integration with Next and Apollo Server is implemented using the [apollo-server-integration-next](https://github.com/apollo-server-integrations/apollo-server-integration-next) community package.

In this simple example, we integrate Apollo seamlessly with [Next.js data fetching methods](https://nextjs.org/docs/basic-features/data-fetching) to fetch queries in the server and hydrate them in the browser.

Expand Down
@@ -1,16 +1,15 @@
import { useMemo } from 'react'
import { ApolloClient, InMemoryCache } from '@apollo/client'
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'
import { SchemaLink } from '@apollo/client/link/schema'
import { schema } from '../apollo/schema'
import merge from 'deepmerge'

let apolloClient

function createIsomorphLink() {
if (typeof window === 'undefined') {
const { SchemaLink } = require('@apollo/client/link/schema')
const { schema } = require('./schema')
return new SchemaLink({ schema })
} else {
const { HttpLink } = require('@apollo/client/link/http')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
Expand Down
@@ -1,20 +1,25 @@
import { AuthenticationError, UserInputError } from 'apollo-server-micro'
import { createUser, findUser, validatePassword } from '../lib/user'
import { setLoginSession, getLoginSession } from '../lib/auth'
import { removeTokenCookie } from '../lib/auth-cookies'
import { GraphQLError } from 'graphql'

export const resolvers = {
Query: {
async viewer(_parent, _args, context, _info) {
async viewer(_root, _args, context, _info) {
try {
const session = await getLoginSession(context.req)

if (session) {
return findUser({ email: session.email })
}
} catch (error) {
throw new AuthenticationError(
'Authentication token is invalid, please log in'
throw new GraphQLError(
'Authentication token is invalid, please log in',
{
extensions: {
code: 'UNAUTHENTICATED',
},
}
)
}
},
Expand All @@ -38,7 +43,7 @@ export const resolvers = {
return { user }
}

throw new UserInputError('Invalid email and password combination')
throw new GraphQLError('Invalid email and password combination')
},
async signOut(_parent, _args, context, _info) {
removeTokenCookie(context.res)
Expand Down
@@ -1,4 +1,4 @@
import { makeExecutableSchema } from 'graphql-tools'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { typeDefs } from './type-defs'
import { resolvers } from './resolvers'

Expand Down
14 changes: 11 additions & 3 deletions examples/api-routes-apollo-server-and-client-auth/package.json
Expand Up @@ -6,16 +6,24 @@
"start": "next start"
},
"dependencies": {
"@apollo/client": "^3.0.2",
"@apollo/client": "^3.7.1",
"@apollo/server": "^4.1.1",
"@as-integrations/next": "^1.1.0",
"@graphql-tools/schema": "^9.0.9",
"graphql": "^16.6.0",
"@hapi/iron": "6.0.0",
"apollo-server-micro": "^2.14.2",
"cookie": "^0.4.1",
"deepmerge": "4.2.2",
"graphql": "^14.0.2",
"next": "latest",
"prop-types": "^15.6.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"uuid": "8.1.0"
},
"devDependencies": {
"@types/node": "^18.0.2",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"typescript": "^4.7.4"
}
}

This file was deleted.

@@ -0,0 +1,15 @@
import { ApolloServer } from '@apollo/server'
import { startServerAndCreateNextHandler } from '@as-integrations/next'
import { NextApiRequest, NextApiResponse } from 'next'
import { schema } from '../../apollo/schema'

type ExampleContext = {
req: NextApiRequest
res: NextApiResponse
}

const apolloServer = new ApolloServer<ExampleContext>({ schema })

export default startServerAndCreateNextHandler(apolloServer, {
context: async (req, res) => ({ req, res }),
})
Expand Up @@ -32,8 +32,9 @@ const Index = () => {
if (viewer) {
return (
<div>
You're signed in as {viewer.email} goto <Link href="/about">about</Link>{' '}
page. or <Link href="/signout">signout</Link>
You're signed in as {viewer.email}. Go to{' '}
<Link href="/about">about</Link> page or{' '}
<Link href="/signout">signout</Link>.
</div>
)
}
Expand Down
20 changes: 20 additions & 0 deletions examples/api-routes-apollo-server-and-client-auth/tsconfig.json
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "pages/about.js"],
"exclude": ["node_modules"]
}
2 changes: 1 addition & 1 deletion examples/api-routes-apollo-server-and-client/README.md
@@ -1,6 +1,6 @@
# Apollo Server and Client Example

[Apollo](https://www.apollographql.com/client/) is a GraphQL client that allows you to easily query the exact data you need from a GraphQL server. In addition to fetching and mutating data, Apollo analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run.
[Apollo](https://www.apollographql.com/client/) is a GraphQL client that allows you to easily query the exact data you need from a GraphQL server. In addition to fetching and mutating data, Apollo analyzes your queries and their results to construct a client-side cache of your data, which is kept up to date as further queries and mutations are run. The integration with Next and Apollo Server is implemented using the [apollo-server-integration-next](https://github.com/apollo-server-integrations/apollo-server-integration-next) community package.

In this simple example, we integrate Apollo seamlessly with [Next.js data fetching methods](https://nextjs.org/docs/basic-features/data-fetching) to fetch queries in the server and hydrate them in the browser.

Expand Down
@@ -1,16 +1,15 @@
import { useMemo } from 'react'
import { ApolloClient, InMemoryCache } from '@apollo/client'
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'
import { SchemaLink } from '@apollo/client/link/schema'
import { schema } from '../apollo/schema'
import merge from 'deepmerge'

let apolloClient

function createIsomorphLink() {
if (typeof window === 'undefined') {
const { SchemaLink } = require('@apollo/client/link/schema')
const { schema } = require('./schema')
return new SchemaLink({ schema })
} else {
const { HttpLink } = require('@apollo/client/link/http')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
Expand Down
@@ -1,6 +1,6 @@
export const resolvers = {
Query: {
viewer(_parent, _args, _context, _info) {
viewer() {
return { id: 1, name: 'John Smith', status: 'cached' }
},
},
Expand Down
@@ -1,4 +1,4 @@
import { makeExecutableSchema } from 'graphql-tools'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { typeDefs } from './type-defs'
import { resolvers } from './resolvers'

Expand Down
15 changes: 11 additions & 4 deletions examples/api-routes-apollo-server-and-client/package.json
Expand Up @@ -6,13 +6,20 @@
"start": "next start"
},
"dependencies": {
"@apollo/client": "^3.0.2",
"apollo-server-micro": "^2.14.2",
"@apollo/client": "^3.7.1",
"@apollo/server": "^4.1.1",
"@as-integrations/next": "^1.1.0",
"@graphql-tools/schema": "^9.0.9",
"deepmerge": "4.2.2",
"graphql": "^14.0.2",
"graphql": "^16.6.0",
"next": "latest",
"prop-types": "^15.6.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "^18.0.2",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"typescript": "^4.7.4"
}
}
12 changes: 0 additions & 12 deletions examples/api-routes-apollo-server-and-client/pages/api/graphql.js

This file was deleted.

@@ -0,0 +1,7 @@
import { ApolloServer } from '@apollo/server'
import { startServerAndCreateNextHandler } from '@as-integrations/next'
import { schema } from '../../apollo/schema'

const apolloServer = new ApolloServer({ schema })

export default startServerAndCreateNextHandler(apolloServer)
20 changes: 20 additions & 0 deletions examples/api-routes-apollo-server-and-client/tsconfig.json
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
2 changes: 1 addition & 1 deletion examples/api-routes-apollo-server/README.md
@@ -1,6 +1,6 @@
# Consume local Apollo GraphQL schema to create Static Generation export

Next.js ships with two forms of pre-rendering: [Static Generation](https://nextjs.org/docs/basic-features/pages#static-generation-recommended) and [Server-side Rendering](https://nextjs.org/docs/basic-features/pages#server-side-rendering). This example shows how to perform Static Generation using a local [Apollo GraphQL](https://www.apollographql.com/docs/apollo-server/) schema within [getStaticProps](https://nextjs.org/docs/basic-features/data-fetching/get-static-props) and [getStaticPaths](https://nextjs.org/docs/basic-features/data-fetching/get-static-paths.md). The end result is a Next.js application that uses one Apollo GraphQL schema to generate static pages at build time and also serve a GraphQL [API Route](https://nextjs.org/docs/api-routes/introduction) at runtime.
Next.js ships with two forms of pre-rendering: [Static Generation](https://nextjs.org/docs/basic-features/pages#static-generation-recommended) and [Server-side Rendering](https://nextjs.org/docs/basic-features/pages#server-side-rendering). This example shows how to perform Static Generation using a local [Apollo GraphQL Server ](https://www.apollographql.com/docs/apollo-server/) schema within [getStaticProps](https://nextjs.org/docs/basic-features/data-fetching/get-static-props) and [getStaticPaths](https://nextjs.org/docs/basic-features/data-fetching/get-static-paths.md). The end result is a Next.js application that uses one Apollo GraphQL schema to generate static pages at build time and also serve a GraphQL [API Route](https://nextjs.org/docs/api-routes/introduction) at runtime. The integration with Next and Apollo Server is implemented using the [apollo-server-integration-next](https://github.com/apollo-server-integrations/apollo-server-integration-next) community package.

## Deploy your own

Expand Down
13 changes: 11 additions & 2 deletions examples/api-routes-apollo-server/package.json
Expand Up @@ -7,10 +7,19 @@
"start": "next start"
},
"dependencies": {
"apollo-server-micro": "2.13.1",
"graphql": "15.0.0",
"@apollo/server": "^4.1.1",
"@as-integrations/next": "^1.1.0",
"@graphql-tools/schema": "^9.0.9",
"graphql": "16.6.0",
"graphql-tag": "^2.12.6",
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"typescript": "^4.7.4"
}
}
Expand Up @@ -29,13 +29,14 @@ export async function getStaticProps(context) {
}

export async function getStaticPaths() {
const { users } = await queryGraphql(`
const { users } = (await queryGraphql(`
query {
users {
username
}
}
`)
`)) as { users: { username: string }[] }

return {
paths: users.map(({ username }) => ({
params: { username },
Expand Down
@@ -1,4 +1,7 @@
import { ApolloServer, gql, makeExecutableSchema } from 'apollo-server-micro'
import { ApolloServer } from '@apollo/server'
import { startServerAndCreateNextHandler } from '@as-integrations/next'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { gql } from 'graphql-tag'

const typeDefs = gql`
type Query {
Expand All @@ -10,6 +13,7 @@ const typeDefs = gql`
username: String
}
`

const users = [
{ name: 'Leeroy Jenkins', username: 'leeroy' },
{ name: 'Foo Bar', username: 'foobar' },
Expand All @@ -28,12 +32,8 @@ const resolvers = {

export const schema = makeExecutableSchema({ typeDefs, resolvers })

export const config = {
api: {
bodyParser: false,
},
}

export default new ApolloServer({ schema }).createHandler({
path: '/api/graphql',
const server = new ApolloServer({
schema,
})

export default startServerAndCreateNextHandler(server)
20 changes: 20 additions & 0 deletions examples/api-routes-apollo-server/tsconfig.json
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

1 comment on commit 081b8fb

@dilipdivate
Copy link

Choose a reason for hiding this comment

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

How to connect to mongoose with the above example, tried connecting database but its not working.

Please sign in to comment.