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

Schema Coordinates #794

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

Conversation

magicmark
Copy link
Contributor

👋

I've pulled out the proposed spec edits for Schema Coordinates (issue: #735) into this PR.

(The RFC now lives in the original PR: https://github.com/graphql/graphql-spec/pull/746/files)

@leebyron you mentioned it might be possible to simplify the grammar - I played around a bit since the original PR, but I think I need some help here. What did you have in mind?

As suggested, tagging @eapache @mjmahone as additional reviewers as we had some good conversation in last WG meeting about this.

Thanks!

@magicmark
Copy link
Contributor Author

magicmark commented Nov 18, 2020

Oh also, here's another option I had for the examples table, was thinking it might be good to explicitly show all the different kinds of schema you can select:

Screen Shot 2020-11-17 at 10 38 01 PM

felt slightly too verbose to me, but curious to see if anyone prefers this

Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

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

Thanks for your hard work on this!

spec/Appendix C -- Schema Coordinates.md Outdated Show resolved Hide resolved
spec/Appendix C -- Schema Coordinates.md Outdated Show resolved Hide resolved
spec/Appendix C -- Schema Coordinates.md Outdated Show resolved Hide resolved
spec/Appendix C -- Schema Coordinates.md Outdated Show resolved Hide resolved
spec/Appendix C -- Schema Coordinates.md Outdated Show resolved Hide resolved
Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

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

Looks good to me; a few optional tweaks suggested.

spec/Section 3 -- Type System.md Outdated Show resolved Hide resolved
spec/Section 3 -- Type System.md Outdated Show resolved Hide resolved
spec/Section 3 -- Type System.md Outdated Show resolved Hide resolved
spec/Section 3 -- Type System.md Outdated Show resolved Hide resolved
Comment on lines 379 to 399
Schema Coordinates are always unique. Each type, field, argument, enum value, or
directive may be referenced by exactly one possible Schema Coordinate.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

feels like something worth highlighting and being clear about as a guarantee in the spec

Comment on lines 382 to 391
For example, the following is *not* a valid Schema Coordinate:

```graphql counter-example
Entity.Business
```

In this counter example, both `Entity.Business` and `Business` would refer to
the `Business` type. Since it would be ambiguous what the "primary key" should
be in an application that uses Schema Coordinates to reference types, this is
not allowed.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

is this waffle? thought it might be helpful to have a little explanation/demonstration of this property

Copy link
Contributor Author

@magicmark magicmark Jan 4, 2021

Choose a reason for hiding this comment

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

Could just be

- Since it would be ambiguous what the "primary key" should be in an application that uses Schema Coordinates to reference types, this is not allowed.
+ Such ambiguity is disallowed (and hence why this is is invalid syntax).

(More terse, but doesn't walk the reader through why this is bad)

Voting lines are now open!

Copy link
Member

Choose a reason for hiding this comment

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

In this counter example, Entity.Business is redundant since Business already uniquely identifies the Business type. Such redundancy is disallowed by this spec - every type, field, field argument, enum value, directive, and directive argument has exactly one canonical Schema Coordinate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 thanks benjie, stealing this wording

magicmark added a commit to magicmark/graphql-wg that referenced this pull request Jan 4, 2021
Happy new year! 🥳

It's possible we still want more time for the RFC to marinate, but I'll attend so I can be available to folks to discuss the schema coordinates rfc/spec edit in person.

graphql/graphql-spec#794

Thanks!
@leebyron leebyron added the 💡 Proposal (RFC 1) RFC Stage 1 (See CONTRIBUTING.md) label Jan 7, 2021
Base automatically changed from master to main February 3, 2021 04:50
@mcohen75
Copy link

mcohen75 commented Feb 4, 2021

At Indeed we log usage of schema elements to 1) support deprecation and 2) understand usage from a product management perspective (i.e. is this API we built adding value?).

We defined our own coordinate system that is not quite as complete as this spec. A nice benefit of formalizing a coordinate system is that shared tools can be built to solve these and other use cases.

👍 👍 👍

@leebyron leebyron added 📄 Draft (RFC 2) RFC Stage 2 (See CONTRIBUTING.md) and removed 💡 Proposal (RFC 1) RFC Stage 1 (See CONTRIBUTING.md) labels Mar 4, 2021
@leebyron leebyron added this to the May2021 milestone Apr 13, 2021
@leebyron leebyron force-pushed the schema_coordinates_spec_edit branch 3 times, most recently from 4f854af to c0b82d5 Compare April 13, 2021 23:57
@leebyron
Copy link
Collaborator

I made some fairly significant edits to the prose and examples section in an attempt to simplify. @magicmark please take a look and let me know what you think.

@leebyron leebyron force-pushed the schema_coordinates_spec_edit branch 3 times, most recently from 81ef020 to 4299d8c Compare April 14, 2021 01:18
@leebyron leebyron requested review from benjie and a team April 14, 2021 01:20
@leebyron leebyron changed the title Schema Coordinates: add spec edit Schema Coordinates Apr 14, 2021
@leebyron
Copy link
Collaborator

