graphql-compose / graphql-compose-mongoose

Mongoose model converter to GraphQL types with resolvers for graphql-compose https://github.com/nodkz/graphql-compose
MIT License
709 stars 94 forks source link

Inconsistency with mongoose custom types #411

Open Zleub opened 1 year ago

Zleub commented 1 year ago

Hello !

Before all, i've been fiddling with this library for a few months now, thank you for putting work into it ! That's a really nice idea.

I've noticed a small issue with how mongoose is handling types on their side : a mongoose path can be either declared as a reference to the subschema directly or as the name of the custom type (if registered in mongoose beforehand)

This leads to compose-mongoose not being able to pick up a custom type and typing it as JSON.

Here a example you can run, the main thing to notice being the declaration of UserProfile and Article schemas :

import mongoose, { Schema } from 'mongoose';
import { schemaComposer } from 'graphql-compose'; // get the default schemaComposer or your created schemaComposer
import { convertSchemaToGraphQL } from 'graphql-compose-mongoose';
import { composeMongoose } from 'graphql-compose-mongoose';

// the embedded schema
const ImageDataStructure = new Schema({
  url: String,
  dimensions : {
    width: Number,
    height: Number
  }
}, { _id: false });

// A class declaration of a schemaType so mongoose is pleased
class IMG extends mongoose.SchemaType {
    constructor(key: string, options: any) {
      super(key, options, 'ImageDataStructure');
    }

    cast(val: any) { return val; }
  }

/* @ts-ignore */
mongoose.SchemaTypes["ImageDataStructure"] = IMG

const UserProfile = new Schema({
  fullName: String,
  personalImage: ImageDataStructure
});

const Article = new Schema({
  title: String,
  heroImage: "ImageDataStructure"
});

convertSchemaToGraphQL(ImageDataStructure, 'ImageDataStructure', schemaComposer); // Force this type on this mongoose schema

const UserProfileModel = mongoose.model('UserProfile', UserProfile);
const ArticleModel = mongoose.model('Article', Article);

const UserProfileTC = composeMongoose(UserProfileModel);
const ArticleTC = composeMongoose(ArticleModel);

schemaComposer.Query.addFields({
    userById: UserProfileTC.mongooseResolvers.findById(),
    articleById: ArticleTC.mongooseResolvers.findById(),
})

schemaComposer.buildSchema()
console.log( schemaComposer.toSDL() )

Which lead to the following output (truncated) :

type Article {
  title: String
  heroImage: JSON
  _id: MongoID!
}

type ImageDataStructure {
  url: String
  dimensions: ImageDataStructureDimensions
}

type ImageDataStructureDimensions {
  width: Float
  height: Float
}

type UserProfile {
  fullName: String
  personalImage: ImageDataStructure
  _id: MongoID!
}

UserProfile.personalImage is correct (as a ImageDataStructure) while Article.heroImage is typed as JSON.

Did i miss something to get this to work properly ?

Have a good day !