diff --git a/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.graphql b/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.graphql index e471ca4b4b..6df2b31624 100644 --- a/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.graphql +++ b/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.graphql @@ -1,14 +1,23 @@ schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.5", for: EXECUTION) - @link(url: "https://specs.apollo.dev/tag/v0.3") - @link(url: "https://specs.apollo.dev/inaccessible/v0.2", for: SECURITY) + @link(url: "https://specs.apollo.dev/tag/v0.3", import: ["@tag"]) + @link(url: "https://specs.apollo.dev/inaccessible/v0.2", import: ["@inaccessible"], for: SECURITY) + @link(url: "https://specs.apollo.dev/authenticated/v0.1", import: ["@authenticated"], for: SECURITY) + @link(url: "https://specs.apollo.dev/requiresScopes/v0.1", import: ["@requiresScopes"], for: SECURITY) + @link(url: "https://specs.apollo.dev/policy/v0.1", import: ["@policy"], for: SECURITY) + @link(url: "http://specs.example.org/custom/v0.1", import: ["@custom"]) + @link(url: "https://specs.apollo.dev/connect/v0.1", for: EXECUTION) @join__directive(graphs: [ONE], name: "link", args: {url: "https://specs.apollo.dev/connect/v0.1", import: ["@connect", "@source"]}) @join__directive(graphs: [ONE], name: "source", args: {name: "json", http: {baseURL: "http://example/"}}) { query: Query } +directive @authenticated on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM + +directive @custom on OBJECT | FIELD_DEFINITION + directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION directive @join__directive(graphs: [join__Graph!], name: String!, args: join__DirectiveArguments) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION @@ -27,6 +36,10 @@ 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 @policy(policies: [[policy__Policy!]!]!) on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM + +directive @requiresScopes(scopes: [[requiresScopes__Scope!]!]!) on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM + directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA input join__ContextArgument { @@ -61,12 +74,14 @@ enum link__Purpose { EXECUTION } +scalar policy__Policy + type Query @join__type(graph: ONE) @join__type(graph: TWO) { - ts: [T] @join__field(graph: ONE) @join__directive(graphs: [ONE], name: "connect", args: {source: "json", http: {GET: "/t"}, selection: "id\ntagged\nhidden\n# custom\n# authenticated\n# requiresScopes\n# policy\noverridden"}) - t(id: ID): T @join__field(graph: ONE) @join__directive(graphs: [ONE], name: "connect", args: {source: "json", http: {GET: "/t/{$args.id}"}, selection: "id\ntagged\nhidden\n# custom\n# authenticated\n# requiresScopes\n# policy\noverridden", entity: true}) + ts: [T] @join__field(graph: ONE) @join__directive(graphs: [ONE], name: "connect", args: {source: "json", http: {GET: "/t"}, selection: "id\ntagged\nhidden\ncustom\nauthenticated\nrequiresScopes\npolicy\noverridden"}) + t(id: ID): T @join__field(graph: ONE) @join__directive(graphs: [ONE], name: "connect", args: {source: "json", http: {GET: "/t/{$args.id}"}, selection: "id\ntagged\nhidden\ncustom\nauthenticated\nrequiresScopes\npolicy\noverridden", entity: true}) } type R @@ -75,6 +90,8 @@ type R id: ID! } +scalar requiresScopes__Scope + type T @join__type(graph: ONE, key: "id") @join__type(graph: TWO, key: "id") @@ -82,6 +99,10 @@ type T id: ID! tagged: String @join__field(graph: ONE) @tag(name: "tag") hidden: String @inaccessible @join__field(graph: ONE) + custom: String @join__field(graph: ONE) @custom + authenticated: String @join__field(graph: ONE) @authenticated + requiresScopes: String @join__field(graph: ONE) @requiresScopes(scopes: ["scope"]) + policy: String @join__field(graph: ONE) @policy(policies: [["admin"]]) overridden: String @join__field(graph: ONE, override: "two", overrideLabel: "label") @join__field(graph: TWO, overrideLabel: "label") r: R @join__field(graph: ONE) @join__directive(graphs: [ONE], name: "connect", args: {source: "json", http: {GET: "/t/{$this.id}/r"}, selection: "id"}) } diff --git a/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.yaml b/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.yaml index 64b43f2c21..1285641eea 100644 --- a/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.yaml +++ b/apollo-federation/src/sources/connect/expand/tests/schemas/carryover.yaml @@ -1,5 +1,5 @@ # rover supergraph compose --config apollo-federation/src/sources/connect/expand/tests/schemas/carryover.yaml > apollo-federation/src/sources/connect/expand/tests/schemas/carryover.graphql -federation_version: =2.9.0-connectors.9 +federation_version: =2.10.0-alpha.0 subgraphs: one: routing_url: none @@ -15,9 +15,9 @@ subgraphs: ) @link(url: "http://specs.example.org/custom/v0.1", import: ["@custom"]) @link(url: "https://specs.apollo.dev/connect/v0.1", import: ["@connect", "@source"]) - # @composeDirective(name: "@custom") + @composeDirective(name: "@custom") @source(name: "json" http: { baseURL: "http://example/" }) - # directive @custom on OBJECT | FIELD_DEFINITION + directive @custom on OBJECT | FIELD_DEFINITION type Query { ts: [T] @connect( source: "json" @@ -26,10 +26,10 @@ subgraphs: id tagged hidden - # custom - # authenticated - # requiresScopes - # policy + custom + authenticated + requiresScopes + policy overridden """ ) @@ -40,10 +40,10 @@ subgraphs: id tagged hidden - # custom - # authenticated - # requiresScopes - # policy + custom + authenticated + requiresScopes + policy overridden """ entity: true @@ -54,10 +54,10 @@ subgraphs: id: ID! tagged: String @tag(name: "tag") hidden: String @inaccessible - # custom: String @custom - # authenticated: String @authenticated - # requiresScopes: String @requiresScopes(scopes: ["scope"]) - # policy: String @policy(policies: [["admin"]]) + custom: String @custom + authenticated: String @authenticated + requiresScopes: String @requiresScopes(scopes: ["scope"]) + policy: String @policy(policies: [["admin"]]) overridden: String @override(from: "two", label: "label") r: R @connect( source: "json" diff --git a/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.graphql b/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.graphql index 7a01562f91..bbb5bc6cf3 100644 --- a/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.graphql +++ b/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.graphql @@ -1,17 +1,19 @@ schema @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.4", for: EXECUTION) + @link(url: "https://specs.apollo.dev/join/v0.5", for: EXECUTION) + @link(url: "https://specs.apollo.dev/connect/v0.1", for: EXECUTION) @join__directive(graphs: [CONNECTORS], name: "link", args: {url: "https://specs.apollo.dev/connect/v0.1", import: ["@connect", "@source"]}) @join__directive(graphs: [CONNECTORS], name: "source", args: {name: "example", http: {baseURL: "http://example"}}) { query: Query + mutation: Mutation } directive @join__directive(graphs: [join__Graph!], name: String!, args: join__DirectiveArguments) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE -directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean, overrideLabel: String) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION +directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean, overrideLabel: String, contextArguments: [join__ContextArgument!]) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION directive @join__graph(name: String!, url: String!) on ENUM_VALUE @@ -40,6 +42,23 @@ type AddressGeo lng: Float } +input AddressGeoInput + @join__type(graph: CONNECTORS) +{ + lat: Float + lng: Float +} + +input AddressInput + @join__type(graph: CONNECTORS) +{ + street: String + suite: String + city: String + zipcode: String + geo: AddressGeoInput +} + type CompanyInfo @join__type(graph: CONNECTORS) { @@ -56,13 +75,32 @@ input CompanyInput catchPhrase: String } +input CreateUserInput + @join__type(graph: CONNECTORS) +{ + name: String! + username: String! + email: EmailAddress + status: Status + address: AddressInput +} + scalar EmailAddress @join__type(graph: CONNECTORS) +input join__ContextArgument { + name: String! + type: String! + context: String! + selection: join__FieldValue! +} + scalar join__DirectiveArguments scalar join__FieldSet +scalar join__FieldValue + enum join__Graph { CONNECTORS @join__graph(name: "connectors", url: "none") } @@ -81,6 +119,12 @@ enum link__Purpose { EXECUTION } +type Mutation + @join__type(graph: CONNECTORS) +{ + createUser(input: CreateUserInput!): User @join__directive(graphs: [CONNECTORS], name: "connect", args: {source: "example", http: {POST: "/create/user", body: "$args.input { name username email status address { street suite city zipcode geo { lat lng } } }"}, selection: "id"}) +} + type Query @join__type(graph: CONNECTORS) { @@ -89,6 +133,13 @@ type Query user(id: ID!): User @join__directive(graphs: [CONNECTORS], name: "connect", args: {source: "example", http: {GET: "/{$args.id}"}, selection: "id\nname\nusername\nemail\naddress {\n street\n suite\n city\n zipcode\n geo {\n lat\n lng\n }\n}\nphone\nwebsite\ncompany {\n name\n catchPhrase\n bs\n email\n}", entity: true}) } +enum Status + @join__type(graph: CONNECTORS) +{ + ACTIVE @join__enumValue(graph: CONNECTORS) + INACTIVE @join__enumValue(graph: CONNECTORS) +} + type User @join__type(graph: CONNECTORS, key: "id") { @@ -100,4 +151,5 @@ type User phone: String website: String company: CompanyInfo + status: Status } diff --git a/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.yaml b/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.yaml index 78465f7274..10df54538e 100644 --- a/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.yaml +++ b/apollo-federation/src/sources/connect/expand/tests/schemas/realistic.yaml @@ -1,4 +1,6 @@ -federation_version: =2.9.0-connectors.0 +# rover supergraph compose --config apollo-federation/src/sources/connect/expand/tests/schemas/realistic.yaml > apollo-federation/src/sources/connect/expand/tests/schemas/realistic.graphql +# this is currently manually edited to add Status enum and EmailAddress scalars to the input type +federation_version: =2.10.0-alpha.0 subgraphs: connectors: routing_url: none @@ -6,7 +8,7 @@ subgraphs: sdl: | extend schema @link( - url: "https://specs.apollo.dev/federation/v2.7" + url: "https://specs.apollo.dev/federation/v2.10" import: ["@key"] ) @link(url: "https://specs.apollo.dev/connect/v0.1", import: ["@connect", "@source"]) @@ -64,6 +66,7 @@ subgraphs: phone: String website: String company: CompanyInfo + status: String # Status } type Address { @@ -83,7 +86,7 @@ subgraphs: name: String catchPhrase: String bs: String - email: EmailAddress + email: String # EmailAddress } input CompanyInput { @@ -92,3 +95,34 @@ subgraphs: } scalar EmailAddress + + enum Status { + ACTIVE + INACTIVE + } + + type Mutation { + createUser(input: CreateUserInput!): User + @connect(source: "example", http: { POST: "/create/user", body: "$$args.input { name username email status address { street suite city zipcode geo { lat lng } } }" }, selection: "id") + } + + input CreateUserInput { + name: String! + username: String! + email: String # EmailAddress! + status: String # Status! + address: AddressInput + } + + input AddressInput { + street: String + suite: String + city: String + zipcode: String + geo: AddressGeoInput + } + + input AddressGeoInput { + lat: Float + lng: Float + } diff --git a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-2.snap b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-2.snap index b0cea9af72..0a74040dc0 100644 --- a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-2.snap +++ b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-2.snap @@ -69,6 +69,26 @@ expression: connectors.by_service_name "hidden", None, ), + Field( + None, + "custom", + None, + ), + Field( + None, + "authenticated", + None, + ), + Field( + None, + "requiresScopes", + None, + ), + Field( + None, + "policy", + None, + ), Field( None, "overridden", @@ -159,6 +179,26 @@ expression: connectors.by_service_name "hidden", None, ), + Field( + None, + "custom", + None, + ), + Field( + None, + "authenticated", + None, + ), + Field( + None, + "requiresScopes", + None, + ), + Field( + None, + "policy", + None, + ), Field( None, "overridden", diff --git a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-3.snap b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-3.snap index 49ef0ab954..2d5f9c54e2 100644 --- a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-3.snap +++ b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph-3.snap @@ -2,7 +2,7 @@ source: apollo-federation/src/sources/connect/expand/tests/mod.rs expression: raw_sdl --- -schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) @link(url: "https://specs.apollo.dev/inaccessible/v0.2", for: SECURITY) @join__directive(graphs: [], name: "link", args: {url: "https://specs.apollo.dev/connect/v0.1"}) @link(url: "https://specs.apollo.dev/tag/v0.3") { +schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) @link(url: "https://specs.apollo.dev/inaccessible/v0.2", for: SECURITY) @join__directive(graphs: [], name: "link", args: {url: "https://specs.apollo.dev/connect/v0.1"}) @link(url: "https://specs.apollo.dev/tag/v0.3", import: ["@tag"]) @link(url: "https://specs.apollo.dev/authenticated/v0.1", for: SECURITY, import: ["@authenticated"]) @link(url: "https://specs.apollo.dev/requiresScopes/v0.1", for: SECURITY, import: ["@requiresScopes"]) @link(url: "https://specs.apollo.dev/policy/v0.1", for: SECURITY, import: ["@policy"]) @link(url: "http://specs.example.org/custom/v0.1", import: ["@custom"]) { query: Query } @@ -26,6 +26,14 @@ directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUM directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA +directive @authenticated on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM + +directive @requiresScopes(scopes: [[requiresScopes__Scope!]!]!) on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM + +directive @policy(policies: [[policy__Policy!]!]!) on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM + +directive @custom on OBJECT | FIELD_DEFINITION + enum link__Purpose { """ SECURITY features provide metadata necessary to securely resolve fields. @@ -49,9 +57,13 @@ enum join__Graph { } type T @join__type(graph: ONE_QUERY_T_0, key: "id") @join__type(graph: ONE_QUERY_TS_0) @join__type(graph: ONE_T_R_0, key: "id") @join__type(graph: TWO, key: "id") { + authenticated: String @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @authenticated + custom: String @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @custom hidden: String @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @inaccessible id: ID! @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @join__field(graph: ONE_T_R_0) @join__field(graph: TWO) overridden: String @join__field(graph: ONE_QUERY_T_0, override: "two", overrideLabel: "label") @join__field(graph: ONE_QUERY_TS_0, override: "two", overrideLabel: "label") @join__field(graph: TWO) + policy: String @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @policy(policies: [["admin"]]) + requiresScopes: String @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @requiresScopes(scopes: ["scope"]) tagged: String @join__field(graph: ONE_QUERY_T_0) @join__field(graph: ONE_QUERY_TS_0) @tag(name: "tag") r: R @join__field(graph: ONE_T_R_0) } @@ -65,3 +77,7 @@ type Query @join__type(graph: ONE_QUERY_T_0) @join__type(graph: ONE_QUERY_TS_0) type R @join__type(graph: ONE_T_R_0) { id: ID! @join__field(graph: ONE_T_R_0) } + +scalar requiresScopes__Scope + +scalar policy__Policy diff --git a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph.snap b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph.snap index a9923d3a1b..ef2d442ead 100644 --- a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph.snap +++ b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__carryover__it_expands_supergraph.snap @@ -16,6 +16,10 @@ type R { type T { id: ID! tagged: String + custom: String + authenticated: String + requiresScopes: String + policy: String overridden: String r: R } diff --git a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-2.snap b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-2.snap index 1323df702d..7c7c332ec5 100644 --- a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-2.snap +++ b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-2.snap @@ -3,6 +3,167 @@ source: apollo-federation/src/sources/connect/expand/tests/mod.rs expression: connectors.by_service_name --- { + "connectors_Mutation_createUser_0": Connector { + id: ConnectId { + label: "connectors.example http: POST /create/user", + subgraph_name: "connectors", + source_name: Some( + "example", + ), + directive: ObjectOrInterfaceFieldDirectivePosition { + field: Object(Mutation.createUser), + directive_name: "connect", + directive_index: 0, + }, + }, + transport: HttpJsonTransport { + source_url: Some( + Url { + scheme: "http", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "example", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + ), + connect_template: URLTemplate { + base: None, + path: [ + ParameterValue { + parts: [ + Text( + "create", + ), + ], + }, + ParameterValue { + parts: [ + Text( + "user", + ), + ], + }, + ], + query: {}, + }, + method: Post, + headers: {}, + body: Some( + Path( + Var( + "$args", + Key( + Field( + "input", + ), + Selection( + SubSelection { + selections: [ + Field( + None, + "name", + None, + ), + Field( + None, + "username", + None, + ), + Field( + None, + "email", + None, + ), + Field( + None, + "status", + None, + ), + Field( + None, + "address", + Some( + SubSelection { + selections: [ + Field( + None, + "street", + None, + ), + Field( + None, + "suite", + None, + ), + Field( + None, + "city", + None, + ), + Field( + None, + "zipcode", + None, + ), + Field( + None, + "geo", + Some( + SubSelection { + selections: [ + Field( + None, + "lat", + None, + ), + Field( + None, + "lng", + None, + ), + ], + star: None, + }, + ), + ), + ], + star: None, + }, + ), + ), + ], + star: None, + }, + ), + ), + ), + ), + ), + }, + selection: Named( + SubSelection { + selections: [ + Field( + None, + "id", + None, + ), + ], + star: None, + }, + ), + config: None, + max_requests: None, + entity_resolver: None, + }, "connectors_Query_filterUsersByEmailDomain_0": Connector { id: ConnectId { label: "connectors.example http: GET /filter/users", diff --git a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-3.snap b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-3.snap index d6bb4ee3cb..4ea7e9ac0c 100644 --- a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-3.snap +++ b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph-3.snap @@ -2,7 +2,7 @@ source: apollo-federation/src/sources/connect/expand/tests/mod.rs expression: raw_sdl --- -schema @link(url: "https://specs.apollo.dev/link/v1.0") @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) @join__directive(graphs: [], name: "link", args: {url: "https://specs.apollo.dev/connect/v0.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://specs.apollo.dev/inaccessible/v0.2", for: SECURITY) @join__directive(graphs: [], name: "link", args: {url: "https://specs.apollo.dev/connect/v0.1"}) { query: Query } @@ -22,6 +22,8 @@ directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE directive @join__directive(graphs: [join__Graph!], name: String!, args: join__DirectiveArguments!) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION +directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + enum link__Purpose { """ SECURITY features provide metadata necessary to securely resolve fields. @@ -38,15 +40,42 @@ scalar join__FieldSet scalar join__DirectiveArguments enum join__Graph { + CONNECTORS_MUTATION_CREATEUSER_0 @join__graph(name: "connectors_Mutation_createUser_0", url: "none") CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0 @join__graph(name: "connectors_Query_filterUsersByEmailDomain_0", url: "none") CONNECTORS_QUERY_USER_0 @join__graph(name: "connectors_Query_user_0", url: "none") CONNECTORS_QUERY_USERSBYCOMPANY_0 @join__graph(name: "connectors_Query_usersByCompany_0", url: "none") } -scalar EmailAddress @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__type(graph: CONNECTORS_QUERY_USER_0) +scalar EmailAddress @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__type(graph: CONNECTORS_QUERY_USER_0) + +enum Status @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) { + ACTIVE @join__enumValue(graph: CONNECTORS_MUTATION_CREATEUSER_0) + INACTIVE @join__enumValue(graph: CONNECTORS_MUTATION_CREATEUSER_0) +} + +input AddressGeoInput @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) { + lat: Float + lng: Float +} + +input AddressInput @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) { + street: String + suite: String + city: String + zipcode: String + geo: AddressGeoInput +} + +input CreateUserInput @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) { + name: String! + username: String! + email: EmailAddress + status: Status + address: AddressInput +} -type User @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__type(graph: CONNECTORS_QUERY_USER_0, key: "id") @join__type(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) { - id: ID! @join__field(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__field(graph: CONNECTORS_QUERY_USER_0) @join__field(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) +type User @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__type(graph: CONNECTORS_QUERY_USER_0, key: "id") @join__type(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) { + id: ID! @join__field(graph: CONNECTORS_MUTATION_CREATEUSER_0) @join__field(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__field(graph: CONNECTORS_QUERY_USER_0) @join__field(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) name: String @join__field(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__field(graph: CONNECTORS_QUERY_USER_0) @join__field(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) address: Address @join__field(graph: CONNECTORS_QUERY_USER_0) company: CompanyInfo @join__field(graph: CONNECTORS_QUERY_USER_0) @join__field(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) @@ -56,7 +85,12 @@ type User @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join_ website: String @join__field(graph: CONNECTORS_QUERY_USER_0) } -type Query @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__type(graph: CONNECTORS_QUERY_USER_0) @join__type(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) { +type Mutation @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) { + createUser(input: CreateUserInput!): User @join__field(graph: CONNECTORS_MUTATION_CREATEUSER_0) +} + +type Query @join__type(graph: CONNECTORS_MUTATION_CREATEUSER_0) @join__type(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) @join__type(graph: CONNECTORS_QUERY_USER_0) @join__type(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) { + _: ID @inaccessible @join__field(graph: CONNECTORS_MUTATION_CREATEUSER_0) filterUsersByEmailDomain(email: EmailAddress!): [User] @join__field(graph: CONNECTORS_QUERY_FILTERUSERSBYEMAILDOMAIN_0) user(id: ID!): User @join__field(graph: CONNECTORS_QUERY_USER_0) usersByCompany(company: CompanyInput!): [User] @join__field(graph: CONNECTORS_QUERY_USERSBYCOMPANY_0) diff --git a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph.snap b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph.snap index 9908defa24..6220c818a9 100644 --- a/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph.snap +++ b/apollo-federation/src/sources/connect/expand/tests/snapshots/apollo_federation__sources__connect__expand__tests__realistic__it_expands_supergraph.snap @@ -17,6 +17,19 @@ type AddressGeo { lng: Float } +input AddressGeoInput { + lat: Float + lng: Float +} + +input AddressInput { + street: String + suite: String + city: String + zipcode: String + geo: AddressGeoInput +} + type CompanyInfo { name: String catchPhrase: String @@ -29,14 +42,31 @@ input CompanyInput { catchPhrase: String } +input CreateUserInput { + name: String! + username: String! + email: EmailAddress + status: Status + address: AddressInput +} + scalar EmailAddress +type Mutation { + createUser(input: CreateUserInput!): User +} + type Query { filterUsersByEmailDomain(email: EmailAddress!): [User] usersByCompany(company: CompanyInput!): [User] user(id: ID!): User } +enum Status { + ACTIVE + INACTIVE +} + type User { id: ID! name: String @@ -46,4 +76,5 @@ type User { phone: String website: String company: CompanyInfo + status: Status } diff --git a/apollo-federation/src/sources/connect/expand/visitors/input.rs b/apollo-federation/src/sources/connect/expand/visitors/input.rs index 9dc7aecae4..80eb9937d2 100644 --- a/apollo-federation/src/sources/connect/expand/visitors/input.rs +++ b/apollo-federation/src/sources/connect/expand/visitors/input.rs @@ -39,6 +39,30 @@ impl FieldVisitor ty: field_def.ty.clone(), directives: filter_directives(self.directive_deny_list, &field_def.directives), }; + + let input_type = self + .original_schema + .get_type(field_def.ty.inner_named_type().clone())?; + match input_type { + TypeDefinitionPosition::Scalar(pos) => { + try_pre_insert!(self.to_schema, pos)?; + try_insert!( + self.to_schema, + pos, + pos.get(self.original_schema.schema())?.clone() + )?; + } + TypeDefinitionPosition::Enum(pos) => { + try_pre_insert!(self.to_schema, pos)?; + try_insert!( + self.to_schema, + pos, + pos.get(self.original_schema.schema())?.clone() + )?; + } + _ => {} + } + if let Some(old_field) = r#type.fields.get(&field.field_name) { if *old_field.deref().deref() != new_field { return Err(FederationError::internal(