Skip to content

Commit a208f1c

Browse files
authored
feat: schema contract composition (#180)
Adds utility for composing a schema contract. We already had this code within Hive console, but it makes sense to move this here so people that do not use a schema registry can benefit from it as well. See graphql-hive/console#6964
1 parent 34368d8 commit a208f1c

10 files changed

+4724
-0
lines changed

.changeset/plenty-foxes-guess.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
"@theguild/federation-composition": minor
3+
---
4+
5+
Add `composeSchemaContract` function for composing schema contracts.
6+
7+
Running the following script:
8+
9+
```ts
10+
import { composeSchemaContract } from "@theguild/federation-composition";
11+
import { parse } from "graphql";
12+
13+
const result = composeSchemaContract(
14+
[
15+
{
16+
name: "a",
17+
typeDefs: parse(/* GraphQL */ `
18+
type Query {
19+
a: String @tag(name: "public")
20+
}
21+
`),
22+
url: "a.localhost",
23+
},
24+
{
25+
name: "b",
26+
typeDefs: parse(/* GraphQL */ `
27+
type Query {
28+
b: String
29+
}
30+
`),
31+
url: "b.localhost",
32+
},
33+
],
34+
/** Tags to include and exclude */
35+
{
36+
include: new Set(["public"]),
37+
exclude: new Set(),
38+
},
39+
/** Exclude unreachable types */
40+
true,
41+
);
42+
43+
console.log(result.publicSdl);
44+
```
45+
46+
Will result in the output containing only the fields tagged with `public`:
47+
48+
```graphql
49+
type Query {
50+
a: String!
51+
}
52+
```
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { parse } from "graphql";
2+
import { CompositionSuccess, extractLinkImplementations } from "../../src";
3+
import { addInaccessibleToUnreachableTypes } from "../../src/contracts/add-inaccessible-to-unreachable-types";
4+
import { composeServices } from "../../src";
5+
import { expect, test } from "vitest";
6+
7+
test("Filters based on tags", async () => {
8+
let compositionResult = composeServices([
9+
{
10+
name: "user",
11+
url: "https://user-example.graphql-hive.com",
12+
typeDefs: parse(`
13+
type Query {
14+
user: User
15+
}
16+
type User {
17+
id: ID!
18+
name: String
19+
}
20+
21+
type Unused {
22+
foo: String
23+
}
24+
`),
25+
},
26+
]);
27+
28+
expect(compositionResult.errors).toBe(undefined);
29+
expect(compositionResult.supergraphSdl).not.toBe(undefined);
30+
const { resolveImportName } = extractLinkImplementations(
31+
parse(compositionResult.supergraphSdl!),
32+
);
33+
34+
compositionResult = addInaccessibleToUnreachableTypes(
35+
resolveImportName,
36+
compositionResult as CompositionSuccess,
37+
);
38+
39+
expect(compositionResult.supergraphSdl).toMatchInlineSnapshot(`
40+
"schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) {
41+
query: Query
42+
}
43+
44+
directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE
45+
46+
directive @join__graph(name: String!, url: String!) on ENUM_VALUE
47+
48+
directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
49+
50+
directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
51+
52+
directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true, isInterfaceObject: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
53+
54+
directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION
55+
56+
scalar join__FieldSet
57+
58+
directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
59+
60+
scalar link__Import
61+
62+
enum link__Purpose {
63+
"""
64+
\`SECURITY\` features provide metadata necessary to securely resolve fields.
65+
"""
66+
SECURITY
67+
"""
68+
\`EXECUTION\` features provide metadata necessary for operation execution.
69+
"""
70+
EXECUTION
71+
}
72+
73+
enum join__Graph {
74+
USER @join__graph(name: "user", url: "https://user-example.graphql-hive.com")
75+
}
76+
77+
type Query @join__type(graph: USER) {
78+
user: User
79+
}
80+
81+
type User @join__type(graph: USER) {
82+
id: ID!
83+
name: String
84+
}
85+
86+
type Unused @join__type(graph: USER) @inaccessible {
87+
foo: String
88+
}"
89+
`);
90+
expect(compositionResult.publicSdl).toMatchInlineSnapshot(`
91+
"type Query {
92+
user: User
93+
}
94+
95+
type User {
96+
id: ID!
97+
name: String
98+
}"
99+
`);
100+
});

0 commit comments

Comments
 (0)