NestJS の GraphQL のスキーマから API ドキュメントを自動生成する

spectaql を使って、 schema.gql を HTML のドキュメントに変換していきます。

https://github.com/anvilco/spectaql

次の画像のように、GrapqhQL のスキーマからAPIリファレンスが生成できます。サンプルのクエリもあるので、クエリを実行するときに便利です。

ドキュメントを格納するディレクトリを作成

shell
mkdir -p ./docs/graphql/spectaql/

spectaql の config.yml を配置

docs/graphql/spectaql ディレクトリに、config.yml を作ります。

config.yml
spectaql:
  Default: "spectaql"
  displayAllServers: true

introspection:
  schemaFile: ./src/schema.gql

extensions:
  graphqlScalarExamples: true

info:
  title: GraphQL API Reference
  description: APIリファレンス

servers:
  - url: https://staging.example.com/graphql
    description: Staging

設定は色々とあります。上の設定は最低限です。他の設定はサンプルを見てみてください。

https://github.com/anvilco/spectaql/blob/main/examples/config.yml

package.json に doc コマンドを作成

package.json の scripts 以下に doc を作ります。

package.json
"doc": "npx spectaql --target-dir ./docs/graphql ./docs/graphql/spectaql/config.yml",

ドキュメントを生成

shell
npm run doc

コマンドを実行すると、 docs/graphql 以下に index.html が作成されます。

この index.html をブラウザで開くと、ドキュメントが表示されます。ドキュメントとスキーマは別のチームに渡してあげると、開発が捗るでしょう。

なお、 schema.gql は NestJS の app.module.ts で自動で出力されるように設定しています。

app.module.ts
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: 'src/schema.gql',
      sortSchema: true,
    }),

app.module.ts 全体は以下のようになっています。

app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import configration from './config/configration';
import { TypeOrmModule } from '@nestjs/typeorm';
import { NotesModule } from './notes/notes.module';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [configration],
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (configService: ConfigService) => ({
        type: 'mariadb',
        host: configService.get<string>('database.host'),
        port: configService.get<number>('database.port'),
        username: configService.get<string>('database.username'),
        password: configService.get<string>('database.password'),
        database: configService.get<string>('database.database'),
        synchronize: configService.get<boolean>('database.synchronize'),
        autoLoadEntities: true,
        charset: 'utf8mb4',
      }),
      inject: [ConfigService],
    }),
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: 'src/schema.gql',
      sortSchema: true,
    }),
    NotesModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}