apollographql / apollographql/federation

Federation throws Unused Externals error when using nested keys (EXTERNAL_UNUSED)

Open
#331 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
725
Forks
276
Avg merge
1h 47m
Merged PRs (30d)
1

Description

Using @apollo/federation @0.13.2 and earlier, I've noticed odd behavior when using nested keys.
According to how I'm reading the specs, this should work:

```
const serviceA = {
typeDefs: gql`
type Product @key(fields: "id { nestedA { nestedB } }") {
sku: String!
upc: String!
id: NestedA
}

type NestedA {
nestedA: NestedB
}

type NestedB {
nestedB: String
}

type Query {
some: Product
}
`,
name: 'serviceA',
}

const serviceB = {
typeDefs: gql`
extend type Product @key(fields: "id { nestedA { nestedB } }") {
id: NestedA @external
}

extend type NestedA {
nestedA: NestedB @external
}

extend type NestedB {
nestedB: String @external
}
`,
name: 'serviceB',
}

const serviceList = [serviceA, serviceB]
const { schema: someSchema, errors } = composeAndValidate(serviceList)
console.log('Errors: ', errors)
```

However, I'm getting an EXTERNAL_UNUSED error here:
`"is marked as @external but is not used by a @requires, @key, or @provides directive."`

Looking through the postComposition validator for this, I noticed that the @requires directive does this recursively, while the @key directive doesn't. So I tried it the following way (Note the `noop` with `@requires`):

```
const serviceA = {
typeDefs: gql`
type Product @key(fields: "id { nestedA { nestedB } }") {
sku: String!
upc: String!
id: NestedA
}

type NestedA {
nestedA: NestedB
}

type NestedB {
nestedB: String
}

type Query {
some: Product
}
`,
name: 'serviceA',
}

const serviceB = {
typeDefs: gql`
extend type Product {
id: NestedA @external
noop: String @requires(fields: "id { nestedA { nestedB } }")
}

extend type NestedA {
nestedA: NestedB @external
}

extend type NestedB {
nestedB: String @external
}
`,
name: 'serviceB',
}

const serviceList = [serviceA, serviceB]
const { schema: someSchema, errors } = composeAndValidate(serviceList)
console.log('Errors: ', errors)
```

Which works, but now we have `noop` all over the place.

I'm not all too familiar with the federation code base, but I can take a stab at fixing this, if this isn't intended behavior.

Let me know!

Contributor guide

Open the contributing guide

Research direction

Start with the postComposition validator mentioned in the report and reproduce the issue through composeAndValidate using the provided serviceList schemas. Compare the recursive @requires handling with the @key handling for nested fields, then verify that valid nested keys no longer produce EXTERNAL_UNUSED without requiring a noop field.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.