Skip to content

TypeScript GraphQL for MongoDB — Numio

Generates TypeScript MongoDB document types from a schema annotated with @entity, @id, @column, @link, @embedded and @map, using @graphql-codegen/typescript-mongodb. Each @entity type gets a <Name>DbObject type; fields without a directive are left out.

Keeping the stored MongoDB document shape typed alongside the GraphQL API types of the same entity.

GraphQL Schema

TypeScript MongoDB

When to use it

  • Keeping the stored MongoDB document shape typed alongside the GraphQL API types of the same entity.
  • Seeing how @map paths and @link references translate into nested objects and ObjectId arrays before writing data-access code.

How to use

  1. Paste a schema whose types use @entity and whose fields use @id, @column, @link, @embedded or @map(path: ...).
  2. Read the DbObject types near the end of the output; the GraphQL types themselves are generated above them.
  3. Copy the result into a .ts file; it imports ObjectId from the mongodb package.

GraphQL schema with MongoDB directives

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 types

…
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
}

Details and limitations

@id becomes _id: ObjectId, @link becomes the linked entity's _id (Array<PostDbObject["_id"]> for lists), and @map(path: "login.email") creates a nested login object.

Fields with no directive (no @column, @id, @link, @embedded) are not included in the DbObject type; nullable columns become optional Maybe<T> properties.

The output also contains the standard typescript-plugin types (elided above). Generation runs in a Web Worker in your browser.

FAQ

Do I need to declare the @entity and @column directives in my schema?

No. The plugin adds its own directive definitions, which is also why an AdditionalEntityFields input type appears in the output.

How are embedded documents typed?

A type declared with @entity(embedded: true) gets a DbObject type without _id, and a field marked @embedded references it, for example profile: ProfileDbObject.

Why is a field missing from the DbObject type?

Only fields with @id, @column, @link, @embedded or @map are stored fields. Add @column to include a plain field.

Specifications and references