⚒️

Deno で graphql-codegen する

2023/10/23に公開

はじめに

The Guild がメンテナンスしている https://github.com/dotansimha/graphql-code-generator は、GraphQL の Schema から TypeScript を生成できたりします。
フロントエンドでもバックエンドでも重宝する超便利ライブラリなのですが、Deno で使おうと思った時「あれ。どうやるんだっけ。」となったので調べてみました。

(そこだけ npm 使えばいいやん。という話かもしれないですが、統一できた方がなんか気持ち良かったので ...)

TL;DR

Deno で graphql-codegen を利用したい際には、@graphql-codegen/core を利用しスクリプトを書いて実行する。

https://www.npmjs.com/package/@graphql-codegen/core

deno run --allow-write https://raw.githubusercontent.com/motoya-k/graphql-scalar-sample/main/codegen.example.ts

https://github.com/motoya-k/graphql-scalar-sample/blob/main/codegen.example.ts

【試行錯誤】 Deno で graphql-codegen する方法を考える

Deno CLI の install コマンドを利用する

Deno CLI では install コマンドが提供されています。

https://docs.deno.com/runtime/manual/tools/script_installer

このコマンドによりローカル環境にシェルスクリプトが作成され、特定の名前でスクリプトを実行できるようになります。

例えば、

deno install --allow-net --allow-read -n myfs https://deno.land/std/http/file_server.ts -- -p 8080

とすると、

myfs
> Listening on http://localhost:8080/

でファイルサーバーが http://localhost:8080 で立ち上がります。
これを利用して、@graphql-codegen/cli を実行しようとしてみます。

https://www.npmjs.com/package/@graphql-codegen/cli

deno install -A -n graphql-codegen "npm:@graphql-codegen/cli@5.0.0"

> ✅ Successfully installed graphql-codegen
> /Users/motoyakondo/.deno/bin/graphql-codegen

インストールはうまくいったので実行してみます。

graphql-codegen

> error: '***/Caches/deno/npm/registry.npmjs.org/@graphql-codegen/cli/5.0.0/package.json' did not have a bin entry for '@graphql-codegen/cli'
> 
> Possibilities:
>  * npm:@graphql-codegen/cli@5.0.0/gql-gen
>  * npm:@graphql-codegen/cli@5.0.0/graphql-codegen
>  * npm:@graphql-codegen/cli@5.0.0/graphql-code-generator
>  * npm:@graphql-codegen/cli@5.0.0/graphql-codegen-esm

となってしまい、実行できません。
試しに Possibilities で提示されているエントリポイントを利用してみます。

どれも SyntaxError: await is only valid in async functions and the top level bodies of modules というエラーが出てしまいうまくいきませんでした。

無念 ...。

Script を書いて実行する

困ったなと思って Issue を漁っていたところ以下を発見しました。

https://github.com/dotansimha/graphql-code-generator/issues/6206

@graphql-codegen/cli ではなく @graphql-codegen/core の方を利用して、スクリプトを書けば良いという話でした。

以下のようなスクリプトを用意し、このファイルを実行します。

codegen.ts
import { codegen } from "npm:@graphql-codegen/core@4.0.0";
import * as typescriptResolversPlugin from "npm:@graphql-codegen/typescript-resolvers@2.7.7";
import { TypeScriptResolversPluginConfig } from "npm:@graphql-codegen/typescript-resolvers@2.7.7";
import * as typescriptPlugin from "npm:@graphql-codegen/typescript@2.8.2";
import { TypeScriptPluginConfig } from "npm:@graphql-codegen/typescript@2.8.2";
import { GraphQLSchema, buildSchema, parse, printSchema } from "npm:graphql@16.8.1";

const typeDefs = /* GraphQL */`
  type User {
    id: ID!
    name: String!
    age: Int!
  }
  type Query {
    users: [User!]!
    user(id: ID!): User
  }
  type Mutation {
    createUser(name: String!, age: Int!): User!
  }
`

const schema: GraphQLSchema = buildSchema(typeDefs);
const outputFile = "./resolvers_types.ts";
const typescriptPluginConfig: TypeScriptPluginConfig = {}
const typescriptResolversPluginConfig: TypeScriptResolversPluginConfig = {}
const config: Parameters<typeof codegen>[number] = {
  documents: [],
  config: {},
  filename: outputFile,
  schema: parse(printSchema(schema)),
  plugins: [
    {
      // ref: https://the-guild.dev/graphql/codegen/plugins/typescript/typescript
      typescript: typescriptPluginConfig,
    },
    {
      // ref: https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-resolvers
      typescriptResolvers: typescriptResolversPluginConfig,
    },
  ],
  pluginMap: {
    typescript: typescriptPlugin,
    typescriptResolvers: typescriptResolversPlugin,
  },
};

const output = await codegen(config);
await Deno.writeFile(outputFile, new TextEncoder().encode(output));
console.log("Outputs generated! 🚀");

Deno のカスタムコマンドを登録しておくと使い勝手が良いかもしれません。

node.json
{
  "tasks": {
    "codegen": "deno run -A codegen.ts"
  }
}
deno task codegen

この方法では無事、型ファイルを生成できました!良かった😊
手元で Deno を動かせる方は、以下のコマンドで実際の動作を確認することができます。

deno run --allow-write https://raw.githubusercontent.com/motoya-k/graphql-scalar-sample/main/codegen.example.ts

Discussion