Skip to content

Commit

Permalink
enhance(compose): avoid extra @transport annotation if unnecessary (#…
Browse files Browse the repository at this point in the history
…7936)

* enhance(compose): avoid extra `@transport` annotation if unnecessary

* Fix
  • Loading branch information
ardatan committed Nov 20, 2024
1 parent a8333fc commit 489b7c7
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 309 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-eyes-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-mesh/fusion-composition': patch
---

Do not create extra \`@transport\` annotation if the subgraph is a regular HTTP subgraph
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,12 @@ directive @httpOperation(
) repeatable on FIELD_DEFINITION
directive @transport(
subgraph: String!
kind: String!
location: String!
subgraph: String
kind: String
location: String
headers: [[String]]
queryStringOptions: ObjMap
queryParams: [[String]]
options: TransportOptions
) repeatable on SCHEMA
directive @hidden on FIELD_DEFINITION | OBJECT | INTERFACE | INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_OBJECT
Expand Down Expand Up @@ -154,14 +153,12 @@ scalar File @join__type(graph: PETSTORE)
scalar ObjMap @join__type(graph: PETSTORE)
scalar _DirectiveExtensions @join__type(graph: PETSTORE) @join__type(graph: VACCINATION)
scalar _DirectiveExtensions @join__type(graph: PETSTORE)
scalar TransportOptions @join__type(graph: VACCINATION)
type Query @extraSchemaDefinitionDirective(
directives: {transport: [{subgraph: "petstore", kind: "rest", location: "http://localhost:<petstore_port>/api/v3"}]}
) @extraSchemaDefinitionDirective(
directives: {transport: [{kind: "http", subgraph: "vaccination", location: "http://localhost:<vaccination_port>/graphql", options: {}}]}
) @join__type(graph: PETSTORE) @join__type(graph: VACCINATION) {
"""
Multiple status values can be provided with comma separated strings
Expand Down
15 changes: 4 additions & 11 deletions e2e/federation-mixed/__snapshots__/federation-mixed.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,12 @@ directive @httpOperation(
) repeatable on FIELD_DEFINITION
directive @transport(
subgraph: String!
kind: String!
location: String!
subgraph: String
kind: String
location: String
headers: [[String]]
queryStringOptions: ObjMap
queryParams: [[String]]
options: TransportOptions
) repeatable on SCHEMA
directive @source(name: String!, type: String, subgraph: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
Expand All @@ -125,18 +124,12 @@ directive @extraSchemaDefinitionDirective(directives: _DirectiveExtensions) rep
scalar ObjMap @join__type(graph: ACCOUNTS)
scalar _DirectiveExtensions @join__type(graph: ACCOUNTS) @join__type(graph: INVENTORY) @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS)
scalar _DirectiveExtensions @join__type(graph: ACCOUNTS)
scalar TransportOptions @join__type(graph: INVENTORY) @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS)
type Query @extraSchemaDefinitionDirective(
directives: {transport: [{subgraph: "accounts", kind: "rest", location: "http://localhost:<accounts_port>"}]}
) @extraSchemaDefinitionDirective(
directives: {transport: [{kind: "http", subgraph: "inventory", location: "http://localhost:<inventory_port>/graphql", options: {}}]}
) @extraSchemaDefinitionDirective(
directives: {transport: [{kind: "http", subgraph: "products", location: "http://localhost:<products_port>/graphql", options: {}}]}
) @extraSchemaDefinitionDirective(
directives: {transport: [{kind: "http", subgraph: "reviews", location: "http://localhost:<reviews_port>/graphql", options: {}}]}
) @join__type(graph: ACCOUNTS) @join__type(graph: INVENTORY) @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS) {
me: User @httpOperation(
subgraph: "accounts"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ schema
@link(
url: "https://the-guild.dev/graphql/mesh/spec/v1.0"
import: ["@transport", "@hoist", "@source", "@extraSchemaDefinitionDirective"]
import: ["@hoist", "@source"]
)
{
query: Query
Expand Down Expand Up @@ -84,29 +84,15 @@ enum join__Graph {
WEATHER @join__graph(name: "weather", url: "http://localhost:<weather_port>/graphql")
}
directive @transport(
kind: String!
subgraph: String!
location: String!
headers: [[String]]
options: Test_TransportOptions
) repeatable on SCHEMA
directive @hoist(subgraph: String, pathConfig: _HoistConfig) repeatable on FIELD_DEFINITION
directive @source(name: String!, type: String, subgraph: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
directive @extraSchemaDefinitionDirective(directives: _DirectiveExtensions) repeatable on OBJECT
scalar Test_TransportOptions @source(name: "TransportOptions", subgraph: "weather") @join__type(graph: WEATHER)
scalar _HoistConfig @join__type(graph: WEATHER)
scalar _DirectiveExtensions @join__type(graph: WEATHER)
type Query @source(name: "Query", subgraph: "weather") @extraSchemaDefinitionDirective(
directives: {transport: [{kind: "http", subgraph: "weather", location: "http://localhost:<weather_port>/graphql", options: {}}]}
) @join__type(graph: WEATHER) {
type Query @source(name: "Query", subgraph: "weather") @join__type(graph: WEATHER) {
here: Test_Weather @source(name: "here", type: "Weather", subgraph: "weather")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,27 +99,24 @@ directive @httpOperation(
) repeatable on FIELD_DEFINITION
directive @transport(
subgraph: String!
kind: String!
location: String!
subgraph: String
kind: String
location: String
headers: [[String]]
queryStringOptions: ObjMap
queryParams: [[String]]
options: TransportOptions
) repeatable on SCHEMA
directive @extraSchemaDefinitionDirective(directives: _DirectiveExtensions) repeatable on OBJECT
scalar ObjMap @join__type(graph: GREETINGS)
scalar _DirectiveExtensions @join__type(graph: GREETINGS) @join__type(graph: HELLOER)
scalar _DirectiveExtensions @join__type(graph: GREETINGS)
scalar TransportOptions @join__type(graph: HELLOER)
type Query @extraSchemaDefinitionDirective(
directives: {transport: [{subgraph: "greetings", kind: "rest", location: "http://localhost:<greetings_port>"}]}
) @extraSchemaDefinitionDirective(
directives: {transport: [{kind: "http", subgraph: "helloer", location: "http://localhost:<helloer_port>/graphql", options: {}}]}
) @join__type(graph: GREETINGS) @join__type(graph: HELLOER) {
greet(name: String!) : greet_200_response @httpOperation(
subgraph: "greetings"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should compose the appropriate schema 1`] = `
"schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) @link(url: "https://the-guild.dev/graphql/mesh/spec/v1.0", import: ["@transport", "@merge", "@extraSchemaDefinitionDirective", "@source"]) {
"schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) @link(url: "https://the-guild.dev/graphql/mesh/spec/v1.0", import: ["@merge", "@source"]) {
query: Query
}
Expand All @@ -19,12 +19,8 @@ directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on
directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
directive @transport(kind: String!, subgraph: String!, location: String!, headers: [[String]], options: TransportOptions) repeatable on SCHEMA
directive @merge(subgraph: String, argsExpr: String, keyArg: String, keyField: String, key: [String!], additionalArgs: String) repeatable on FIELD_DEFINITION
directive @extraSchemaDefinitionDirective(directives: _DirectiveExtensions) repeatable on OBJECT
directive @source(name: String!, type: String, subgraph: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
directive @additionalField on FIELD_DEFINITION
Expand All @@ -51,9 +47,7 @@ enum join__Graph {
scalar TransportOptions @join__type(graph: AUTHORS) @join__type(graph: BOOKS)
scalar _DirectiveExtensions @join__type(graph: AUTHORS) @join__type(graph: BOOKS)
type Query @extraSchemaDefinitionDirective(directives: {transport: [{kind: "http", subgraph: "authors", location: "http://localhost:<authors_port>/graphql", options: {}}]}) @extraSchemaDefinitionDirective(directives: {transport: [{kind: "http", subgraph: "books", location: "http://localhost:<books_port>/graphql", options: {}}]}) @join__type(graph: AUTHORS) @join__type(graph: BOOKS) {
type Query @join__type(graph: AUTHORS) @join__type(graph: BOOKS) {
author(id: ID!): Author @merge(subgraph: "authors", keyField: "id", keyArg: "id") @merge(subgraph: "books", keyField: "id", keyArg: "id") @source(name: "authorWithBooks", type: "AuthorWithBooks", subgraph: "books")
authors(ids: [ID]): [Author] @merge(subgraph: "authors", keyField: "id", keyArg: "ids") @join__field(graph: AUTHORS)
book(id: ID!): Book @merge(subgraph: "books", keyField: "id", keyArg: "id") @join__field(graph: BOOKS)
Expand Down
1 change: 1 addition & 0 deletions packages/compose-cli/src/getComposedSchemaFromConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export async function getComposedSchemaFromConfig(config: MeshComposeCLIConfig,
if (config.subgraph) {
const annotatedSubgraphs = getAnnotatedSubgraphs(subgraphConfigsForComposition, {
ignoreSemanticConventions: config.ignoreSemanticConventions,
alwaysAddTransportDirective: true,
});
const subgraph = annotatedSubgraphs.find(sg => sg.name === config.subgraph);
if (!subgraph) {
Expand Down
44 changes: 40 additions & 4 deletions packages/fusion/composition/src/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ export function getUnifiedGraphGracefully(subgraphs: SubgraphConfig[]) {
return result.supergraphSdl;
}

function isEmptyObject(obj: any) {
if (!obj) {
return true;
}
for (const key in obj) {
if (obj[key] != null) {
return false;
}
}
return true;
}

export function getAnnotatedSubgraphs(
subgraphs: SubgraphConfig[],
options: GetAnnotatedSubgraphsOptions = {},
Expand All @@ -74,13 +86,27 @@ export function getAnnotatedSubgraphs(
let url: string = subgraphConfig.url;
const subgraphSchemaExtensions = getDirectiveExtensions(schema);
const transportDirectives = subgraphSchemaExtensions?.transport;
if (transportDirectives?.length) {
url = transportDirectives[0].location;
const transportDirective = transportDirectives?.[0];
let removeTransportDirective = false;
if (transportDirective) {
url = transportDirective.location;
if (
!options.alwaysAddTransportDirective &&
transportDirective.kind === 'http' &&
!transportDirective.headers &&
isEmptyObject(transportDirective.options)
) {
removeTransportDirective = true;
}
}

let mergeDirectiveUsed = false;
const sourceDirectiveUsed = transforms?.length > 0;
const annotatedSubgraph = mapSchema(normalizeDirectiveExtensions(schema), {
const normalizedSchema = normalizeDirectiveExtensions(schema);
if (removeTransportDirective && (normalizedSchema.extensions?.directives as any)?.transport) {
delete (normalizedSchema.extensions?.directives as any).transport;
}
const annotatedSubgraph = mapSchema(normalizedSchema, {
[MapperKind.TYPE]: type => {
if (!sourceDirectiveUsed || isSpecifiedScalarType(type)) {
return type;
Expand Down Expand Up @@ -286,6 +312,11 @@ export function getAnnotatedSubgraphs(
astNode: undefined,
};
},
[MapperKind.DIRECTIVE]: directive => {
if (directive.name === 'transport' && removeTransportDirective) {
return null;
}
},
});
let transformedSubgraph = annotatedSubgraph;
if (transforms?.length) {
Expand Down Expand Up @@ -424,7 +455,10 @@ export function getAnnotatedSubgraphs(
if (schemaDirectiveExtensions) {
const schemaDirectiveExtensionsEntries = Object.entries(schemaDirectiveExtensions);
const schemaDirectiveExtraEntries = schemaDirectiveExtensionsEntries.filter(
([dirName]) => dirName !== 'link' && dirName !== 'composeDirective',
([dirName]) =>
dirName !== 'link' &&
dirName !== 'composeDirective' &&
(removeTransportDirective ? dirName !== 'transport' : true),
);
if (schemaDirectiveExtraEntries.length) {
transformedSubgraph = new GraphQLSchema({
Expand Down Expand Up @@ -518,6 +552,8 @@ export interface GetAnnotatedSubgraphsOptions {
* @default false
*/
ignoreSemanticConventions?: boolean;

alwaysAddTransportDirective?: boolean;
}

export type ComposeSubgraphsOptions = GetAnnotatedSubgraphsOptions;
Expand Down
Loading

0 comments on commit 489b7c7

Please sign in to comment.