Skip to content

Commit f04f86f

Browse files
committed
Merge branch 'main' into data-collections
2 parents 4a241b2 + 646f937 commit f04f86f

12 files changed

+525
-265
lines changed

.github/algorithm-format-check.mjs

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { readFile, readdir } from "node:fs/promises";
22

33
const SPEC_DIR = new URL("../spec", import.meta.url).pathname;
44

5+
/** @see {@link https://spec-md.com/#sec-Value-Literals} */
6+
const valueLiteralsRegexp = /\{((?:[^{}]|(?:\{[^{}]*\}))+)\}/g;
7+
58
process.exitCode = 0;
69
const filenames = await readdir(SPEC_DIR);
710
for (const filename of filenames) {
@@ -23,13 +26,16 @@ for (const filename of filenames) {
2326
{
2427
// Is it an algorithm definition?
2528
const matches = line.match(/^([a-z0-9A-Z]+)(\s*)\(([^)]*)\)(\s*):(\s*)$/);
29+
const grammarMatches =
30+
filename === "Section 2 -- Language.md" &&
31+
line.match(/^([A-Za-z0-9]+) :\s+((\S).*)$/);
2632
if (matches) {
2733
const [, algorithmName, ns1, _args, ns2, ns3] = matches;
2834
if (ns1 || ns2 || ns3) {
2935
console.log(
3036
`Bad whitespace in definition of ${algorithmName} in '${filename}':`
3137
);
32-
console.log(line);
38+
console.dir(line);
3339
console.log();
3440
process.exitCode = 1;
3541
}
@@ -47,7 +53,7 @@ for (const filename of filenames) {
4753
console.log(
4854
`Bad algorithm ${algorithmName} step in '${filename}':`
4955
);
50-
console.log(step);
56+
console.dir(step);
5157
console.log();
5258
process.exitCode = 1;
5359
}
@@ -57,18 +63,45 @@ for (const filename of filenames) {
5763
console.log(
5864
`Bad formatting for '${algorithmName}' step (does not end in '.' or ':') in '${filename}':`
5965
);
60-
console.log(step);
66+
console.dir(step);
6167
console.log();
6268
process.exitCode = 1;
6369
}
6470
if (step.match(/^\s*(-|[0-9]\.)\s+[a-z]/)) {
6571
console.log(
6672
`Bad formatting of '${algorithmName}' step (should start with a capital) in '${filename}':`
6773
);
68-
console.log(step);
74+
console.dir(step);
6975
console.log();
7076
process.exitCode = 1;
7177
}
78+
79+
const stepWithoutValueLiterals = step.replace(
80+
valueLiteralsRegexp,
81+
""
82+
);
83+
if (stepWithoutValueLiterals.match(/\b[A-Z][A-Za-z0-9]+\(/)) {
84+
console.log(
85+
`Bad formatting of '${algorithmName}' step (algorithm call should be wrapped in braces: \`{MyAlgorithm(a, b, c)}\`) in '${filename}':`
86+
);
87+
console.dir(step);
88+
console.log();
89+
process.exitCode = 1;
90+
}
91+
92+
const valueLiterals = step.matchAll(valueLiteralsRegexp, "");
93+
for (const lit of valueLiterals) {
94+
const inner = lit[1];
95+
if (inner.includes("{")) {
96+
console.log(
97+
`Bad formatting of '${algorithmName}' step (algorithm call should not contain braces: \`${lit}\`) in '${filename}':`
98+
);
99+
console.dir(step);
100+
console.log();
101+
process.exitCode = 1;
102+
}
103+
}
104+
72105
const trimmedInnerLine = step.replace(/\s+/g, " ");
73106
if (
74107
trimmedInnerLine.match(
@@ -79,7 +112,67 @@ for (const filename of filenames) {
79112
console.log(
80113
`Potential bad formatting of '${algorithmName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':`
81114
);
82-
console.log(step);
115+
console.dir(step);
116+
console.log();
117+
process.exitCode = 1;
118+
}
119+
}
120+
} else if (grammarMatches) {
121+
// This is super loosey-goosey
122+
const [, grammarName, rest] = grammarMatches;
123+
if (rest.trim() === "one of") {
124+
// Still grammar, not algorithm
125+
continue;
126+
}
127+
if (rest.trim() === "" && lines[i + 1] !== "") {
128+
console.log(
129+
`No empty space after grammar ${grammarName} header in '${filename}'`
130+
);
131+
console.log();
132+
process.exitCode = 1;
133+
}
134+
if (!lines[i + 2].startsWith("- ")) {
135+
// Not an algorithm; probably more grammar
136+
continue;
137+
}
138+
for (let j = i + 2; j < l; j++) {
139+
const step = lines[j];
140+
if (!step.match(/^\s*(-|[0-9]+\.) /)) {
141+
if (step !== "") {
142+
console.log(`Bad grammar ${grammarName} step in '${filename}':`);
143+
console.dir(step);
144+
console.log();
145+
process.exitCode = 1;
146+
}
147+
break;
148+
}
149+
if (!step.match(/[.:]$/)) {
150+
console.log(
151+
`Bad formatting for '${grammarName}' step (does not end in '.' or ':') in '${filename}':`
152+
);
153+
console.dir(step);
154+
console.log();
155+
process.exitCode = 1;
156+
}
157+
if (step.match(/^\s*(-|[0-9]\.)\s+[a-z]/)) {
158+
console.log(
159+
`Bad formatting of '${grammarName}' step (should start with a capital) in '${filename}':`
160+
);
161+
console.dir(step);
162+
console.log();
163+
process.exitCode = 1;
164+
}
165+
const trimmedInnerLine = step.replace(/\s+/g, " ");
166+
if (
167+
trimmedInnerLine.match(
168+
/(?:[rR]eturn|is (?:not )?)(true|false|null)\b/
169+
) &&
170+
!trimmedInnerLine.match(/null or empty/)
171+
) {
172+
console.log(
173+
`Potential bad formatting of '${grammarName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':`
174+
);
175+
console.dir(step);
83176
console.log();
84177
process.exitCode = 1;
85178
}

CONTRIBUTING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ contributions.
66

77
Contributions that do not change the interpretation of the spec but instead
88
improve legibility, fix editorial errors, clear up ambiguity and improve
9-
examples are encouraged and are often merged by a spec editor with little
10-
process.
9+
examples are encouraged. These "editorial changes" will normally be given the
10+
["✏ Editorial" label](https://github.com/graphql/graphql-spec/issues?q=sort%3Aupdated-desc+is%3Aopen+label%3A%22%E2%9C%8F%EF%B8%8F+Editorial%22)
11+
and are often merged by a spec editor with little process.
1112

1213
However, contributions that _do_ meaningfully change the interpretation of the
1314
spec must follow an RFC (Request For Comments) process led by a _champion_

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
[![GraphQLConf 2025 Banner: September 08-10, Amsterdam. Hosted by the GraphQL Foundation](./assets/graphql.org_conf_2025_.png)](https://graphql.org/conf/2025/?utm_source=github&utm_medium=graphql_js&utm_campaign=readme)
2+
13
# GraphQL
24

35
<img alt="GraphQL Logo" align="right" src="https://graphql.org/img/logo.svg" width="15%" />

STYLE_GUIDE.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,25 @@ MyAlgorithm(argOne, argTwo):
8282
- Let {something} be {true}.
8383
- Return {something}.
8484
```
85+
86+
## Definitions
87+
88+
For important terms, use
89+
[Spec Markdown definition paragraphs](https://spec-md.com/#sec-Definition-Paragraph).
90+
91+
Definition paragraphs start with `::` and add the matching italicized term to
92+
the [specification index](https://spec.graphql.org/draft/#index), making it easy
93+
to reference them.
94+
95+
## Tone of voice
96+
97+
The GraphQL specification is a reference document and should use neutral and
98+
descriptive tone of voice.
99+
100+
**Favor the present tense**
101+
102+
The present tense is usually clearer and shorter:
103+
104+
✅ Present: The client then sends a request to the server.
105+
106+
❌ Future: The client will then send a request to the server.

assets/graphql.org_conf_2025_.png

488 KB
Loading

cspell.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ words:
2121
- tatooine
2222
- zuck
2323
- zuckerberg
24+
# Forbid Alternative spellings
25+
flagWords:
26+
- implementor
27+
- implementors

spec/Section 2 -- Language.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@ There are three types of operations that GraphQL models:
288288

289289
- query - a read-only fetch.
290290
- mutation - a write followed by a fetch.
291-
- subscription - a long-lived request that fetches data in response to source
292-
events.
291+
- subscription - a long-lived request that fetches data in response to a
292+
sequence of events over time.
293293

294294
Each operation is represented by an optional operation name and a _selection
295295
set_.
@@ -466,8 +466,9 @@ These two operations are semantically identical:
466466

467467
Alias : Name :
468468

469-
By default a field's response key in the response object will use that field's
470-
name. However, you can define a different response key by specifying an alias.
469+
:: A _response name_ is the key in the response object which correlates with a
470+
field's result. By default the response name will use the field's name; however,
471+
you can define a different response name by specifying an alias.
471472

472473
In this example, we can fetch two profile pictures of different sizes and ensure
473474
the resulting response object will not have duplicate keys:
@@ -1253,7 +1254,7 @@ Type : Name
12531254

12541255
- Let {name} be the string value of {Name}.
12551256
- Let {type} be the type defined in the Schema named {name}.
1256-
- {type} must not be {null}.
1257+
- {type} must exist.
12571258
- Return {type}.
12581259

12591260
Type : [ Type ]

0 commit comments

Comments
 (0)