Skip to content

Default values for nested input objects #385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
eknkc opened this issue May 7, 2016 · 7 comments
Closed

Default values for nested input objects #385

eknkc opened this issue May 7, 2016 · 7 comments

Comments

@eknkc
Copy link

eknkc commented May 7, 2016

Hi,

It seems that if a nested input object is not supplied, the default values are not applied either;

const SomeConfig = new GraphQLInputObjectType({
  name: "X",
  fields: {
    foo: { type: GraphQLInt, defaultValue: 0 }
  }
})

const Query = new GraphQLObjectType({
  name: "Query",
  fields: {
    someQuery: {
      type: GraphQLString,
      args: {
        bar: { type: SomeConfig, defaultValue: {} }
      },
      resolve(parent, args) {
       // if no bar is supplied and bar has no defaultvalue, args.bar is null, this is expected.
       // if bar arg has a defaultValue: {} as above
       // args.bar.foo is not populated, args becomes {}
      }
     }
  }  
});

How can I make sure that the entire nested argument graph is populated with their default values?

@leebyron
Copy link
Contributor

leebyron commented May 9, 2016

Thanks for bringing this up! Currently this indirect default values isn't supported, so you would have to manually write { foo: 0 } as the default value for your bar argument. This is interesting and deserves more thought, so leaving this issue open.

@eknkc
Copy link
Author

eknkc commented May 9, 2016

Thanks!

I thought about writing a "extractDefault" function to create the default parameter for entire input object. Gonna need to call "getFields" on the input type to reflect on the inner fields and default values but getFields does not seem to be documented. Is it an internal API or safe to use?

Ekin Koc

On 9 May 2016 at 21:09:41, Lee Byron ([email protected](mailto:[email protected])) wrote:

Thanks for bringing this up! Currently this indirect default values isn't supported, so you would have to manually write { foo: 0 } as the default value for your bar argument. This is interesting and deserves more thought, so leaving this issue open.


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub(#385 (comment))

@yaquawa
Copy link

yaquawa commented Nov 21, 2018

any progress on this ?? it has been 2 years!

@IvanGoncharov
Copy link
Member

Sorry for the delay.
graphql-js implemented according to the spec so this change should be first added there.
If someone wants to be champion for this proposal here is the description of workflow:
https://github.com/facebook/graphql/blob/master/CONTRIBUTING.md#rfc-contribution-stages

@Sytten
Copy link

Sytten commented Jul 20, 2020

The closing of this feels a bit weird, did someone manage to open an RFC for that?

@benjie
Copy link
Member

benjie commented Nov 13, 2020

It seems obvious to me that the defaultValue should be coerced to match the type in the same way that a supplied argument would at runtime (otherwise it breaks the type safety guarantees of GraphQL); however @IvanGoncharov is correct that this is not specified in the GraphQL Spec, so I have opened an RFC here:

graphql/graphql-spec#793

And added it to the next GraphQL WG:

https://github.com/graphql/graphql-wg/blob/master/agendas/2020-12-03.md#agenda

@benjie
Copy link
Member

benjie commented Nov 13, 2020

In the mean time; here's a JS file that reproduces this issue:

const {
  graphqlSync,
  printSchema,
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLInputObjectType,
  GraphQLInt,
} = require("graphql");

const ExampleInputObject = new GraphQLInputObjectType({
  name: "ExampleInputObject",
  fields: {
    number: {
      type: GraphQLInt,
      defaultValue: 3,
    },
  },
});

const Query = new GraphQLObjectType({
  name: "Query",
  fields: {
    example: {
      args: {
        inputObject: {
          type: ExampleInputObject,
          defaultValue: {},
        },
      },
      type: GraphQLInt,
      resolve(source, args) {
        return args.inputObject.number;
      },
    },
  },
});

const schema = new GraphQLSchema({
  query: Query,
});

console.log(printSchema(schema));

// All three of these should be equivalent?
const source = /* GraphQL */ `
  query A {
    example
  }
  query B {
    example(inputObject: {})
  }
  query C {
    example(inputObject: { number: 3 })
  }
`;
const result1 = graphqlSync({ schema, source, operationName: "A" });
const result2 = graphqlSync({ schema, source, operationName: "B" });
const result3 = graphqlSync({ schema, source, operationName: "C" });

console.log(JSON.stringify(result1.data));
console.log(JSON.stringify(result2.data));
console.log(JSON.stringify(result3.data));

And you can fix it by changing line 28:

           type: ExampleInputObject,
-          defaultValue: {},
+          defaultValue: coerceInputValue({}, ExampleInputObject),

(also import coerceInputValue from graphql).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants