GraphQL

更新:2025-03-23
Query
概要
「GraphQL」は、API向けクエリ言語。
プロジェクト
Node.jsのプロジェクトを作成。
npm init -y
ESMで記述したいので、type
を追記しておく。
{ .. "type": "module"}
開発環境
モジュールの追加
npm i apollo-server graphql typescript @types/graphql @types/node
モジュール名 | 簡易説明 |
---|---|
apollo-server | GraphQLサーバー |
graphql | GraphQL |
typescript | TypeScript |
@types/graphql | GraphQLの型 |
@types/node | Node.jsの型 |
npm i -D @graphql-codegen/cli @graphql-codegen/typescript tsx
モジュール名 | 簡易説明 |
---|---|
@graphql-codegen/cli | GraphQL Code GeneratorのCLI |
@graphql-codegen/typescript | TypeScriptの型を生成するプラグイン |
tsx | TypeScriptファイルを実行するCLI |
実装
スキーマの作成
スキーマは、APIのデータ構造を定義する役割。たとえば何かのモンスターに関するデータを用意してみる。
import { gql } from 'apollo-server';
const typeDefs = gql` type Query { monsters: [Monster!]! }
type Monster { id: ID! name: String! element: Element! }
enum Element { Fire Water Earth Wind Thunder }`;
export default typeDefs;
idはNumber
やString
でもいけるが、ID
を指定することでユニークであることを表現できる。
型の生成
schema.ts
からtypes.ts
を生成する設定を用意。
schema: "schema.ts"generates: types.ts: plugins: - "typescript"
GraphQL Code Generatorで生成。
npx graphql-codegen
以下のようなファイルが生成された。
export type Maybe<T> = T | null;export type InputMaybe<T> = Maybe<T>;export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };/** All built-in and custom scalars, mapped to their actual values */export type Scalars = { ID: { input: string; output: string; } String: { input: string; output: string; } Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; }};
export enum Element { Earth = 'Earth', Fire = 'Fire', Thunder = 'Thunder', Water = 'Water', Wind = 'Wind'}
export type Monster = { __typename?: 'Monster'; element: Element; id: Scalars['ID']['output']; name: Scalars['String']['output'];};
export type Query = { __typename?: 'Query'; monsters: Array<Monster>;};
リゾルバーの作成
リゾルバーは、クエリに対してデータを返す役割。
import { IResolvers } from '@graphql-tools/utils';
// 生成した型が使えるので、自分でinterfaceを定義する必要がないimport { Monster, Element } from './types'
// 適当なモンスターデータを用意const monsters: Monster[] = [ { id: '001', name: 'AAAAA', element: Element.Fire }, { id: '002', name: 'BBBBB', element: Element.Water }, { id: '003', name: 'CCCCC', element: Element.Earth }, { id: '004', name: 'DDDDD', element: Element.Wind }, { id: '005', name: 'EEEEE', element: Element.Thunder }];
const resolvers: IResolvers = { Query: { monsters: (): Monster[] => monsters }};
export default resolvers;
サーバの作成
import { ApolloServer } from 'apollo-server';import typeDefs from './schema';import resolvers from './resolvers';
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => { console.log(`Local: ${url}`);});
実行
npx tsx index# http://localhost:4000/
「Query your server」でGUIにアクセスできるので、クエリを実行すればデータが取得できる。
query { monsters { name }}
{ "data": { "monsters": [ { "name": "AAAAA" }, { "name": "BBBBB" }, { "name": "CCCCC" }, { "name": "DDDDD" }, { "name": "EEEEE" } ] }}
続く...かもね