0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

nuxt3とapollo(4系)でGraphQL Serverを実装

Last updated at Posted at 2022-11-19

概要

  • nuxt3とapollo-serverの4系でGraphQLサーバを実装するサンプルを書いた。(2022/11/20 08:52:28)
  • まちがってたらごめんね

準備

  • nuxt3のプロジェクトを作成する。
$ npx nuxi init nuxt-app
$ cd nuxt-app
  • apolloサーバとgraphqlをインストールする。
npm install @apollo/server graphql --save

server/routes に tsファイルを置いてみる

  • 名前は graphql.ts とかにしてみる
apollo.ts
import { readBody, getHeaders, H3Event } from "h3";
import {
  ApolloServer,
  HeaderMap,
  HTTPGraphQLRequest,
  ContextThunk,
  BaseContext,
} from "@apollo/server";

// schema
const typeDefs = `
type Book {
  title: String
  author: String
}
type Query {
  books: [Book]
}
`;

//  data
const books = [
  {
    title: "The Awakening",
    author: "Kate Chopin",
  },
  {
    title: "City of Glass",
    author: "Paul Auster",
  },
];

//  resolver
const resolvers = {
  Query: {
    books: () => books,
  },
};

//
//  sample query
//    query { books{ title author} }
//
//  test url
//    curl --request GET --header 'content-type: application/json' \
//      --url 'http://localhost:3000/api/apollo?query=%7Bbooks%7Btitle%7D%7D'
//
//    curl --request POST --header 'content-type: application/json' \
//      --url 'http://localhost:3000/api/apollo' --data '{"query":"query{books{title}}"}'

// initialize GraphQL server
//process.env.NODE_ENV = "production";
const apolloServer = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== "production",
});
apolloServer.start();

// execute request
const executeRequest = async (event: H3Event) => {
  //console.log("apollo: run event handler");
  const { req, res } = event.node;

  //  conver headers h3->apollo
  const apolloHeaders = new HeaderMap();
  const h3Headers = getHeaders(event);
  for (const k in h3Headers) {
    apolloHeaders.set(k, h3Headers[k] || "");
  }

  // build request object
  const query = req.url ? req.url.split("?", 2)[1] : "";
  const method = req.method || "GET";
  const httpGraphQLRequest: HTTPGraphQLRequest = {
    method,
    headers: apolloHeaders,
    search: method === "GET" ? query : "",
    body: method === "GET" ? "" : await readBody(event),
  };
  // context
  const context: ContextThunk<BaseContext> = async () => {
    return {};
  };

  // execute request
  const httpGraphQLResponse = await apolloServer.executeHTTPGraphQLRequest({
    httpGraphQLRequest,
    context,
  });

  // write response
  if (httpGraphQLResponse.body.kind === "complete") {
    res.end(httpGraphQLResponse.body.string);
  } else {
    for await (const chunk of httpGraphQLResponse.body.asyncIterator) {
      res.write(chunk);
      if (typeof (res as any).flush === "function") {
        (res as any).flush();
      }
    }
    res.end();
  }
};

console.log("apollo server initialized.");
export default defineEventHandler(executeRequest);

起動してURLにアクセス

  • 起動
$ npm run dev

開発環境ならイントロスペクションが開くので

query { books{ title author} }

とか送信してみる。

結果

{
  "data": {
    "books": [
      {
        "title": "The Awakening",
        "author": "Kate Chopin"
      },
      {
        "title": "City of Glass",
        "author": "Paul Auster"
      }
    ]
  }
}

おしまい

  • おしまい。

今後

  • nuxt3で特定のrouteへの接続をwebsocketにupgradeしたい
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?