@descryy/adapter-graphql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The GraphQL SDL adapter.
3
+ *
4
+ * The third capability in this project that reaches **R3 with no language
5
+ * adapter at all**, after `adapter-sql` and `adapter-openapi`, and for the same
6
+ * reason all three do: a published schema is *declared*, not deduced. It is a
7
+ * `LanguageAdapter` because it is a per-format reader with a capability matrix,
8
+ * not because SDL is a programming language — `language: "graphql"` describes
9
+ * the artifact it read, DEC-026, exactly the reading `adapter-sql` and
10
+ * `adapter-openapi` get.
11
+ *
12
+ * ## What it mints, and why the identity is not this file's to choose
13
+ *
14
+ * `DEC-317` fixed GraphQL operation identity, transposing `DEC-316`'s gRPC
15
+ * precedent: `method` is the literal sentinel `"GRAPHQL"`, the path is
16
+ * `/<OperationType>/<field>`. That decision was written against Python's
17
+ * strawberry, and its "Consequences" section says any later GraphQL reader
18
+ * "must mint this identical shape". This is the first such reader, so this is
19
+ * the first place that claim is *tested* rather than asserted —
20
+ * `test/sdl-strawberry-join.test.ts` runs both producers over the same
21
+ * operation and compares the emitted ids, in the shape `DEC-321` established
22
+ * for the PHP/SQL `DATABASE_TABLE` join.
23
+ *
24
+ * ## Why this reader supersedes the class-structure one, and how
25
+ *
26
+ * `DEC-317` §"The departure" is candid that strawberry forced a compromise:
27
+ * with no artifact to read, the schema-facing name had to be derived from the
28
+ * class structure, and a name that could only be *computed* had to be refused
29
+ * as `graphqlFieldNameNotReadable`. An SDL field name is the schema-facing name
30
+ * by definition. There is nothing to compute and nothing to refuse.
31
+ *
32
+ * **The precedence is expressed through resolution, not through a priority
33
+ * rule, and that is deliberate.** This adapter emits at R3: the document is the
34
+ * schema. `adapter-python`'s strawberry reader emits its operations at R0 or R1
35
+ * (`extract.ts` — R1 once a field was reached through the import graph). Rule 3,
36
+ * the resolution cap, then does the ranking on its own: an SDL-derived finding
37
+ * is capped at reliability class A and a strawberry-derived one at C or B. No
38
+ * new machinery, no producer allow-list, no "SDL wins" branch anywhere above
39
+ * the IR — the mechanism the engine already has says the right thing, because
40
+ * the two producers genuinely differ in the strength of their evidence.
41
+ *
42
+ * **Where SDL and source disagree, they do not fight — they diverge visibly.**
43
+ * The two producers' `API_ROUTE` nodes are distinct by construction (`API_ROUTE`
44
+ * is language-scoped, so `graphql` and `python` routes never share an id), and
45
+ * that asymmetry is the contract mechanism working as designed: the route is
46
+ * each producer's local view. They meet at the `API_ENDPOINT`, which is fileless
47
+ * and language-less. So:
48
+ *
49
+ * - **agreement** — one `API_ENDPOINT`, two `SERVES_API` edges into it from two
50
+ * routes, at two resolutions. This is the join, and it is the case that
51
+ * proves the convention transposed correctly.
52
+ * - **disagreement on a name** — two `API_ENDPOINT` nodes, one per spelling.
53
+ * The SDL's is the correct one, and it carries R3 while the source-derived one
54
+ * carries R0/R1. A stale committed SDL is the same risk a stale committed
55
+ * `openapi.json` carries and is treated the same way: disclosed, not
56
+ * downgraded. The divergence being *visible* is the useful property — a
57
+ * published schema that no longer matches its source is a real finding, and a
58
+ * reader that silently preferred one would have destroyed the evidence for it.
59
+ *
60
+ * ## What it does not claim, and the two refusals are load-bearing
61
+ *
62
+ * **No `DTO`, and not for scope reasons.** `adapter-openapi` mints a `DTO` per
63
+ * `components.schemas` entry and a `USES_TYPE` edge from the operation that
64
+ * names it, because in REST the response body *is* the schema the operation
65
+ * returns. **GraphQL does not work that way.** A client selects the fields it
66
+ * wants, so a `USES_TYPE` edge asserting "this operation returns this shape"
67
+ * would be false for every caller that selects a subset — which is every caller.
68
+ * Emitting one would be a wrong edge, and rule 2 puts a wrong edge below a
69
+ * missing one because it corrupts every layer above it. Disclosed gap.
70
+ *
71
+ * **No `USES_API`, and this one is a gate.** `DEC-317` §"The one flagged risk"
72
+ * found that `nearestMiss` rule 2 collapses under GraphQL paths — every
73
+ * operation is arity-2, carries no `{param}`, and draws its first segment from a
74
+ * set of size three — and gated any caller-side GraphQL reader on that being
75
+ * fixed first. `DEC-319` has since given rule 2 a measured similarity floor,
76
+ * which narrows the collapse but does not by itself discharge a gate that was
77
+ * written about a rule's reachability. This adapter builds the **server half
78
+ * only**, so it does not reach `nearestMiss` at all: that function is called
79
+ * from exactly one place, `orphans.ts`'s `withCallers` loop, which requires an
80
+ * endpoint with a `USES_API` caller. Verified in `descry-core` for this change,
81
+ * not inherited.
82
+ */
83
+ import { type LanguageAdapter, type ResolutionLevel } from "@descryy/ir";
84
+ import { type OperationSlot } from "./document.ts";
85
+ export declare const ADAPTER_ID = "adapter-graphql";
86
+ export declare const ADAPTER_VERSION = "0.1.0";
87
+ /**
88
+ * `.graphql` and `.gql`. An introspection `schema.json` is **not** read — see
89
+ * `document.ts`'s declared limits for the census that decided it.
90
+ */
91
+ export declare const DEFAULT_SCHEMA_GLOBS: readonly ["**/*.graphql", "**/*.gql"];
92
+ /** DEC-026: the artifact read, not a programming language. Part of the id since DEC-054. */
93
+ export declare const LANGUAGE = "graphql";
94
+ /**
95
+ * `DEC-317`'s protocol sentinel, repeated here rather than imported.
96
+ *
97
+ * `adapter-python` exports the same constant from `packages/adapter-python/src/graphql.ts`,
98
+ * and importing it would make a format adapter depend on a language adapter to
99
+ * state its own identity — the dependency edge pointing the wrong way, and a
100
+ * package boundary crossed for one string. The value is pinned by the
101
+ * two-producer test instead, which is the guard that actually matters: a
102
+ * shared constant that both sides import can drift from the *decision* without
103
+ * either test noticing, whereas a test that runs both producers cannot.
104
+ */
105
+ export declare const GRAPHQL_METHOD = "GRAPHQL";
106
+ /** `Query` + `circuit` -> `/Query/circuit`. `DEC-317`'s path shape, exactly. */
107
+ export declare function operationPath(slot: OperationSlot, fieldName: string): string;
108
+ export interface GraphqlAdapterOptions {
109
+ readonly maxResolution?: ResolutionLevel;
110
+ readonly parseGlobs?: readonly string[];
111
+ }
112
+ export declare function createGraphqlAdapter(options?: GraphqlAdapterOptions): LanguageAdapter;
113
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AAKH,OAAO,EAYL,KAAK,eAAe,EAGpB,KAAK,eAAe,EAErB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAA4C,KAAK,aAAa,EAAe,MAAM,eAAe,CAAC;AAE1G,eAAO,MAAM,UAAU,oBAAoB,CAAC;AAC5C,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,uCAAwC,CAAC;AAE1E,4FAA4F;AAC5F,eAAO,MAAM,QAAQ,YAAY,CAAC;AAElC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,YAAY,CAAC;AAIxC,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,eAAe,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAOD,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,eAAe,CA2GzF"}
@@ -0,0 +1,294 @@
1
+ /**
2
+ * The GraphQL SDL adapter.
3
+ *
4
+ * The third capability in this project that reaches **R3 with no language
5
+ * adapter at all**, after `adapter-sql` and `adapter-openapi`, and for the same
6
+ * reason all three do: a published schema is *declared*, not deduced. It is a
7
+ * `LanguageAdapter` because it is a per-format reader with a capability matrix,
8
+ * not because SDL is a programming language — `language: "graphql"` describes
9
+ * the artifact it read, DEC-026, exactly the reading `adapter-sql` and
10
+ * `adapter-openapi` get.
11
+ *
12
+ * ## What it mints, and why the identity is not this file's to choose
13
+ *
14
+ * `DEC-317` fixed GraphQL operation identity, transposing `DEC-316`'s gRPC
15
+ * precedent: `method` is the literal sentinel `"GRAPHQL"`, the path is
16
+ * `/<OperationType>/<field>`. That decision was written against Python's
17
+ * strawberry, and its "Consequences" section says any later GraphQL reader
18
+ * "must mint this identical shape". This is the first such reader, so this is
19
+ * the first place that claim is *tested* rather than asserted —
20
+ * `test/sdl-strawberry-join.test.ts` runs both producers over the same
21
+ * operation and compares the emitted ids, in the shape `DEC-321` established
22
+ * for the PHP/SQL `DATABASE_TABLE` join.
23
+ *
24
+ * ## Why this reader supersedes the class-structure one, and how
25
+ *
26
+ * `DEC-317` §"The departure" is candid that strawberry forced a compromise:
27
+ * with no artifact to read, the schema-facing name had to be derived from the
28
+ * class structure, and a name that could only be *computed* had to be refused
29
+ * as `graphqlFieldNameNotReadable`. An SDL field name is the schema-facing name
30
+ * by definition. There is nothing to compute and nothing to refuse.
31
+ *
32
+ * **The precedence is expressed through resolution, not through a priority
33
+ * rule, and that is deliberate.** This adapter emits at R3: the document is the
34
+ * schema. `adapter-python`'s strawberry reader emits its operations at R0 or R1
35
+ * (`extract.ts` — R1 once a field was reached through the import graph). Rule 3,
36
+ * the resolution cap, then does the ranking on its own: an SDL-derived finding
37
+ * is capped at reliability class A and a strawberry-derived one at C or B. No
38
+ * new machinery, no producer allow-list, no "SDL wins" branch anywhere above
39
+ * the IR — the mechanism the engine already has says the right thing, because
40
+ * the two producers genuinely differ in the strength of their evidence.
41
+ *
42
+ * **Where SDL and source disagree, they do not fight — they diverge visibly.**
43
+ * The two producers' `API_ROUTE` nodes are distinct by construction (`API_ROUTE`
44
+ * is language-scoped, so `graphql` and `python` routes never share an id), and
45
+ * that asymmetry is the contract mechanism working as designed: the route is
46
+ * each producer's local view. They meet at the `API_ENDPOINT`, which is fileless
47
+ * and language-less. So:
48
+ *
49
+ * - **agreement** — one `API_ENDPOINT`, two `SERVES_API` edges into it from two
50
+ * routes, at two resolutions. This is the join, and it is the case that
51
+ * proves the convention transposed correctly.
52
+ * - **disagreement on a name** — two `API_ENDPOINT` nodes, one per spelling.
53
+ * The SDL's is the correct one, and it carries R3 while the source-derived one
54
+ * carries R0/R1. A stale committed SDL is the same risk a stale committed
55
+ * `openapi.json` carries and is treated the same way: disclosed, not
56
+ * downgraded. The divergence being *visible* is the useful property — a
57
+ * published schema that no longer matches its source is a real finding, and a
58
+ * reader that silently preferred one would have destroyed the evidence for it.
59
+ *
60
+ * ## What it does not claim, and the two refusals are load-bearing
61
+ *
62
+ * **No `DTO`, and not for scope reasons.** `adapter-openapi` mints a `DTO` per
63
+ * `components.schemas` entry and a `USES_TYPE` edge from the operation that
64
+ * names it, because in REST the response body *is* the schema the operation
65
+ * returns. **GraphQL does not work that way.** A client selects the fields it
66
+ * wants, so a `USES_TYPE` edge asserting "this operation returns this shape"
67
+ * would be false for every caller that selects a subset — which is every caller.
68
+ * Emitting one would be a wrong edge, and rule 2 puts a wrong edge below a
69
+ * missing one because it corrupts every layer above it. Disclosed gap.
70
+ *
71
+ * **No `USES_API`, and this one is a gate.** `DEC-317` §"The one flagged risk"
72
+ * found that `nearestMiss` rule 2 collapses under GraphQL paths — every
73
+ * operation is arity-2, carries no `{param}`, and draws its first segment from a
74
+ * set of size three — and gated any caller-side GraphQL reader on that being
75
+ * fixed first. `DEC-319` has since given rule 2 a measured similarity floor,
76
+ * which narrows the collapse but does not by itself discharge a gate that was
77
+ * written about a rule's reachability. This adapter builds the **server half
78
+ * only**, so it does not reach `nearestMiss` at all: that function is called
79
+ * from exactly one place, `orphans.ts`'s `withCallers` loop, which requires an
80
+ * endpoint with a `USES_API` caller. Verified in `descry-core` for this change,
81
+ * not inherited.
82
+ */
83
+ import { readFileSync } from "node:fs";
84
+ import { join } from "node:path";
85
+ import { endpointQsp, nodeId, normaliseEndpointPath, } from "@descryy/ir";
86
+ import { discover } from "@descryy/adapter-common";
87
+ import { OPERATION_TYPE, readSchema, rootFieldsOf } from "./document.js";
88
+ export const ADAPTER_ID = "adapter-graphql";
89
+ export const ADAPTER_VERSION = "0.1.0";
90
+ /**
91
+ * `.graphql` and `.gql`. An introspection `schema.json` is **not** read — see
92
+ * `document.ts`'s declared limits for the census that decided it.
93
+ */
94
+ export const DEFAULT_SCHEMA_GLOBS = ["**/*.graphql", "**/*.gql"];
95
+ /** DEC-026: the artifact read, not a programming language. Part of the id since DEC-054. */
96
+ export const LANGUAGE = "graphql";
97
+ /**
98
+ * `DEC-317`'s protocol sentinel, repeated here rather than imported.
99
+ *
100
+ * `adapter-python` exports the same constant from `packages/adapter-python/src/graphql.ts`,
101
+ * and importing it would make a format adapter depend on a language adapter to
102
+ * state its own identity — the dependency edge pointing the wrong way, and a
103
+ * package boundary crossed for one string. The value is pinned by the
104
+ * two-producer test instead, which is the guard that actually matters: a
105
+ * shared constant that both sides import can drift from the *decision* without
106
+ * either test noticing, whereas a test that runs both producers cannot.
107
+ */
108
+ export const GRAPHQL_METHOD = "GRAPHQL";
109
+ const PRODUCED_BY = `${ADAPTER_ID}@${ADAPTER_VERSION}`;
110
+ /** `Query` + `circuit` -> `/Query/circuit`. `DEC-317`'s path shape, exactly. */
111
+ export function operationPath(slot, fieldName) {
112
+ return `/${OPERATION_TYPE[slot]}/${fieldName}`;
113
+ }
114
+ export function createGraphqlAdapter(options = {}) {
115
+ const ceiling = options.maxResolution ?? 3;
116
+ const globs = options.parseGlobs ?? DEFAULT_SCHEMA_GLOBS;
117
+ let root;
118
+ const read = (repoRoot, file) => {
119
+ try {
120
+ return { file, schema: readSchema(readFileSync(join(repoRoot.absolutePath, file), "utf8")) };
121
+ }
122
+ catch {
123
+ return { file, schema: undefined };
124
+ }
125
+ };
126
+ /** Every candidate file that actually read as a schema — an executable document does not. */
127
+ const schemasUnder = (repoRoot) => [...new Set(discover(repoRoot.absolutePath, globs))]
128
+ .sort()
129
+ .map((file) => read(repoRoot, file))
130
+ .filter((unit) => unit.schema !== undefined);
131
+ return {
132
+ id: ADAPTER_ID,
133
+ version: ADAPTER_VERSION,
134
+ async detect(repoRoot) {
135
+ const units = schemasUnder(repoRoot);
136
+ if (units.length === 0)
137
+ return { detected: false, roots: [], evidence: [] };
138
+ const operations = units.reduce((sum, unit) => sum + (unit.schema === undefined ? 0 : rootFieldsOf(unit.schema).length), 0);
139
+ return {
140
+ detected: true,
141
+ roots: [...new Set(units.map((unit) => unit.file.split("/")[0] ?? "."))].sort(),
142
+ evidence: [
143
+ `${units.length} GraphQL SDL document(s), ${operations} root operation(s)`,
144
+ "SDL only — an introspection schema.json is not read, by declared limit",
145
+ ],
146
+ };
147
+ },
148
+ capabilities() {
149
+ return {
150
+ maxResolution: ceiling,
151
+ // No DTO and no USES_TYPE: a GraphQL client selects its own fields, so
152
+ // an edge asserting that an operation returns a whole named shape would
153
+ // be wrong for every caller. See the module header.
154
+ nodeTypes: ["API_ROUTE", "API_ENDPOINT"],
155
+ edgeTypes: ["SERVES_API"],
156
+ hasCallHierarchy: false,
157
+ hasTypeHierarchy: false,
158
+ frameworkExtractors: ["graphql-sdl"],
159
+ frameworkCapabilities: ["route-extractor"],
160
+ };
161
+ },
162
+ async prepare(ctx) {
163
+ root = ctx.root;
164
+ // Nothing to prepare and nothing that can fail: no dependency resolution,
165
+ // no type checker, no index. R3 is not optimism — the document *is* the
166
+ // schema, and every name in it is the served name.
167
+ return ceiling;
168
+ },
169
+ async parseFiles(files) {
170
+ const active = root;
171
+ return files.map((file) => ({
172
+ file,
173
+ tree: active === undefined ? { file: file.path, schema: undefined } : read(active, file.path),
174
+ }));
175
+ },
176
+ extractNodes(units) {
177
+ return build(units.map((unit) => unit.tree), root, ceiling).nodes;
178
+ },
179
+ extractEdges(units) {
180
+ return build(units.map((unit) => unit.tree), root, ceiling).edges;
181
+ },
182
+ async emit(ctx) {
183
+ const reached = await this.prepare(ctx);
184
+ const units = schemasUnder(ctx.root);
185
+ const { nodes, edges, unresolved } = build(units, ctx.root, reached);
186
+ return {
187
+ repo: ctx.root.repo,
188
+ ...(ctx.root.workspace === undefined ? {} : { workspace: ctx.root.workspace }),
189
+ commitSha: ctx.root.commitSha,
190
+ producedBy: PRODUCED_BY,
191
+ sourceFiles: units.map((unit) => unit.file),
192
+ // `schemasUnder` already filters to units that read as a schema — a
193
+ // `.graphql` file holding an executable document is excluded from
194
+ // `units` (and so from `sourceFiles`) without reaching this session,
195
+ // exactly as `adapter-openapi` handles an unparseable contract.
196
+ skippedFiles: [],
197
+ reachedResolution: reached,
198
+ nodes,
199
+ edges,
200
+ unresolved,
201
+ };
202
+ },
203
+ async dispose() {
204
+ root = undefined;
205
+ },
206
+ };
207
+ }
208
+ function build(units, repoRoot, reached) {
209
+ if (repoRoot === undefined)
210
+ return { nodes: [], edges: [], unresolved: [] };
211
+ const nodes = new Map();
212
+ const edges = new Map();
213
+ const unresolved = [];
214
+ const scope = { repo: repoRoot.repo, workspace: repoRoot.workspace };
215
+ for (const unit of units) {
216
+ const schema = unit.schema;
217
+ if (schema === undefined)
218
+ continue;
219
+ let anchorId;
220
+ for (const field of rootFieldsOf(schema)) {
221
+ const served = operationPath(field.slot, field.name);
222
+ // `${method} ${served}` and `endpointQsp(method, served)` are the two
223
+ // minting sites `DEC-317` fixed, spelled here exactly as
224
+ // `adapter-python`'s `emitDjangoRoute` spells them. The two-producer test
225
+ // is what holds them equal; this comment is not.
226
+ const routeId = nodeId(scope, "API_ROUTE", `${GRAPHQL_METHOD} ${served}`, LANGUAGE);
227
+ if (!nodes.has(routeId)) {
228
+ anchorId ??= routeId;
229
+ nodes.set(routeId, {
230
+ id: routeId,
231
+ type: "API_ROUTE",
232
+ name: `${GRAPHQL_METHOD} ${served}`,
233
+ file: unit.file,
234
+ range: { startLine: field.line, endLine: field.line },
235
+ language: LANGUAGE,
236
+ producedBy: PRODUCED_BY,
237
+ resolution: reached,
238
+ attrs: {
239
+ method: GRAPHQL_METHOD,
240
+ pathTemplate: normaliseEndpointPath(served),
241
+ rawTemplate: served,
242
+ framework: "graphql-sdl",
243
+ operationType: OPERATION_TYPE[field.slot],
244
+ },
245
+ });
246
+ }
247
+ // Fileless AND language-less. This node is where an SDL-derived operation
248
+ // and a strawberry-derived one for the same real operation meet, and
249
+ // `nodeId` throws if a fileless type is hashed with a language — the guard
250
+ // against an id whose only symptom would be a join that silently does not
251
+ // happen.
252
+ const endpointId = nodeId(scope, "API_ENDPOINT", endpointQsp(GRAPHQL_METHOD, served), null);
253
+ if (!nodes.has(endpointId)) {
254
+ nodes.set(endpointId, {
255
+ id: endpointId,
256
+ type: "API_ENDPOINT",
257
+ name: `${GRAPHQL_METHOD} ${normaliseEndpointPath(served)}`,
258
+ file: null,
259
+ range: null,
260
+ language: null,
261
+ producedBy: PRODUCED_BY,
262
+ resolution: reached,
263
+ attrs: { method: GRAPHQL_METHOD, pathTemplate: normaliseEndpointPath(served) },
264
+ });
265
+ }
266
+ edges.set(`${routeId} ${endpointId} SERVES_API`, {
267
+ from: routeId,
268
+ to: endpointId,
269
+ type: "SERVES_API",
270
+ producedBy: PRODUCED_BY,
271
+ resolution: reached,
272
+ confidence: 0.95,
273
+ });
274
+ }
275
+ // Every refusal, anchored to a node the batch actually contains. A ledger
276
+ // entry naming a node that was never emitted is a dangling reference
277
+ // dressed up as a disclosure.
278
+ if (anchorId === undefined)
279
+ continue;
280
+ for (const refusal of schema.refused) {
281
+ unresolved.push({
282
+ fromNodeId: anchorId,
283
+ edgeType: "SERVES_API",
284
+ rawTarget: refusal.what.slice(0, 120),
285
+ file: unit.file,
286
+ line: refusal.line,
287
+ producedBy: PRODUCED_BY,
288
+ reason: refusal.why,
289
+ });
290
+ }
291
+ }
292
+ return { nodes: [...nodes.values()], edges: [...edges.values()], unresolved };
293
+ }
294
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Reading a GraphQL SDL document, and why this is the *strong* half of the
3
+ * GraphQL story rather than a convenience.
4
+ *
5
+ * `DEC-317` built GraphQL operation identity for Python/strawberry, and was
6
+ * explicit about the compromise it had to make. gRPC's precedent
7
+ * (`DEC-316`) rests on **"the path is read, not assembled"** — protoc writes
8
+ * `Service_Method_FullMethodName = "/pkg.Service/Method"` and the reader takes
9
+ * that literal verbatim. strawberry writes no such artifact: the schema is
10
+ * built at import time out of the class structure, the schema-facing name is
11
+ * camel-cased by default, and so `DEC-317` had to narrow itself to the three
12
+ * cases in which a name is genuinely *read* and refuse the rest as
13
+ * `graphqlFieldNameNotReadable`.
14
+ *
15
+ * **An SDL artifact removes the compromise entirely.** A field name in SDL is
16
+ * the schema-facing name — not a Python attribute that a naming converter will
17
+ * later transform, not a value a default might change, but the string the
18
+ * server publishes and a client types. There is nothing to compute, nothing to
19
+ * resolve and nothing to refuse on naming grounds. `DEC-317` §"The three
20
+ * sub-questions" says so outright: where an SDL artifact exists it "**is** the
21
+ * protoc-const analogue and should be preferred over this mechanism outright".
22
+ * This reader is that preference, built.
23
+ *
24
+ * ## Why a lexer and not a regex
25
+ *
26
+ * The naive rule — *a `Name` followed by `:` inside a type body is a field* —
27
+ * fails on the first real schema it meets, in four separate ways that Saleor's
28
+ * `saleor/graphql/schema.graphql` contains thousands of instances of:
29
+ *
30
+ * | construct | what the naive rule does |
31
+ * | --- | --- |
32
+ * | `webhook(id: ID!, filter: F = { channel: "x" }): Webhook` | emits `id`, `filter` and `channel` as operations |
33
+ * | `webhookEvents: [E!] @doc(category: "Webhooks")` | emits `category` |
34
+ * | `"""A description with a { brace and a colon: here."""` | emits whatever the prose contains |
35
+ * | `# a comment` | the same |
36
+ *
37
+ * So the document is tokenised properly — block strings, strings, comments and
38
+ * punctuation — and a field is admitted only in the one position the grammar
39
+ * puts one: a `Name`, at the type body's own brace depth and outside every
40
+ * parenthesis, followed (past a balanced argument list, if it has one) by `:`.
41
+ *
42
+ * ## Declared limits
43
+ *
44
+ * **`.graphql`/`.gql` only — an introspection `schema.json` is not read.**
45
+ * `DEC-317` names it as a third artifact that could carry the same truth, and
46
+ * it could. It is not built because **no repository on hand contains one**: a
47
+ * census of 52 reference repositories plus Saleor found two `.graphql` files
48
+ * and zero GraphQL introspection JSON documents. Building a second format
49
+ * reader against documentation with no source to measure it on is the thing
50
+ * `DEC-317`'s own graphene paragraph refuses to do, and it would be no more
51
+ * defensible here. Disclosed gap, not a silent one.
52
+ *
53
+ * **One file is one document.** A schema block naming a root type that the same
54
+ * file does not declare earns a ledger row rather than a search of the other
55
+ * `.graphql` files in the repository. SDL *can* legally be split across files,
56
+ * and where it is this reader under-reports and says so; both real artifacts
57
+ * measured here are single-file, so cross-file stitching would be reach built
58
+ * against zero demand, and a wrong stitch — pairing a schema block with a
59
+ * same-named type from an unrelated schema — is a silently wrong answer rather
60
+ * than a missing one.
61
+ *
62
+ * **Executable documents are not schemas.** A `.graphql` file holding
63
+ * `query IntrospectionQuery { ... }` or a fragment is a *client* document;
64
+ * twenty ships exactly one. It yields no type-system definition, so it yields
65
+ * no schema, and `readSchema` returns `undefined` rather than minting
66
+ * operations named after an introspection payload.
67
+ */
68
+ /** GraphQL's three root operation types, fixed by the specification. */
69
+ export declare const OPERATION_SLOTS: readonly ["query", "mutation", "subscription"];
70
+ export type OperationSlot = (typeof OPERATION_SLOTS)[number];
71
+ /**
72
+ * The path segment each slot contributes, and the type name each slot defaults
73
+ * to when the document declares no `schema` block.
74
+ *
75
+ * **These two columns are the same word for a reason, and it is not a
76
+ * coincidence worth collapsing.** The left is GraphQL's operation-type
77
+ * vocabulary, which `DEC-317` puts in the path; the right is the specification's
78
+ * default root type name (October 2021 §3.3.1), which a `schema` block may
79
+ * override. Saleor overrides nothing and still writes the block; twenty writes
80
+ * no block at all. Keeping them apart is what makes `schema { query: RootQuery }`
81
+ * yield `/Query/…` rather than `/RootQuery/…`.
82
+ */
83
+ export declare const OPERATION_TYPE: Readonly<Record<OperationSlot, string>>;
84
+ export interface Refusal {
85
+ readonly what: string;
86
+ readonly why: string;
87
+ readonly line: number;
88
+ }
89
+ export interface RootField {
90
+ readonly slot: OperationSlot;
91
+ /**
92
+ * The schema-facing name, **read verbatim**. There is no other kind here —
93
+ * that is the whole reason this adapter is worth more than the class-structure
94
+ * mechanism it supersedes.
95
+ */
96
+ readonly name: string;
97
+ readonly line: number;
98
+ }
99
+ export interface Schema {
100
+ /** Slot -> the type name occupying it, as the document states or defaults it. */
101
+ readonly roots: ReadonlyMap<OperationSlot, string>;
102
+ /** Whether the roots came from a `schema` block or from the specification's defaults. */
103
+ readonly rootsDeclared: boolean;
104
+ readonly fields: ReadonlyMap<string, readonly RootField[]>;
105
+ readonly refused: readonly Refusal[];
106
+ }
107
+ /**
108
+ * The type-system definitions of one document.
109
+ *
110
+ * Returns `undefined` when the text yields no root operation type at all —
111
+ * an executable document, a fragment library, or a file that is not SDL.
112
+ */
113
+ export declare function readSchema(text: string): Schema | undefined;
114
+ /** Every root operation the document declares, in slot then declaration order. */
115
+ export declare function rootFieldsOf(schema: Schema): readonly RootField[];
116
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAEH,wEAAwE;AACxE,eAAO,MAAM,eAAe,gDAAiD,CAAC;AAC9E,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAIlE,CAAC;AAIF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,MAAM;IACrB,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnD,yFAAyF;IACzF,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;IAC3D,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC;CACtC;AAkND;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA8H3D;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,SAAS,EAAE,CAQjE"}
@@ -0,0 +1,415 @@
1
+ /**
2
+ * Reading a GraphQL SDL document, and why this is the *strong* half of the
3
+ * GraphQL story rather than a convenience.
4
+ *
5
+ * `DEC-317` built GraphQL operation identity for Python/strawberry, and was
6
+ * explicit about the compromise it had to make. gRPC's precedent
7
+ * (`DEC-316`) rests on **"the path is read, not assembled"** — protoc writes
8
+ * `Service_Method_FullMethodName = "/pkg.Service/Method"` and the reader takes
9
+ * that literal verbatim. strawberry writes no such artifact: the schema is
10
+ * built at import time out of the class structure, the schema-facing name is
11
+ * camel-cased by default, and so `DEC-317` had to narrow itself to the three
12
+ * cases in which a name is genuinely *read* and refuse the rest as
13
+ * `graphqlFieldNameNotReadable`.
14
+ *
15
+ * **An SDL artifact removes the compromise entirely.** A field name in SDL is
16
+ * the schema-facing name — not a Python attribute that a naming converter will
17
+ * later transform, not a value a default might change, but the string the
18
+ * server publishes and a client types. There is nothing to compute, nothing to
19
+ * resolve and nothing to refuse on naming grounds. `DEC-317` §"The three
20
+ * sub-questions" says so outright: where an SDL artifact exists it "**is** the
21
+ * protoc-const analogue and should be preferred over this mechanism outright".
22
+ * This reader is that preference, built.
23
+ *
24
+ * ## Why a lexer and not a regex
25
+ *
26
+ * The naive rule — *a `Name` followed by `:` inside a type body is a field* —
27
+ * fails on the first real schema it meets, in four separate ways that Saleor's
28
+ * `saleor/graphql/schema.graphql` contains thousands of instances of:
29
+ *
30
+ * | construct | what the naive rule does |
31
+ * | --- | --- |
32
+ * | `webhook(id: ID!, filter: F = { channel: "x" }): Webhook` | emits `id`, `filter` and `channel` as operations |
33
+ * | `webhookEvents: [E!] @doc(category: "Webhooks")` | emits `category` |
34
+ * | `"""A description with a { brace and a colon: here."""` | emits whatever the prose contains |
35
+ * | `# a comment` | the same |
36
+ *
37
+ * So the document is tokenised properly — block strings, strings, comments and
38
+ * punctuation — and a field is admitted only in the one position the grammar
39
+ * puts one: a `Name`, at the type body's own brace depth and outside every
40
+ * parenthesis, followed (past a balanced argument list, if it has one) by `:`.
41
+ *
42
+ * ## Declared limits
43
+ *
44
+ * **`.graphql`/`.gql` only — an introspection `schema.json` is not read.**
45
+ * `DEC-317` names it as a third artifact that could carry the same truth, and
46
+ * it could. It is not built because **no repository on hand contains one**: a
47
+ * census of 52 reference repositories plus Saleor found two `.graphql` files
48
+ * and zero GraphQL introspection JSON documents. Building a second format
49
+ * reader against documentation with no source to measure it on is the thing
50
+ * `DEC-317`'s own graphene paragraph refuses to do, and it would be no more
51
+ * defensible here. Disclosed gap, not a silent one.
52
+ *
53
+ * **One file is one document.** A schema block naming a root type that the same
54
+ * file does not declare earns a ledger row rather than a search of the other
55
+ * `.graphql` files in the repository. SDL *can* legally be split across files,
56
+ * and where it is this reader under-reports and says so; both real artifacts
57
+ * measured here are single-file, so cross-file stitching would be reach built
58
+ * against zero demand, and a wrong stitch — pairing a schema block with a
59
+ * same-named type from an unrelated schema — is a silently wrong answer rather
60
+ * than a missing one.
61
+ *
62
+ * **Executable documents are not schemas.** A `.graphql` file holding
63
+ * `query IntrospectionQuery { ... }` or a fragment is a *client* document;
64
+ * twenty ships exactly one. It yields no type-system definition, so it yields
65
+ * no schema, and `readSchema` returns `undefined` rather than minting
66
+ * operations named after an introspection payload.
67
+ */
68
+ /** GraphQL's three root operation types, fixed by the specification. */
69
+ export const OPERATION_SLOTS = ["query", "mutation", "subscription"];
70
+ /**
71
+ * The path segment each slot contributes, and the type name each slot defaults
72
+ * to when the document declares no `schema` block.
73
+ *
74
+ * **These two columns are the same word for a reason, and it is not a
75
+ * coincidence worth collapsing.** The left is GraphQL's operation-type
76
+ * vocabulary, which `DEC-317` puts in the path; the right is the specification's
77
+ * default root type name (October 2021 §3.3.1), which a `schema` block may
78
+ * override. Saleor overrides nothing and still writes the block; twenty writes
79
+ * no block at all. Keeping them apart is what makes `schema { query: RootQuery }`
80
+ * yield `/Query/…` rather than `/RootQuery/…`.
81
+ */
82
+ export const OPERATION_TYPE = {
83
+ query: "Query",
84
+ mutation: "Mutation",
85
+ subscription: "Subscription",
86
+ };
87
+ const DEFAULT_ROOT_TYPE = OPERATION_TYPE;
88
+ const isNameStart = (c) => /[_A-Za-z]/.test(c);
89
+ const isNameChar = (c) => /[_0-9A-Za-z]/.test(c);
90
+ /**
91
+ * Tokens, with comments and commas dropped.
92
+ *
93
+ * Numbers and the rest of the value grammar are deliberately *not* classified:
94
+ * nothing this reader decides depends on telling `1` from `x`, and every value
95
+ * it might meet sits inside a parenthesis or a brace it is already skipping.
96
+ * A digit run therefore falls through to the single-character `punct` arm,
97
+ * which is harmless — it can never be mistaken for a `name`, which is the only
98
+ * classification that carries a decision.
99
+ */
100
+ function tokenise(text) {
101
+ const tokens = [];
102
+ let index = 0;
103
+ let line = 1;
104
+ while (index < text.length) {
105
+ const char = text[index];
106
+ if (char === "\n") {
107
+ line += 1;
108
+ index += 1;
109
+ continue;
110
+ }
111
+ if (char === " " || char === "\t" || char === "\r" || char === "," || char === "") {
112
+ index += 1;
113
+ continue;
114
+ }
115
+ // A comment runs to end of line and can say anything at all, including
116
+ // something shaped exactly like a field.
117
+ if (char === "#") {
118
+ while (index < text.length && text[index] !== "\n")
119
+ index += 1;
120
+ continue;
121
+ }
122
+ if (char === '"') {
123
+ const startLine = line;
124
+ // A block string is the case that matters: Saleor's descriptions contain
125
+ // braces, quotes and colons, and a reader that scanned to the next `"`
126
+ // would resume parsing in the middle of prose.
127
+ if (text.startsWith('"""', index)) {
128
+ index += 3;
129
+ while (index < text.length) {
130
+ if (text[index] === "\\" && text.startsWith('"""', index + 1)) {
131
+ index += 4;
132
+ continue;
133
+ }
134
+ if (text.startsWith('"""', index)) {
135
+ index += 3;
136
+ break;
137
+ }
138
+ if (text[index] === "\n")
139
+ line += 1;
140
+ index += 1;
141
+ }
142
+ }
143
+ else {
144
+ index += 1;
145
+ while (index < text.length && text[index] !== '"') {
146
+ if (text[index] === "\\")
147
+ index += 1;
148
+ if (text[index] === "\n")
149
+ line += 1;
150
+ index += 1;
151
+ }
152
+ index += 1;
153
+ }
154
+ tokens.push({ kind: "string", value: "", line: startLine });
155
+ continue;
156
+ }
157
+ if (isNameStart(char)) {
158
+ const start = index;
159
+ while (index < text.length && isNameChar(text[index]))
160
+ index += 1;
161
+ tokens.push({ kind: "name", value: text.slice(start, index), line });
162
+ continue;
163
+ }
164
+ tokens.push({ kind: "punct", value: char, line });
165
+ index += 1;
166
+ }
167
+ return tokens;
168
+ }
169
+ /** The index just past the balanced `(`…`)` or `{`…`}` opening at `from`. */
170
+ function skipBalanced(tokens, from, open, close) {
171
+ let depth = 0;
172
+ let index = from;
173
+ for (; index < tokens.length; index += 1) {
174
+ const token = tokens[index];
175
+ if (token.kind !== "punct")
176
+ continue;
177
+ if (token.value === open)
178
+ depth += 1;
179
+ else if (token.value === close) {
180
+ depth -= 1;
181
+ if (depth === 0)
182
+ return index + 1;
183
+ }
184
+ }
185
+ return tokens.length;
186
+ }
187
+ /**
188
+ * The fields a type body declares, read from the token just past its `{`.
189
+ *
190
+ * A field is a `Name` at the body's own depth, outside every parenthesis,
191
+ * followed — past its argument list if it has one — by `:`. That trailing colon
192
+ * is what does the precision work: `@doc(category: "x")` puts `doc` in exactly
193
+ * the same position as a field name and is separated from one only by what
194
+ * comes after its parentheses.
195
+ */
196
+ function fieldsIn(tokens, bodyStart) {
197
+ const fields = [];
198
+ let index = bodyStart;
199
+ let depth = 1;
200
+ while (index < tokens.length && depth > 0) {
201
+ const token = tokens[index];
202
+ if (token.kind === "punct") {
203
+ if (token.value === "{") {
204
+ depth += 1;
205
+ index += 1;
206
+ continue;
207
+ }
208
+ if (token.value === "}") {
209
+ depth -= 1;
210
+ index += 1;
211
+ continue;
212
+ }
213
+ if (token.value === "(") {
214
+ index = skipBalanced(tokens, index, "(", ")");
215
+ continue;
216
+ }
217
+ // `@` — the directive's own name follows and is not a field. Skipping it
218
+ // here is belt-and-braces: the trailing-colon test already rejects it.
219
+ if (token.value === "@") {
220
+ index += 2;
221
+ continue;
222
+ }
223
+ index += 1;
224
+ continue;
225
+ }
226
+ if (token.kind !== "name" || depth !== 1) {
227
+ index += 1;
228
+ continue;
229
+ }
230
+ let next = index + 1;
231
+ if (tokens[next]?.kind === "punct" && tokens[next].value === "(") {
232
+ next = skipBalanced(tokens, next, "(", ")");
233
+ }
234
+ if (tokens[next]?.kind === "punct" && tokens[next].value === ":") {
235
+ fields.push({ slot: "query", name: token.value, line: token.line });
236
+ index = next + 1;
237
+ continue;
238
+ }
239
+ index += 1;
240
+ }
241
+ return { fields, end: index };
242
+ }
243
+ /** `schema { query: Query … }` — the slot map, and a ledger row for any slot that is not a bare name. */
244
+ function readSchemaBlock(tokens, bodyStart, roots, refused) {
245
+ let index = bodyStart;
246
+ while (index < tokens.length) {
247
+ const token = tokens[index];
248
+ if (token.kind === "punct" && token.value === "}")
249
+ return index + 1;
250
+ const slot = OPERATION_SLOTS.find((candidate) => token.kind === "name" && token.value === candidate);
251
+ if (slot === undefined) {
252
+ index += 1;
253
+ continue;
254
+ }
255
+ if (!(tokens[index + 1]?.kind === "punct" && tokens[index + 1].value === ":")) {
256
+ index += 1;
257
+ continue;
258
+ }
259
+ const value = tokens[index + 2];
260
+ if (value?.kind === "name") {
261
+ roots.set(slot, value.value);
262
+ index += 3;
263
+ continue;
264
+ }
265
+ // `query: [Query]` and friends. Legal SDL forbids it, but a hand-edited or
266
+ // generated document can contain anything, and picking the name out of a
267
+ // wrapper would be a guess about what the server actually serves.
268
+ refused.push({
269
+ what: slot,
270
+ why: `the schema block's ${slot} slot is not a bare type name, so the root type it names cannot be read`,
271
+ line: token.line,
272
+ });
273
+ index += 2;
274
+ }
275
+ return index;
276
+ }
277
+ /**
278
+ * The type-system definitions of one document.
279
+ *
280
+ * Returns `undefined` when the text yields no root operation type at all —
281
+ * an executable document, a fragment library, or a file that is not SDL.
282
+ */
283
+ export function readSchema(text) {
284
+ const tokens = tokenise(text);
285
+ const roots = new Map();
286
+ const refused = [];
287
+ const byType = new Map();
288
+ let sawSchemaBlock = false;
289
+ let sawTypeDefinition = false;
290
+ let index = 0;
291
+ while (index < tokens.length) {
292
+ const token = tokens[index];
293
+ if (token.kind !== "name") {
294
+ index += 1;
295
+ continue;
296
+ }
297
+ if (token.value === "schema") {
298
+ // `schema @link(...) { … }` is legal; skip to the body the same way a
299
+ // type definition's directives are skipped.
300
+ let cursor = index + 1;
301
+ while (cursor < tokens.length) {
302
+ const next = tokens[cursor];
303
+ if (next.kind === "punct" && next.value === "(") {
304
+ cursor = skipBalanced(tokens, cursor, "(", ")");
305
+ continue;
306
+ }
307
+ if (next.kind === "punct" && next.value === "{")
308
+ break;
309
+ if (next.kind === "punct" && next.value === "}")
310
+ break;
311
+ cursor += 1;
312
+ }
313
+ if (tokens[cursor]?.kind === "punct" && tokens[cursor].value === "{") {
314
+ sawSchemaBlock = true;
315
+ index = readSchemaBlock(tokens, cursor + 1, roots, refused);
316
+ continue;
317
+ }
318
+ index += 1;
319
+ continue;
320
+ }
321
+ // `type X` and `extend type X`. Only object types can be a root operation
322
+ // type — an `input`, `interface`, `enum`, `union` or `scalar` never is.
323
+ const isExtend = token.value === "extend" && tokens[index + 1]?.value === "type";
324
+ if (token.value !== "type" && !isExtend) {
325
+ index += 1;
326
+ continue;
327
+ }
328
+ const nameToken = tokens[index + (isExtend ? 2 : 1)];
329
+ if (nameToken?.kind !== "name") {
330
+ index += 1;
331
+ continue;
332
+ }
333
+ // Past `implements A & B` and any directives, to the body.
334
+ let cursor = index + (isExtend ? 3 : 2);
335
+ while (cursor < tokens.length) {
336
+ const next = tokens[cursor];
337
+ if (next.kind === "punct" && next.value === "(") {
338
+ cursor = skipBalanced(tokens, cursor, "(", ")");
339
+ continue;
340
+ }
341
+ if (next.kind === "punct" && next.value === "{")
342
+ break;
343
+ // A type extension may have no body at all (`extend type X @dir`), and a
344
+ // bare `type X` ends where the next definition begins.
345
+ if (next.kind === "name" && (next.value === "type" || next.value === "extend" || next.value === "schema")) {
346
+ break;
347
+ }
348
+ cursor += 1;
349
+ }
350
+ if (!(tokens[cursor]?.kind === "punct" && tokens[cursor].value === "{")) {
351
+ index = cursor;
352
+ continue;
353
+ }
354
+ sawTypeDefinition = true;
355
+ const { fields, end } = fieldsIn(tokens, cursor + 1);
356
+ const existing = byType.get(nameToken.value);
357
+ if (existing === undefined)
358
+ byType.set(nameToken.value, fields);
359
+ else
360
+ existing.push(...fields);
361
+ index = end;
362
+ }
363
+ if (!sawTypeDefinition)
364
+ return undefined;
365
+ if (!sawSchemaBlock) {
366
+ // The specification's defaults. This assembles no name that is not written
367
+ // in the file: the *field* names are still read verbatim, and the three
368
+ // root type words are GraphQL's own, fixed by the grammar — the same
369
+ // footing on which `DEC-317` assembles the `/Query/` prefix from a slot.
370
+ for (const slot of OPERATION_SLOTS) {
371
+ if (byType.has(DEFAULT_ROOT_TYPE[slot]))
372
+ roots.set(slot, DEFAULT_ROOT_TYPE[slot]);
373
+ }
374
+ }
375
+ // **Not `roots.size === 0`.** A document whose `schema` block declares roots
376
+ // this reader could not read has zero roots and something to say, and
377
+ // returning `undefined` there would drop the refusal on the floor — the
378
+ // adapter would report "no GraphQL here" about a file that plainly contains
379
+ // a schema. Silence is what rule 7 forbids; the empty result must arrive
380
+ // carrying its reasons.
381
+ if (roots.size === 0 && refused.length === 0)
382
+ return undefined;
383
+ const fields = new Map();
384
+ for (const [slot, typeName] of roots) {
385
+ const declared = byType.get(typeName);
386
+ if (declared === undefined) {
387
+ refused.push({
388
+ what: typeName,
389
+ why: `the schema block names ${typeName} as the ${slot} root, but this document does not declare it — ` +
390
+ "SDL split across files is not stitched, by declared limit",
391
+ line: 1,
392
+ });
393
+ continue;
394
+ }
395
+ // Illegal in valid SDL, but a duplicate would otherwise report one
396
+ // operation twice and inflate every count this adapter is measured by.
397
+ const seen = new Set();
398
+ fields.set(typeName, declared
399
+ .filter((field) => (seen.has(field.name) ? false : (seen.add(field.name), true)))
400
+ .map((field) => ({ ...field, slot })));
401
+ }
402
+ return { roots, rootsDeclared: sawSchemaBlock, fields, refused };
403
+ }
404
+ /** Every root operation the document declares, in slot then declaration order. */
405
+ export function rootFieldsOf(schema) {
406
+ const out = [];
407
+ for (const slot of OPERATION_SLOTS) {
408
+ const typeName = schema.roots.get(slot);
409
+ if (typeName === undefined)
410
+ continue;
411
+ out.push(...(schema.fields.get(typeName) ?? []));
412
+ }
413
+ return out;
414
+ }
415
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ADAPTER_ID, ADAPTER_VERSION, DEFAULT_SCHEMA_GLOBS, GRAPHQL_METHOD, LANGUAGE, createGraphqlAdapter, operationPath, type GraphqlAdapterOptions, } from "./adapter.ts";
2
+ export { OPERATION_SLOTS, OPERATION_TYPE, readSchema, rootFieldsOf, type OperationSlot, type Refusal, type RootField, type Schema, } from "./document.ts";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,QAAQ,EACR,oBAAoB,EACpB,aAAa,EACb,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,eAAe,EACf,cAAc,EACd,UAAU,EACV,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,MAAM,GACZ,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ADAPTER_ID, ADAPTER_VERSION, DEFAULT_SCHEMA_GLOBS, GRAPHQL_METHOD, LANGUAGE, createGraphqlAdapter, operationPath, } from "./adapter.js";
2
+ export { OPERATION_SLOTS, OPERATION_TYPE, readSchema, rootFieldsOf, } from "./document.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,QAAQ,EACR,oBAAoB,EACpB,aAAa,GAEd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,eAAe,EACf,cAAc,EACd,UAAU,EACV,YAAY,GAKb,MAAM,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@descryy/adapter-graphql",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "GraphQL SDL adapter. Reaches R3 with no language adapter at all \u2014 a published schema states its own operations, and their names are read rather than computed.",
6
+ "license": "UNLICENSED",
7
+ "engines": {
8
+ "node": ">=22.5"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "registry": "https://registry.npmjs.org",
21
+ "access": "public"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc -b"
25
+ },
26
+ "dependencies": {
27
+ "@descryy/adapter-common": "0.1.0",
28
+ "@descryy/ir": "0.3.0",
29
+ "@descryy/adapter-python": "0.1.0"
30
+ }
31
+ }