本文へスキップ

MongoDBのためのTypeScript GraphQLジェネレーター — Numio

@graphql-codegen/typescript-mongodb を使って、@entity、@id、@column、@link、@embedded、@map で注釈したスキーマから TypeScript の MongoDB ドキュメント型を生成します。@entity の型ごとに <Name>DbObject 型ができ、ディレクティブのないフィールドは含まれません。

同じエンティティについて、MongoDB に保存するドキュメントの形を GraphQL API の型と並べて型付きに保つ。

GraphQL Schema

TypeScript MongoDB

こんなときに使えます

  • 同じエンティティについて、MongoDB に保存するドキュメントの形を GraphQL API の型と並べて型付きに保つ。
  • データアクセスのコードを書く前に、@map のパスや @link の参照がネストしたオブジェクトや ObjectId の配列にどう変換されるかを確認する。

使い方

  1. 型に @entity、フィールドに @id、@column、@link、@embedded、@map(path: ...) を使ったスキーマを貼り付けます。
  2. 出力の末尾近くにある DbObject 型を確認します。GraphQL の型自体はその上に生成されます。
  3. 結果を .ts ファイルにコピーします。mongodb パッケージから ObjectId をインポートします。

MongoDB ディレクティブ付き GraphQL スキーマ

type User @entity {
  id: ID! @id
  email: String! @column @map(path: "login.email")
  profile: Profile! @embedded
  posts: [Post!]! @link
}

type Profile @entity(embedded: true) {
  name: String! @column
}

type Post @entity {
  id: ID! @id
  title: String! @column
}

TypeScript の DbObject 型

…
export type AdditionalEntityFields = {
  path?: InputMaybe<Scalars["String"]["input"]>
  type?: InputMaybe<Scalars["String"]["input"]>
}

import { ObjectId } from "mongodb"
export type UserDbObject = {
  _id: ObjectId
  login: {
    email: string
  }
  profile: ProfileDbObject
  posts: Array<PostDbObject["_id"]>
}

export type ProfileDbObject = {
  name: string
}

export type PostDbObject = {
  _id: ObjectId
  title: string
}

仕様と制限

@id は _id: ObjectId に、@link はリンク先エンティティの _id(リストなら Array<PostDbObject["_id"]>)になり、@map(path: "login.email") はネストした login オブジェクトを作ります。

ディレクティブのないフィールド(@column、@id、@link、@embedded のいずれもないもの)は DbObject 型に含まれません。nullable な column は省略可能な Maybe<T> プロパティになります。

出力には標準の typescript プラグインの型も含まれます(上の例では省略)。生成はブラウザの Web Worker で実行されます。

FAQ

スキーマで @entity や @column ディレクティブを宣言する必要はありますか?

ありません。プラグインが独自のディレクティブ定義を追加します。出力に AdditionalEntityFields という input 型が現れるのもそのためです。

埋め込みドキュメントはどう型付けされますか?

@entity(embedded: true) で宣言した型には _id のない DbObject 型ができ、@embedded を付けたフィールドがそれを参照します。例:profile: ProfileDbObject。

DbObject 型にフィールドがないのはなぜですか?

保存対象のフィールドになるのは @id、@column、@link、@embedded、@map のいずれかを持つものだけです。普通のフィールドを含めるには @column を付けてください。

仕様を確認する