跳到主要内容

数据驱动:生成MongoDB用TypeScript GraphQL — Numio

使用 @graphql-codegen/typescript-mongodb,根据带有 @entity、@id、@column、@link、@embedded 和 @map 注解的 schema 生成 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: ...) 的 schema。
  2. 在输出末尾附近查看 DbObject 类型;GraphQL 类型本身生成在它们上方。
  3. 将结果复制到 .ts 文件中;它会从 mongodb 包导入 ObjectId。

带 MongoDB 指令的 GraphQL schema

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 类型中;可空的 column 变为可选的 Maybe<T> 属性。

输出中还包含标准 typescript 插件生成的类型(上例中已省略)。生成在浏览器的 Web Worker 中运行。

FAQ

需要在 schema 中声明 @entity 和 @column 指令吗?

不需要。插件会添加自己的指令定义,这也是输出中出现 AdditionalEntityFields input 类型的原因。

嵌入文档如何类型化?

用 @entity(embedded: true) 声明的类型会得到一个不含 _id 的 DbObject 类型,标记了 @embedded 的字段会引用它,例如 profile: ProfileDbObject。

为什么 DbObject 类型中缺少某个字段?

只有带 @id、@column、@link、@embedded 或 @map 的字段才是存储字段。为普通字段加上 @column 即可包含它。

规范与参考资料