IIRC the only thing holding this from Approval stage is a landed GraphQL.js PR?

leebyron added a commit to graphql/graphql-js that referenced this pull request Jun 3, 2021
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
leebyron added a commit to graphql/graphql-js that referenced this pull request Jun 3, 2021
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
Comment on lines +2112 to +2121
3. If {type} is an Enum type:
1. Let {enumValueName} be the value of the second {Name}.
2. Return the enum value of {type} named {enumValueName}.
4. Otherwise if {type} is an Input Object type:
1. Let {inputFieldName} be the value of the second {Name}.
2. Return the input field of {type} named {inputFieldName}.
5. Otherwise:
1. Assert {type} must be an Object or Interface type.
2. Let {fieldName} be the value of the second {Name}.
3. Return the field of {type} named {fieldName}.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this section should also specify the behaviour for Union types.
At the moment the spec does not define the behaviour for Union.UnionTypeMember

Suggested change
3. If {type} is an Enum type:
1. Let {enumValueName} be the value of the second {Name}.
2. Return the enum value of {type} named {enumValueName}.
4. Otherwise if {type} is an Input Object type:
1. Let {inputFieldName} be the value of the second {Name}.
2. Return the input field of {type} named {inputFieldName}.
5. Otherwise:
1. Assert {type} must be an Object or Interface type.
2. Let {fieldName} be the value of the second {Name}.
3. Return the field of {type} named {fieldName}.
3. If {type} is an Union type:
1. Assert {type} must be an Enum, Input Object, Object or Interface type.
4. If {type} is an Enum type:
1. Let {enumValueName} be the value of the second {Name}.
2. Return the enum value of {type} named {enumValueName}.
5. Otherwise if {type} is an Input Object type:
1. Let {inputFieldName} be the value of the second {Name}.
2. Return the input field of {type} named {inputFieldName}.
6. Otherwise:
1. Assert {type} must be an Object or Interface type.
2. Let {fieldName} be the value of the second {Name}.
3. Return the field of {type} named {fieldName}.

Copy link
Contributor Author

@magicmark magicmark Dec 30, 2021

Choose a reason for hiding this comment

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

Perhaps I'm misunderstanding your question, but to clarify:

UnionTypeMember

The definition for this would live somewhere else in the schema, outside of the context of the union. You would write the schema coordinate to that instead.

i.e. Union.UnionTypeMember is not a valid schema coordinate.

The rule of thumb is: there should only be one way to reference a thing with Schema Coordinates

Is there still some ambiguity in this spec?

Copy link
Contributor

Choose a reason for hiding this comment

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

@magicmark Makes sense to me

Copy link
Contributor Author

@magicmark magicmark Dec 31, 2021

Choose a reason for hiding this comment

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

@leebyron is it worth keeping in the clarification (or something similar) from a previous commit?

https://github.com/magicmark/graphql-spec/blob/ac5318f9a9f04d0f8dd03d3758d5ca2654f7f7d7/spec/Section%203%20--%20Type%20System.md?plain=1#L391-L399

My gut says this may crop up again and cause some confusion - worth the counter example?

Copy link

Choose a reason for hiding this comment

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

@leebyron is it worth keeping in the clarification (or something similar) from a previous commit?

magicmark/graphql-spec@ac5318f/spec/Section%203%20--%20Type%20System.md?plain=1#L391-L399

My gut says this may crop up again and cause some confusion - worth the counter example?

Just chiming in. From my perspective the counter example would be ideal (maybe even clarify that directives on types are also invalid?).

Maybe add a line on why union members are not valid schema coordinates, instead of solely stating that they are not?

- Note: You may not select members inside a union definition.
+ Note: Union members do not uniquely identify elements in the schema. Therefore the following counter example is *not* considered a valid Schema Coordinate:

...or something along those lines

Copy link
Contributor Author

@magicmark magicmark Dec 31, 2021

Choose a reason for hiding this comment

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

fwiw this is all sort of encapsulated by the following line the spec:

A schema coordinate is always unique. Each schema element may be referenced
by exactly one possible schema coordinate.

++ for the explainer, I would maybe try and reuse this language (e.g. "as stated above, each schema element...."), or hyperlink back to this source of truth somehow

@schenkman
Copy link

schenkman commented Oct 12, 2022

Regarding input arguments, the example is shown as:

Query.searchBusiness(name:)

What would it look like for more interesting sub-input-types on an argument? Example:

input BazInput {
  count: Int
  color: String
}
input BarInput {
  baz_settings: BazInput
}
input FooInput {
  bar_params: BarInput
}

type Query {
  foos(foo_params: FooInput) 
}

Would the above translate to the following coordinates?

Query.foos(foo_params:)
Query.foos(foo_params:bar_params)
Query.foos(foo_params:bar_params:baz_settings:)
Query.foos(foo_params:bar_params:baz_settings:count:)
Query.foos(foo_params:bar_params:baz_settings:color:)

