Type-graphql: Rebuilding schema results in failure due to default value analysis

Created on 19 Feb 2021  路  3Comments  路  Source: MichalLytek/type-graphql

Describe the Bug
When buildSchema has been called once, future calls result in an exception being thrown due to default value conflicts. Examples of the error are:

The 'created' field of 'ArchiveInput' has conflicting default values. Default value from decorator ('Fri Feb 19 2021 10:58:17 GMT+0100 (Central European Standard Time)') is not equal to the property initializer value ('Fri Feb 19 2021 10:58:27 GMT+0100 (Central European Standard Time)').

The 'cordova' field of 'SupportArchiveInput' has conflicting default values. Default value from decorator ('[object Object]') is not equal to the property initializer value ('[object Object]').

To Reproduce
The root cause seems to be a = new Date() initializer in the target class. As a new instance of the class is constructed during schema generation, to retrieve default values from the class instance, the second call has a more recent timestamp.

@InputType("ArchiveInput")
@ObjectType()
export class Archive {
    @Field(is => Date)
    created = new Date();
}

This also affects other cases where a complex default object is assigned with x = new Complex() in the class.

I created a full repro at https://github.com/oliversalzburg/double-build-repro

Expected Behavior
buildSchema calls should be idempotent.

Additionally, assigning a default value in the graph through this mechanism wasn't intentional. It was purely meant as a measure to initialize locally constructed instances of that class.

Environment (please complete the following information):

  • OS: Windows 10
  • Node v14.15.4
  • Package version 1.1.1
  • TypeScript version 4.1.5

Additional Context
https://github.com/MichalLytek/type-graphql/blob/73736e271a7df053ab5df057ef37db328ba49dd0/src/schema/schema-generator.ts#L498

Bug Community Solved

All 3 comments

imho this is a design problem of your API. i faced the same in my current project. you never want to use "dependant values" as default values. while type-graphql could avoid this specific error, it is still strange, if you compare a schema generated (via introspection) an hour ago with a current one. they should be equal, but they are not.

possible solutions:

  • make it nullable and add the fallback in your resolver, while documenting that passing null, will result to the "current" date
  • create a new scalar which allows the use of "now" as a placeholder for "the current date".

in my API i ended up creating a "RelativeDateTime" which i use in almost all input positions, it supports "now" (which uses the query date), ISO duration (which is resolved to a date time by adding it to the query date) and absolute ISO dates.

if you compare a schema generated (via introspection) an hour ago with a current one. they should be equal, but they are not.

I fully agree.

This behavior is unexpected, as I had no intention to even affect the API in this manner. All I wanted to achieve, was that I have a default value _when I locally construct an instance of the class_, like in a test. There is a specific defaultValue setting that I can and do use when I want to set default values. I didn't expect any magic to happen beyond that.

Type-GraphQL, by applying this default value detection magic, prevents this use case entirely. I end up declaring an input schema (where the input value is nullable and then set in a resolver), an output schema (where the value isn't nullable) and a class to internally represent the same schema, but which sets default values upon construction. This is something I was hoping to avoid by using the library in the first place.

I'm happy to accept that this 3-model-approach is ultimately the correct one for what I'm trying to achieve. I just wasn't expecting this and the root cause is unsettling. I don't feel in control of what's happening. I'd much rather like to disable this default value detection entirely.

Closing via 5f864a26 馃敀

Opening a separate ticket for tracking the implicit default value magic issue: https://github.com/MichalLytek/type-graphql/issues/793

Was this page helpful?
0 / 5 - 0 ratings