graphql-compose / graphql-compose-mongoose

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

defaultsAsNonNull falsely reports non-nullability for subdocuments that have a Schema #358

Closed toverux closed 2 years ago

toverux commented 3 years ago

Hi @nodkz,

I noticed a small bug in the behaviour of { defaultsAsNonNull: true } when a Schema embeds another Schema.

Here is a simple repro:

const schema = new Schema({
    subDocument: new Schema({
    })
});

const myModel = model('model', schema);

const tc = composeMongoose(myModel, { defaultsAsNonNull: true });

console.log(tc.getFieldType('subDocument')); // "modelSubDocument!"

console.log(new myModel().toJSON()); // "{ _id: 60f9cdff3d826d1e92a34c14 }"

As you can see, the subDocument field is typed as non-nullable modelSubDocument!, but as you can see, once a document instance is created, the property is not defined. (In this case, Compose detects a default value because of the _id property that Schema is automatically adding, and _id has a default value getter.)

Investigating a little bit more shows that a sub-Schema breaks the "recursive default value assignation" behavior that can be observed with classic subdocuments definitions ({} instead of new Schema({})). Anything that is under a Schema will not be automatically set according to default values unless the user manually creates that host object.

If you want to test it with just mongoose alone first:

In this case graphql-compose-mongoose gets nullability right:

const schema = new Schema({
    subDocument: {
        field: { type: String, default: 'Hey' }
    }
});

const myModel = model('model', schema);

console.log(new myModel().subDocument); // { field: 'Hey' }

In this case graphql-compose-mongoose gets nullability wrong:

const schema = new Schema({
    subDocument: new Schema({
        field: { type: String, default: 'Hey' }
    })
});

const myModel = model('model', schema);

console.log(new myModel().subDocument); // undefined
github-actions[bot] commented 2 years ago

:tada: This issue has been resolved in version 9.5.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

toverux commented 2 years ago

Hi @nodkz, I think I've noticed a small bug in this feature: while it works perfectly for subdocuments now, simple arrays are now always marked as non-nullable even if they have no default value.

For example:

const schema = new Schema({ tags: [String] });

With defaultsAsNonNull: true, this produces the following GraphQL schema:

type Schema {
  tags: [String]!
}

However, mongoose does not provides a default value (ie. []) for such an array. Therefore an error is thrown if this field is accessed on a document that does not have it.

I'm sorry to bother you with this again, I wish mongoose had a better API for you to introspect types.