graphql + mongoose + typescript, how to reduce model definition duplicated
Asked Answered
N

2

12

I use mongoose, typescript and graphql to build my app.

I am a full-stack developer.

The problem is I define the fields and types of model FIVE times.

server side:

models/book.ts:

// first time
interface IBook extends mongoose.Document {
  title: string;
  author: string;
} 

// second time
const bookSchema = new mongoose.Schema({
  title: String,
  author: String
})

const Book: mongoose.Model<IBook> = mongoose.model<IBook>('Book', bookSchema)

graphql/typeDefs.ts

const typeDefs = `
  // third time
  type Book {
    title: String!
    author: String!
  }

  // fourth time
  input BookInput {
    title: String!
    author: String!
  }
`

client side:

interfaces/book.ts

// fifth time
interface IBook {
  title: string;
  author: string;
}

As you can see. the title and author fields and types are defined FIVE times.

There are three main disadvantages:

  1. duplicated
  2. lack of maintainability
  3. inefficient

Is there a way to solve this? I think this is almost a DRY problem.

Here are my thinkings:

  1. universal app - extract some common modules used in client and server side.
  2. make a tool handle this.

    • make a project generator or command line tool like ng-cli for generating model and types statically which means before the run-time

    • make model definition decorator or syntax sugar generate model and types dynamically at run-time

Nelia answered 8/8, 2018 at 6:46 Comment(5)
Is there a solution yet? I like using TypeScript and Mongoose, but I am new to GraphQL and this is the very first problem that appears in my mind.Heartburning
@Heartburning Not yet. Still do not find a solution handle these "duplicated" code.Nelia
Maintain mongoose schema and graphql schema separately as they have different data types. Use Javascript object to avoid duplicate in mongoose and Types to avoid duplicate in GraphQL.Fourteenth
I found a module typegraphql.ml, it's useful enough for meNelia
Thus far, this plugin is the best things I've found: graphql-code-generator.com/docs/getting-started It looks like it will handle the graphql/typescript repetition. Unfortunately, there is currently no mongoose plugin, but there is a MongoDB plugin. I'm going to start looking into how to use that to make the schemas.Bumboat
A
2

We recently ran into this issue, requiring us to maintaining a duplicated Typescript interface alongside our Mongoose schemas (for us the issue was solely server-side as we are not using graphql or client-side Typescript)

We built mongoose-tsgen to address this. It may not handle all cases concerned here, but could be easily bootstrapped to handle your use case.

It reads your Mongoose schemas and generates an index.d.ts file which includes an interface for each document and subdocument. These interfaces can be imported from the mongoose module directly like so:

import { IUser } from "mongoose"

async function getUser(uid: string): IUser {
  // `user` is of type IUser
  const user = await User.findById(uid)
  return user;
}

Alegre answered 11/10, 2020 at 15:14 Comment(0)
N
1

In case anyone is still wondering,

You can use TypeGraphQL together with Typegoose to create all the schemas within one single class with decorators like this:

@ObjectType()
export class Book{

@Field() @prop({ required: true })
title!: string;

@Field() @prop({ required: true })
name!: string;
}
Nereen answered 23/12, 2020 at 19:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.