@PascalSenn
Copy link
Contributor

@schenkman

This would be:

Query.foos(foo_params:) => Query.foos(foo_params:)
Query.foos(foo_params:bar_params) => FooInput.bar_params
Query.foos(foo_params:bar_params:baz_settings:) => BarInput.baz_settings
Query.foos(foo_params:bar_params:baz_settings:count:) => BazInput.count

@benjie
Copy link
Member

benjie commented Oct 13, 2022

Indeed, each schema entity should have exactly one schema coordinate. If you want to identify those kinds of paths in an operation (rather than the schema), then operation expressions might be what you’re after: https://github.com/graphql/graphql-wg/blob/main/rfcs/OperationExpressions.md#arguments

yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Dec 29, 2022
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Dec 29, 2022
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Jan 31, 2023
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Jan 31, 2023
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Feb 6, 2023
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request May 31, 2023
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request May 31, 2023
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
@ddebrunner
Copy link

ddebrunner commented Dec 4, 2023

@PascalSenn @benjie Trying to understand the last two comments:

This would be:
Query.foos(foo_params:bar_params) => FooInput.bar_params

Q1 - "This would be" - intended to mean this is direction the spec will go as it's not covered in this PR?

I assume it would also apply to directives, so with @A(foo_params: FooInput) then the coordinate for bar_params would be:

@A(foo_params:bar_params)

I saw the comment here: https://github.com/graphql/graphql-wg/blob/main/rfcs/SchemaCoordinates.md?plain=1#L370-L375 but it throws me a little as it talks about supporting more than "schema coordinates" but then the first example seems to be a schema coordinate Foo.bar(baz.qux:)

Also note the example Foo.bar(baz.qux:) is different to the comment above, which would have it as Foo.bar(baz:qux) but the latter seems to make more sense.

@benjie
Copy link
Member

benjie commented Dec 4, 2023

@ddebrunner Schema Coordinates and Operation Expressions are two separate proposals with related syntax.

Every entity in a schema has exactly one schema coordinate, there is no schema coordinate @A(foo_params:bar_params:), at least not as currently proposed.

The property bar_params on the type FooInput has the schema coordinate FooInput.bar_params, independent of whether it's accessed through a directive (@A(foo_params:{bar_params:...})) or a field (myField(foo_params:{bar_params:...})).

You can, however, use Operation Expressions to indicate the accessing of something in this manner, since Operation Expressions are not unique.

The comment you quote relates to (what became) Operation Expressions, which is a system that builds upon the Schema Coordinates syntax to talk about paths within operations (rather than the schema).

@ddebrunner
Copy link

ddebrunner commented Dec 5, 2023

@benjie I'm not talking about operations, but schema elements. A type system directive is applied to a schema element and thus is also a schema element(?), so what are the coordinates to such arguments?

E.g.

input IO {
  a:IO2
}
input IO2 {
  b:Int
}
directive @x(v:IO)

type T {
   f:Int @x(v:{a:{b:3}})
}

Now if the value of b is invalid how would I report the coordinate of b in an error message.
The comments related to this RFC seem to imply something like:

@x(v:a.b) on T.f

But I'm assuming that the use of type system directive@x is a schema element, and therefore so are its arguments.
Maybe I'm missing something?

@benjie
Copy link
Member

benjie commented Dec 5, 2023

I don't think the application of a directive is covered by this proposal, only the directive itself. At runtime your @x application on T.f no longer exists - e.g. if you introspect that schema or use graphql.printSchema(schema) you'll not see it - it's a build-time-only directive currently. (See #300 for more details.)

You could use operation expressions to indicate the path of this directive application, I guess it's more "document expressions" than "operation expressions" thinking about it.

@ddebrunner
Copy link

Fair enough, but I hadn't assumed that the RFC was related to runtime, thus the fact that introspection doesn't return type system directives would seem to be irrelevant to the RFC.

yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Mar 20, 2024
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Aug 22, 2024
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Sep 7, 2024
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Sep 8, 2024
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
yaacovCR pushed a commit to yaacovCR/graphql-js that referenced this pull request Sep 11, 2024
Implements graphql/graphql-spec#794

Adds:

* DOT punctuator in lexer
* Improvements to lexer errors around misuse of `.`
* Minor improvement to parser core which simplified this addition
* `SchemaCoordinate` node and `isSchemaCoodinate()` predicate
* Support in `print()` and `visit()`
* Added function `parseSchemaCoordinate()` since it is a parser entry point.
* Added function `resolveSchemaCoordinate()` and `resolveASTSchemaCoordinate()` which implement the semantics (name mirrored from `buildASTSchema`) as well as the return type `ResolvedSchemaElement`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📄 Draft (RFC 2) RFC Stage 2 (See CONTRIBUTING.md) 🚀 Next Stage? This RFC believes it is ready for the next stage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants