Skip to content

Commit

Permalink
Merge branch 'canary' into chore-update-ncc
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] committed May 23, 2022
2 parents 09b1167 + 874957e commit 3243113
Show file tree
Hide file tree
Showing 32 changed files with 461 additions and 57 deletions.
19 changes: 18 additions & 1 deletion examples/api-routes-graphql/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
# API routes with GraphQL server

Next.js ships with [API routes](https://nextjs.org/docs/api-routes/introduction), which provide an easy solution to build your own `API`. This example shows their usage alongside [apollo-server-micro](https://github.com/apollographql/apollo-server/tree/main/packages/apollo-server-micro) to provide simple GraphQL server consumed by Next.js app.
Next.js ships with [API routes](https://nextjs.org/docs/api-routes/introduction), which provide an easy solution to build your own `API`.
This example showcases how to build a lightweight and blazing fast GraphQL API with minimum configuration using GraphQL Yoga.

GraphQL Yoga comes with strong defaults:

- CORS is enabled by default
- Automatically masking unexpected errors and preventing sensitive information from leaking to clients.
- Shipped with GraphiQL

Yoga also brings support (with no additional dependency) for subscriptions, file uploads, and your favorite schema-building library (GraphQL Tools, Pothos, Nexus, TypeGraphQL, SDL first schema-design approaches, graphql-js, Apollo Tools).

More information on all available features are available [on the official documentation](https://www.graphql-yoga.com/docs/quick-start).

Finally, GraphQL Yoga is built on top of Envelop. Envelop is a library that helps build GraphQL API faster and flexibly with plugin-based architecture.

Similar to Express middlewares allowing you to customize requests' behavior, Envelop applies the same idea to GraphQL requests.

More information on [Envelop documentation](https://www.envelop.dev/).

## Deploy your own

Expand Down
5 changes: 2 additions & 3 deletions examples/api-routes-graphql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
"start": "next start"
},
"dependencies": {
"apollo-server-micro": "^3.0.1",
"graphql": "^15.5.1",
"micro": "^9.3.4",
"@graphql-yoga/node": "^2.2.1",
"graphql": "^16.3.0",
"next": "latest",
"react": "^17.0.2",
"react-dom": "^17.0.2",
Expand Down
42 changes: 11 additions & 31 deletions examples/api-routes-graphql/pages/api/graphql.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ApolloServer, gql } from 'apollo-server-micro'
import { createServer } from '@graphql-yoga/node'

const typeDefs = gql`
const typeDefs = /* GraphQL */ `
type Query {
users: [User!]!
}
Expand All @@ -17,33 +17,13 @@ const resolvers = {
},
}

const apolloServer = new ApolloServer({ typeDefs, resolvers })

const startServer = apolloServer.start()

export default async function handler(req, res) {
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader(
'Access-Control-Allow-Origin',
'https://studio.apollographql.com'
)
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
)
if (req.method === 'OPTIONS') {
res.end()
return false
}

await startServer
await apolloServer.createHandler({
path: '/api/graphql',
})(req, res)
}

export const config = {
api: {
bodyParser: false,
const server = createServer({
schema: {
typeDefs,
resolvers,
},
}
endpoint: '/api/graphql',
// graphiql: false // uncomment to disable GraphiQL
})

export default server
37 changes: 37 additions & 0 deletions examples/with-graphql-gateway/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo

.mesh/
6 changes: 6 additions & 0 deletions examples/with-graphql-gateway/.meshrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sources:
- name: PetStore
handler:
newOpenapi:
baseUrl: https://petstore.swagger.io/v2/
oasFilePath: https://petstore.swagger.io/v2/swagger.json
61 changes: 61 additions & 0 deletions examples/with-graphql-gateway/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# GraphQL Gateway using GraphQL Mesh and Next.js API routes

This is a simple set up for Next.js using [GraphQL Mesh](https://www.graphql-mesh.com/docs/introduction) to build a GraphQL Gateway based on a REST API.

GraphQL Mesh is a framework that allows to build GraphQL Gateway server, based on one or multiple source APIs (REST, SOAP, gRPC, GraphQL or Databases).

```mermaid
graph TD;
subgraph AA [" "]
A[Mobile app];
B[Web app];
C[Node.js client];
end
subgraph BB [" "]
E[REST API];
F[GraphQL API];
G[SOAP API];
end
Z[GraphQL Gateway API on a Next.js API route];
A & B & C --> Z;
Z --> E & F & G;
```

Configuring GraphQL Mesh only requires installing the required packages and providing a `.meshrc.yaml` configuration file.

This project translate the PetStore REST API (https://petstore.swagger.io/) to a GraphQL API by simply providing the following configuration:

_[`.meshrc.yaml`](./.meshrc.yaml)_

```yaml
sources:
- name: PetStore
handler:
newOpenapi:
baseUrl: https://petstore.swagger.io/v2/
oasFilePath: https://petstore.swagger.io/v2/swagger.json
```
More information on GraphQL Mesh configuration and concepts [are available in our documentation](https://www.graphql-mesh.com/docs/getting-started/overview).
---
## Deploy your own
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-graphql-gateway&project-name=with-graphql-gateway&repository-name=with-graphql-gateway&env=NEO4J_URI,NEO4J_USER,NEO4J_PASSWORD&envDescription=Required%20to%20connect%20the%20app%20with%20a%20Neo4j%20database&envLink=https://github.com/vercel/next.js/tree/canary/examples/with-graphql-gateway%23step-3-set-up-environment-variables)
---
## How to use
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:

```bash
npx create-next-app --example with-graphql-gateway with-graphql-gateway-app
# or
yarn create next-app --example with-graphql-gateway with-graphql-gateway-app
# or
pnpm create next-app -- --example with-graphql-gateway with-graphql-gateway-app
```
5 changes: 5 additions & 0 deletions examples/with-graphql-gateway/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
6 changes: 6 additions & 0 deletions examples/with-graphql-gateway/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}

module.exports = nextConfig
28 changes: 28 additions & 0 deletions examples/with-graphql-gateway/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"private": true,
"scripts": {
"prestart": "yarn build:mesh",
"start": "next dev",
"prebuild": "yarn build:mesh",
"build": "next build",
"start:prod": "next start",
"build:mesh": "mesh build"
},
"dependencies": {
"@graphql-mesh/cli": "0.68.1",
"@graphql-mesh/config": "0.35.1",
"@graphql-mesh/new-openapi": "0.4.10",
"@graphql-mesh/runtime": "0.34.1",
"@graphql-yoga/node": "latest",
"graphql": "16.3.0",
"next": "latest",
"react": "18.0.0",
"react-dom": "18.0.0"
},
"devDependencies": {
"@types/node": "17.0.24",
"@types/react": "18.0.5",
"@types/react-dom": "18.0.1",
"typescript": "4.6.3"
}
}
8 changes: 8 additions & 0 deletions examples/with-graphql-gateway/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}

export default MyApp
29 changes: 29 additions & 0 deletions examples/with-graphql-gateway/pages/api/graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
import { createServer } from '@graphql-yoga/node'

import { getBuiltMesh } from '../../.mesh'

async function buildServer() {
// retrieve the mesh instance (with configured Envelop plugins)
const mesh = await getBuiltMesh()
// pass the Mesh instance to Yoga and configure GraphiQL
const server = createServer({
plugins: mesh.plugins,
graphiql: {
endpoint: '/api/graphql',
title: 'GraphQL Gateway',
},
})

return server
}

const server$ = buildServer()

export default async function apiHandler(
req: NextApiRequest,
res: NextApiResponse
) {
return (await server$).requestListener(req, res)
}
72 changes: 72 additions & 0 deletions examples/with-graphql-gateway/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'

const Home: NextPage = () => {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>

<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</h1>

<p className={styles.description}>
Get started by editing{' '}
<code className={styles.code}>pages/index.tsx</code>
</p>

<div className={styles.grid}>
<a href="https://nextjs.org/docs" className={styles.card}>
<h2>Documentation &rarr;</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>

<a href="https://nextjs.org/learn" className={styles.card}>
<h2>Learn &rarr;</h2>
<p>Learn about Next.js in an interactive course with quizzes!</p>
</a>

<a
href="https://github.com/vercel/next.js/tree/canary/examples"
className={styles.card}
>
<h2>Examples &rarr;</h2>
<p>Discover and deploy boilerplate example Next.js projects.</p>
</a>

<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
>
<h2>Deploy &rarr;</h2>
<p>
Instantly deploy your Next.js site to a public URL with Vercel.
</p>
</a>
</div>
</main>

<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
)
}

export default Home
Binary file added examples/with-graphql-gateway/public/favicon.ico
Binary file not shown.
4 changes: 4 additions & 0 deletions examples/with-graphql-gateway/public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 3243113

Please sign in to comment.