Skip to content
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

Directive for Oneof Objects and Oneof Input Objects #1

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

erikkessler1
Copy link
Owner

This sets the groundwork for an implementation of graphql/graphql-spec#825 for Objects and Input Objects (Oneof Fields omitted for now) by adding @oneOf as a built-in directive and exposing __Type.oneOf during schema introspection.

expect(schema.getDirective('skip')).to.not.equal(undefined);
expect(schema.getDirective('include')).to.not.equal(undefined);
expect(schema.getDirective('deprecated')).to.not.equal(undefined);
expect(schema.getDirective('specifiedBy')).to.not.equal(undefined);
expect(schema.getDirective('include')).to.not.equal(undefined);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be oneOf?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops yeah. Thanks!

Comment on lines 217 to 221
new GraphQLDirective({
name: 'oneOf',
description: 'Indicates an Object is a Oneof Object or an Input Object is a Oneof Input Object.',
locations: [DirectiveLocation.OBJECT, DirectiveLocation.INPUT_OBJECT],
args: {},
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new GraphQLDirective({
name: 'oneOf',
description: 'Indicates an Object is a Oneof Object or an Input Object is a Oneof Input Object.',
locations: [DirectiveLocation.OBJECT, DirectiveLocation.INPUT_OBJECT],
args: {},
});
new GraphQLDirective({
name: 'oneOf',
description: 'Indicates an Object is a Oneof Object or an Input Object is a Oneof Input Object.',
locations: [DirectiveLocation.OBJECT, DirectiveLocation.INPUT_OBJECT],
args: {},
});

Comment on lines 313 to 314
if (isObjectType(type) && type.isOneOf) {
validateOneofObjectField(type, field, context);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the "of" sometimes gets capitalized (e.g. isOneOf) and sometimes doesn't (e.g. validateOneofObjectField)?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateOneOfObjectField probably make more sense, but I was confused myself what the capitalization should be. In the RFC they are called "Oneof Input Objects" but maybe that is just the titleized version?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He also just writes "oneof" with no caps at all in a comment or two, so I'm not sure there's much consistency to be had ¯\_(ツ)_/¯

Either way it's probably not a big deal, I just happened to notice as I was reading through

Copy link

@jturkel jturkel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great (although I don't know much about graphql-js internals)! A few questions:

  1. Can oneOf be applied to interfaces since this is prototyping support in both inputs and outputs?
  2. Can oneOf be applied to type extensions? Is there additional validation required either way?
  3. This is intentionally not implementing one fields as described here right?

This adds the @OneOf directive as a default directive to indicate
Objects and Input Objects as Oneof Objects/Input Objects which ensure
there is exactly one non-null entry. Future commits will work to
implement this directive.
This exposes a new boolean `oneOf` field on `__Type` that indicates if
a type is `oneOf`. We implement by checking if the AST node for the
object contains a `@oneOf` directive.
This validates that all fields of oneof objects are nullable and that
all fields of oneof input object are nullable and do not have a
default value.
@erikkessler1
Copy link
Owner Author

  1. Can oneOf be applied to interfaces since this is prototyping support in both inputs and outputs?

I imagine it would support interfaces. I'll have to come back to that.

  1. Can oneOf be applied to type extensions? Is there additional validation required either way?

The spec talks about how they apply to extensions here https://github.com/graphql/graphql-spec/pull/825/files#diff-30a69c5a5eded8e1aea52e53dad1181e6ec8f549ca2c50570b035153e2de1c43R1712-R1715 so I'll have to come back and make sure I've captured that part of the spec.

  1. This is intentionally not implementing one fields as described here right?

That's correct, Benjie seemed more concerned with getting objects and input objects implemented:

I think it's fine to drop field arguments ("Oneof Fields" in the spec edit) and go with just object types and input object types.

This adds `oneof` as a valid word so `Oneof` isn't flagged as a typo.
I wasn't sure what the correct capitalization should be since the RFC
styles it as "Oneof Input Objects" but in the schema it is
`__Type.oneOf`. I tried to use "Oneof" in prose and `oneOf` in code.
@benjie
Copy link

benjie commented Jan 28, 2022

I've only looked at this in GitHub (not checked it out and tried it/etc) but it looks good to me 👍

Capitalisation of oneof vs oneOf is an open question. I prefer oneOf because I think it's clearer - especially for non-native speakers. It seems casing is mixed across different languages, e.g. Swagger & JSON Schema use oneOf but protobuf uses oneof. Let's go with oneOf for now 👍

@erikkessler1
Copy link
Owner Author

Capitalisation of oneof vs oneOf is an open question. I prefer oneOf because I think it's clearer - especially for non-native speakers. It seems casing is mixed across different languages, e.g. Swagger & JSON Schema use oneOf but protobuf uses oneof. Let's go with oneOf for now 👍

That makes sense. Do would you imagine that we style it as OneOf when titleized? For example, for the description of the directive, would you imagine it be:

Indicates an Object is a Oneof Object or an Input Object is a Oneof Input Object.

or

Indicates an Object is a OneOf Object or an Input Object is a OneOf Input Object.

@benjie
Copy link

benjie commented Feb 1, 2022

I think OneOf for consistency.

@erikkessler1
Copy link
Owner Author

I've opened this as a PR on the upstream repository graphql#3513

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

Successfully merging this pull request may close these issues.

4 participants