From 8076f1e32a305188b41a71c2fec382b72186b424 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Thu, 6 Jun 2024 19:46:11 +0200 Subject: [PATCH 1/7] chore: add clarifying note for composite and expand term (#1078) * remove mentions of composite * Apply suggestions from code review Co-authored-by: Benjie * add note * Capitalise first letter in note block * remove the term and alter the wording * typo * Update spec/Section 5 -- Validation.md Co-authored-by: Benjie * Update spec/Section 5 -- Validation.md Co-authored-by: Benjie * Update spec/Section 5 -- Validation.md Co-authored-by: Benjie --------- Co-authored-by: Benjie --- spec/Section 5 -- Validation.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 473cf5457..1c75080bb 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -446,7 +446,8 @@ SameResponseShape(fieldA, fieldB): - If {typeA} or {typeB} is Scalar or Enum: - If {typeA} and {typeB} are the same type return {true}, otherwise return {false}. -- Assert: {typeA} and {typeB} are both composite types. +- Assert: {typeA} is an object, union or interface type. +- Assert: {typeB} is an object, union or interface type. - Let {mergedSet} be the result of adding the selection set of {fieldA} and the selection set of {fieldB}. - Let {fieldsForName} be the set of selections with a given response name in @@ -455,6 +456,9 @@ SameResponseShape(fieldA, fieldB): - If {SameResponseShape(subfieldA, subfieldB)} is {false}, return {false}. - Return {true}. +Note: In prior versions of the spec the term "composite" was used to signal a +type that is either an Object, Interface or Union type. + **Explanatory Text** If multiple field selections with the same response names are encountered during @@ -910,7 +914,7 @@ fragment inlineNotExistingType on Dog { } ``` -#### Fragments on Composite Types +#### Fragments on Object, Interface or Union Types **Formal Specification** From 7485a342b1c5f0ba4dbbe270d1f6863f55f7180b Mon Sep 17 00:00:00 2001 From: Benjie Date: Thu, 6 Jun 2024 18:51:13 +0100 Subject: [PATCH 2/7] Reformat the parts of an execution request (#1090) --- spec/Section 6 -- Execution.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 8184f95bb..3331d4371 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -4,18 +4,21 @@ A GraphQL service generates a response from a request via execution. :: A _request_ for execution consists of a few pieces of information: -- The schema to use, typically solely provided by the GraphQL service. -- A {Document} which must contain GraphQL {OperationDefinition} and may contain - {FragmentDefinition}. -- Optionally: The name of the Operation in the Document to execute. -- Optionally: Values for any Variables defined by the Operation. -- An initial value corresponding to the root type being executed. Conceptually, - an initial value represents the "universe" of data available via a GraphQL - Service. It is common for a GraphQL Service to always use the same initial - value for every request. - -Given this information, the result of {ExecuteRequest()} produces the response, -to be formatted according to the Response section below. +- {schema}: The schema to use, typically solely provided by the GraphQL service. +- {document}: A {Document} which must contain GraphQL {OperationDefinition} and + may contain {FragmentDefinition}. +- {operationName} (optional): The name of the Operation in the Document to + execute. +- {variableValues} (optional): Values for any Variables defined by the + Operation. +- {initialValue} (optional): An initial value corresponding to the root type + being executed. Conceptually, an initial value represents the "universe" of + data available via a GraphQL Service. It is common for a GraphQL Service to + always use the same initial value for every request. + +Given this information, the result of {ExecuteRequest(schema, document, +operationName, variableValues, initialValue)} produces the response, to be +formatted according to the Response section below. Note: GraphQL requests do not require any specific serialization format or transport mechanism. Message serialization and transport mechanisms should be From 497e333c35a29dbe1ab3d1f24c31a59789843fb6 Mon Sep 17 00:00:00 2001 From: Jan Melcher Date: Thu, 6 Jun 2024 20:20:11 +0200 Subject: [PATCH 3/7] Fix reference mistake in subscription execution (#994) --- spec/Section 6 -- Execution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 3331d4371..c96bda97b 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -297,7 +297,7 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues): - Let {response} be the result of running {ExecuteSubscriptionEvent(subscription, schema, variableValues, event)}. - Yield an event containing {response}. -- When {responseStream} completes: complete this event stream. +- When {sourceStream} completes: complete {responseStream}. ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue): From a80f9ff13b7ef9957d93ebe09e2dc4f2c93aede4 Mon Sep 17 00:00:00 2001 From: Benjie Date: Fri, 7 Jun 2024 13:43:17 +0100 Subject: [PATCH 4/7] Consistently spell 'implementers' (#1087) --- cspell.yml | 3 +++ spec/Section 5 -- Validation.md | 4 ++-- spec/Section 7 -- Response.md | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cspell.yml b/cspell.yml index e8aa73355..e03ec4a09 100644 --- a/cspell.yml +++ b/cspell.yml @@ -21,3 +21,6 @@ words: - tatooine - zuck - zuckerberg + # Alternative spellings + - !implementor + - !implementors diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 1c75080bb..75af96ffd 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -362,7 +362,7 @@ fragment aliasedLyingFieldTargetNotDefined on Dog { ``` For interfaces, direct field selection can only be done on fields. Fields of -concrete implementors are not relevant to the validity of the given +concrete implementers are not relevant to the validity of the given interface-typed selection set. For example, the following is valid: @@ -376,7 +376,7 @@ fragment interfaceFieldSelection on Pet { and the following is invalid: ```graphql counter-example -fragment definedOnImplementorsButNotInterface on Pet { +fragment definedOnImplementersButNotInterface on Pet { nickname } ``` diff --git a/spec/Section 7 -- Response.md b/spec/Section 7 -- Response.md index aef4359b1..bd9448293 100644 --- a/spec/Section 7 -- Response.md +++ b/spec/Section 7 -- Response.md @@ -23,7 +23,7 @@ request failed before execution, due to a syntax error, missing information, or validation error, this entry must not be present. The response map may also contain an entry with key `extensions`. This entry, if -set, must have a map as its value. This entry is reserved for implementors to +set, must have a map as its value. This entry is reserved for implementers to extend the protocol however they see fit, and hence there are no additional restrictions on its contents. @@ -203,7 +203,7 @@ be the same: GraphQL services may provide an additional entry to errors with key `extensions`. This entry, if set, must have a map as its value. This entry is -reserved for implementors to add additional information to errors however they +reserved for implementers to add additional information to errors however they see fit, and there are no additional restrictions on its contents. ```json example From e5bddd9c31fcd6796698e4fd059514a5a035bf20 Mon Sep 17 00:00:00 2001 From: Benjie Date: Fri, 7 Jun 2024 13:46:47 +0100 Subject: [PATCH 5/7] Fix punctuation in grammar rule (#1084) --- .github/algorithm-format-check.mjs | 73 ++++++++++++++++++++++++++++-- spec/Section 6 -- Execution.md | 10 ++-- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/.github/algorithm-format-check.mjs b/.github/algorithm-format-check.mjs index 13a31ece9..592d721de 100644 --- a/.github/algorithm-format-check.mjs +++ b/.github/algorithm-format-check.mjs @@ -23,13 +23,16 @@ for (const filename of filenames) { { // Is it an algorithm definition? const matches = line.match(/^([a-z0-9A-Z]+)(\s*)\(([^)]*)\)(\s*):(\s*)$/); + const grammarMatches = + filename === "Section 2 -- Language.md" && + line.match(/^([A-Za-z0-9]+) :\s+((\S).*)$/); if (matches) { const [, algorithmName, ns1, _args, ns2, ns3] = matches; if (ns1 || ns2 || ns3) { console.log( `Bad whitespace in definition of ${algorithmName} in '${filename}':` ); - console.log(line); + console.dir(line); console.log(); process.exitCode = 1; } @@ -47,7 +50,7 @@ for (const filename of filenames) { console.log( `Bad algorithm ${algorithmName} step in '${filename}':` ); - console.log(step); + console.dir(step); console.log(); process.exitCode = 1; } @@ -57,7 +60,7 @@ for (const filename of filenames) { console.log( `Bad formatting for '${algorithmName}' step (does not end in '.' or ':') in '${filename}':` ); - console.log(step); + console.dir(step); console.log(); process.exitCode = 1; } @@ -65,7 +68,7 @@ for (const filename of filenames) { console.log( `Bad formatting of '${algorithmName}' step (should start with a capital) in '${filename}':` ); - console.log(step); + console.dir(step); console.log(); process.exitCode = 1; } @@ -79,7 +82,67 @@ for (const filename of filenames) { console.log( `Potential bad formatting of '${algorithmName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':` ); - console.log(step); + console.dir(step); + console.log(); + process.exitCode = 1; + } + } + } else if (grammarMatches) { + // This is super loosey-goosey + const [, grammarName, rest] = grammarMatches; + if (rest.trim() === "one of") { + // Still grammar, not algorithm + continue; + } + if (rest.trim() === "" && lines[i + 1] !== "") { + console.log( + `No empty space after grammar ${grammarName} header in '${filename}'` + ); + console.log(); + process.exitCode = 1; + } + if (!lines[i + 2].startsWith("- ")) { + // Not an algorithm; probably more grammar + continue; + } + for (let j = i + 2; j < l; j++) { + const step = lines[j]; + if (!step.match(/^\s*(-|[0-9]+\.) /)) { + if (step !== "") { + console.log(`Bad grammar ${grammarName} step in '${filename}':`); + console.dir(step); + console.log(); + process.exitCode = 1; + } + break; + } + if (!step.match(/[.:]$/)) { + console.log( + `Bad formatting for '${grammarName}' step (does not end in '.' or ':') in '${filename}':` + ); + console.dir(step); + console.log(); + process.exitCode = 1; + } + if (step.match(/^\s*(-|[0-9]\.)\s+[a-z]/)) { + console.log( + `Bad formatting of '${grammarName}' step (should start with a capital) in '${filename}':` + ); + console.dir(step); + console.log(); + process.exitCode = 1; + } + const trimmedInnerLine = step.replace(/\s+/g, " "); + if ( + trimmedInnerLine.match( + /(?:[rR]eturn|is (?:not )?)(true|false|null)\b/ + ) && + !trimmedInnerLine.match(/null or empty/) + ) { + console.log( + `Potential bad formatting of '${grammarName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':` + ); + console.dir(step); console.log(); process.exitCode = 1; } diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index c96bda97b..5b8594e30 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -293,11 +293,11 @@ subscription _selection set_ using that event as a root value. MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues): - Return a new event stream {responseStream} which yields events as follows: -- For each {event} on {sourceStream}: - - Let {response} be the result of running - {ExecuteSubscriptionEvent(subscription, schema, variableValues, event)}. - - Yield an event containing {response}. -- When {sourceStream} completes: complete {responseStream}. + - For each {event} on {sourceStream}: + - Let {response} be the result of running + {ExecuteSubscriptionEvent(subscription, schema, variableValues, event)}. + - Yield an event containing {response}. + - When {sourceStream} completes: complete {responseStream}. ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue): From f8f2fac7478df812af885f7f8470cdb5a6c1659b Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Mon, 10 Jun 2024 14:20:27 +0200 Subject: [PATCH 6/7] chore: Update cspell.yml (#1100) Co-authored-by: Benjie --- cspell.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cspell.yml b/cspell.yml index e03ec4a09..0ea1def96 100644 --- a/cspell.yml +++ b/cspell.yml @@ -21,6 +21,7 @@ words: - tatooine - zuck - zuckerberg - # Alternative spellings - - !implementor - - !implementors +# Forbid Alternative spellings +flagWords: + - implementor + - implementors From e546aacd22b6a434546fbc400540b5bd5cda0f64 Mon Sep 17 00:00:00 2001 From: Jeff Auriemma Date: Tue, 6 Aug 2024 09:46:13 -0400 Subject: [PATCH 7/7] Add GraphQLConf 2024 banner (#1107) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 458213632..09a7962a5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![GraphQLConf 2024 Banner: September 10-12, San Francisco. Hosted by the GraphQL Foundation](https://github.com/user-attachments/assets/0203f10b-ae1e-4fe1-9222-6547fa2bbd5d)](https://graphql.org/conf/2024/?utm_source=github&utm_medium=graphql_spec&utm_campaign=readme) + # GraphQL GraphQL Logo