-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Service capabilities #1208
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
base: main
Are you sure you want to change the base?
Service capabilities #1208
Changes from all commits
5e01c0c
ccb76ed
35b8067
62583e9
601b846
33a1524
6d0c2d6
39b9b56
fb440fa
f1659df
9980de8
e92af29
aa7302b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ TypeSystemDefinition : | |||||
| - SchemaDefinition | ||||||
| - TypeDefinition | ||||||
| - DirectiveDefinition | ||||||
| - ServiceDefinition | ||||||
|
|
||||||
| The GraphQL language includes an | ||||||
| [IDL](https://en.wikipedia.org/wiki/Interface_description_language) used to | ||||||
|
|
@@ -40,6 +41,7 @@ TypeSystemExtension : | |||||
|
|
||||||
| - SchemaExtension | ||||||
| - TypeExtension | ||||||
| - ServiceExtension | ||||||
|
|
||||||
| Type system extensions are used to represent a GraphQL type system which has | ||||||
| been extended from some previous type system. For example, this might be used by | ||||||
|
|
@@ -2321,3 +2323,132 @@ input UserUniqueCondition @oneOf { | |||||
| organizationAndEmail: OrganizationAndEmailInput | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Service Definition | ||||||
|
|
||||||
| ServiceDefinition : Description? service Directives? { ServiceCapability\* } | ||||||
|
|
||||||
| A GraphQL service is defined in terms of the capabilities that it offers which | ||||||
| are external to the schema. | ||||||
|
|
||||||
| ### Service Capabilities | ||||||
|
|
||||||
| ServiceCapability : Description? capability QualifiedName | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: maybe just
Suggested change
|
||||||
| ServiceCapabilityValue? | ||||||
|
|
||||||
| ServiceCapabilityValue : ( StringValue ) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not Basically: why shouldn't we be able to use enum values or integers or have a service take in an input or etc? Seems like it'd be common to need 3-4 flags for one capability to work.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we don't yet have the But also, if you need multiple arguments (why?) either use custom serialization or use multiple capabilities. service {
capability graphql.ws
capability graphql.ws.endpoint("ws://...")
"To avoid thundering herd, multiply this by `(0.5 + rand())`"
capability graphql.ws.reconnectDelay("3000")
"The modern protocol"
capability graphql.ws.protocol.graphqlTransportWs
"The updated modern protocol"
capability graphql.ws.protocol.graphqlTransportWs.v2
"Configuration for V2 protocol"
capability graphql.ws.protocol.graphqlTransportWs.v2.encoding("utf-8")
"The legacy protocol"
capability graphql.ws.protocol.graphqlWs
}Arguments should be the rarer case, IMO - if in doubt, use a sub-name (like the protocols above) rather than an argument.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have examples that don't fit this well? |
||||||
|
|
||||||
| :: A _service capability_ describes a feature supported by the GraphQL service | ||||||
| but not directly expressible via the type system. This may include support for | ||||||
| new or experimental GraphQL syntactic or behavioral features, protocol support | ||||||
| (such as GraphQL over WebSockets or Server-Sent Events), or additional | ||||||
| operational information (such as endpoints for related services). Service | ||||||
| capabilities may be supplied by the GraphQL implementation, the service, or | ||||||
| both. | ||||||
|
|
||||||
| A _service capability_ is identified by a _capability identifier_ (a | ||||||
| {QualifiedName}), and may optionally have a string value. All capabilities | ||||||
| within a service must have unique identifiers. | ||||||
|
|
||||||
| ```graphql example | ||||||
| service { | ||||||
| "Descriptions on operations and fragments are supported" | ||||||
| capability graphql.operationDescriptions | ||||||
|
|
||||||
| "Websocket transport is supported via the given endpoint" | ||||||
| capability example.transport.ws("wss://api.example.com/graphql") | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| **Capability Identifier** | ||||||
|
|
||||||
| :: A _capability identifier_ is a {QualifiedName} (a case-sensitive string value | ||||||
|
Comment on lines
+2363
to
+2365
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a Java person who likes qualified names, I'm happy if we don't have "Capability identifier" but instead always use "Capability qualified name".
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or maybe just "capability name", just like we have "type name", "field name", etc.... I don't think we need specific language here? |
||||||
| composed of two or more {Name} separated by a period (`.`)) that uniquely | ||||||
| identifies a capability. This structure is inspired by reverse domain notation | ||||||
| to encourage global uniqueness and collision-resistance; it is recommended that | ||||||
| identifiers defined by specific projects, vendors, or implementations begin with | ||||||
| a prefix derived from a DNS name they control (e.g., {"com.example."}). | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it would make sense to use a URI instead, the advantage being that it could point to documentation about the capability. Disadvantage: URIs are more verbose than a |
||||||
|
|
||||||
| Clients must compare capability identifiers using exact (case-sensitive) string | ||||||
| equality. | ||||||
|
|
||||||
| **Reserved Capability Identifiers** | ||||||
|
|
||||||
| A _capability identifier_ must not start with an underscore {"\_"}; this is | ||||||
| reserved for future usage. | ||||||
|
|
||||||
| Capability identifiers beginning with the prefix {"graphql."} are reserved and | ||||||
| must not be used outside of official GraphQL Foundation specifications. | ||||||
| Identifiers beginning with the prefix {"graphql.rfc."} are reserved for RFC | ||||||
| proposals. | ||||||
|
|
||||||
| Any identifiers beginning with case-insensitive variants of {"graphql."}, | ||||||
| {"org.graphql."} and {"gql."} are also reserved. | ||||||
|
|
||||||
| Identifiers beginning with the prefix {"example."} are reserved for usage in | ||||||
| documentation and examples only. | ||||||
|
|
||||||
| Note: Since IANA RFC 2606 reserves the second-level domain names | ||||||
| {"example.com"}, {"example.net"}, and {"example.org"} for documentation | ||||||
| purposes, the corresponding reverse-domain prefixes {"com.example."}, | ||||||
| {"net.example."}, and {"org.example."} are also reserved for documentation | ||||||
| purposes. | ||||||
|
|
||||||
| Implementers should not change the meaning of capability identifiers; instead, a | ||||||
| new capability identifier should be used when the meaning changes. Implementers | ||||||
| should ensure that capability identifiers remain stable and version-agnostic | ||||||
| where possible. | ||||||
|
|
||||||
| Note: Capability versioning, if needed, can be indicated using dot suffixes | ||||||
| (e.g. {"example.capability.v2"}). | ||||||
|
|
||||||
| This system enables incremental feature adoption and richer tooling | ||||||
| interoperability, while avoiding tight coupling to specific implementations. | ||||||
|
|
||||||
| **Capability value** | ||||||
|
|
||||||
| For capabilities that require more information than a simple indication of | ||||||
| support, a string value may be specified. | ||||||
|
|
||||||
| For example, the capability {"graphql.operationDescriptions"} does not require | ||||||
| additional information and thus does not specify a value; whereas a capability | ||||||
| such as {"example.transport.ws"} might use the value to indicate the endpoint to | ||||||
| use for websocket communications (or might omit a value to indicate that | ||||||
| WebSockets are supported at the current endpoint). | ||||||
|
|
||||||
| **Specified capabilities** | ||||||
|
|
||||||
| This version of the specification defines the following capabilities: | ||||||
|
|
||||||
| - {"graphql.operationDescriptions"} - indicates support for descriptions on | ||||||
| operations and fragments | ||||||
|
|
||||||
| ### Service Extension | ||||||
|
|
||||||
| ServiceExtension : | ||||||
|
|
||||||
| - extend service Directives? { ServiceCapability\* } | ||||||
| - extend service Directives [lookahead != `{`] | ||||||
|
|
||||||
| Service extensions are used to represent a service which has been extended from | ||||||
| a previous service. For example, this might be used by a GraphQL service which | ||||||
| adds additional capabilities to an existing service. | ||||||
|
|
||||||
| Note: Service extensions without additional capability definitions must not be | ||||||
| followed by a {`{`} (such as a query shorthand) to avoid parsing ambiguity. | ||||||
|
|
||||||
| ```graphql example | ||||||
| extend service { | ||||||
| capability example.newCapability | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| **Service Validation** | ||||||
|
|
||||||
| Service extensions have the potential to be invalid if incorrectly defined. | ||||||
|
|
||||||
| 1. The Service must already be defined. | ||||||
| 2. Any non-repeatable directives provided must not already apply to the previous | ||||||
| Service. | ||||||
| 3. Any capabilities provided must not already be defined on the previous | ||||||
| Service. | ||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -85,13 +85,14 @@ operation. | |||||||
|
|
||||||||
| ## Schema Introspection | ||||||||
|
|
||||||||
| The schema introspection system is accessible from the meta-fields `__schema` | ||||||||
| and `__type` which are accessible from the type of the root of a query | ||||||||
| operation. | ||||||||
| The schema introspection system is accessible from the meta-fields `__schema`, | ||||||||
| `__type` and `__service` which are accessible from the type of the root of a | ||||||||
| query operation. | ||||||||
|
|
||||||||
| ```graphql | ||||||||
| __schema: __Schema! | ||||||||
| __type(name: String!): __Type | ||||||||
| __service: __Service! | ||||||||
| ``` | ||||||||
|
|
||||||||
| Like all meta-fields, these are implicit and do not appear in the fields list in | ||||||||
|
|
@@ -228,6 +229,16 @@ enum __DirectiveLocation { | |||||||
| INPUT_OBJECT | ||||||||
| INPUT_FIELD_DEFINITION | ||||||||
| } | ||||||||
|
|
||||||||
| type __Service { | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| capabilities: [__Capability!]! | ||||||||
| } | ||||||||
|
|
||||||||
| type __Capability { | ||||||||
| identifier: String! | ||||||||
| description: String | ||||||||
| value: String | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| ### The \_\_Schema Type | ||||||||
|
|
@@ -512,3 +523,29 @@ Fields\: | |||||||
| {true}, deprecated arguments are also returned. | ||||||||
| - `isRepeatable` must return a Boolean that indicates if the directive may be | ||||||||
| used repeatedly at a single location. | ||||||||
|
|
||||||||
| ### The \_\_Service Type | ||||||||
|
|
||||||||
| The `__Service` type is returned from the `__service` meta-field and provides | ||||||||
| information about the GraphQL service, most notably about its capabilities. | ||||||||
|
|
||||||||
| Note: Services implementing an older version of this specification may not | ||||||||
| support the `__service` meta-field or `__Service` type. Support may be probed | ||||||||
| using the introspection query: `{ __type(name: "__Service") { name } }`, a | ||||||||
| {null} result indicates lack of support. | ||||||||
|
|
||||||||
| Fields\: | ||||||||
|
|
||||||||
| - `capabilities` must return a list of `__Capability` detailing each _service | ||||||||
| capability_ supported by the service. | ||||||||
|
|
||||||||
| ### The \_\_Capability Type | ||||||||
|
|
||||||||
| A `__Capability` object describes a specific _service capability_, and has the | ||||||||
| following fields\: | ||||||||
|
|
||||||||
| - `identifier` must return the string _capability identifier_ uniquely | ||||||||
| identifying this service capability. | ||||||||
|
Comment on lines
+547
to
+548
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be more explicit somewhere that capabilities MUST be unique? service {
capability com.example
capability com.example # invalid (or maybe we allow it and it's a no-op?)
} |
||||||||
| - `description` may return a String or {null}. | ||||||||
| - `value` the String value of the service capability, or {null} if there is no | ||||||||
| associated value. | ||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we allow empty extensions?
(ping @BoD)