You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: relax @interfaceObject validation for Fed 1 subgraphs (#3392)
## Relax `@interfaceObject` validation for Fed 1 subgraphs
### What this PR does
Previously, any use of `@interfaceObject` in a Fed 2 subgraph would
cause an
`INTERFACE_OBJECT_USAGE_ERROR` if **any** Fed 1 subgraph was present in
the
composition — regardless of whether the types actually conflicted.
This was overly restrictive. The real problem is narrower:
`@interfaceObject`
on type `T` in a Fed 2 subgraph requires other subgraphs to be able to
resolve
`__typename` via an interface `@key` on `T`. Fed 1 subgraphs silently
drop
`@key` from interfaces during upgrade (the schema upgrader removes
them), so
they **cannot** fulfill that requirement for `T` — but they are
perfectly fine
for any other types.
This PR replaces the blanket check with a **per-type** cross-check:
- An error is only raised when a Fed 2 subgraph uses `@interfaceObject`
on
type `T` **and** a Fed 1 subgraph has `@key` on an interface also named
`T`.
- Fed 2 subgraphs using `@interfaceObject` on a type that has no
corresponding
interface `@key` in any Fed 1 subgraph compose successfully.
### Changes
**`internals-js/src/schemaUpgrader.ts`**
- `SchemaUpgrader`: added `interfaceKeyTypes: Set<string>` field to
track
interface types whose `@key` was removed during upgrade; the set is
returned
from `upgrade()` on success.
- `upgradeSubgraphsIfNecessary`: replaced
`subgraphsUsingInterfaceObject` with
two `SetMultiMap<string, string>` instances
(`fed2InterfaceObjectTypesToSubgraphs`
and `fed1InterfaceKeyTypesToSubgraphs`) that are cross-checked per type
name
after all subgraphs are processed.
**`internals-js/src/__tests__/schemaUpgrader.test.ts`**
- Updated the existing `@interfaceObject` rejection test with the new,
more
precise error message.
- Added a new test confirming that composition succeeds when the same
type name
does **not** have a `@key` on a Fed 1 interface.
---------
Co-authored-by: Sachin D. Shinde <sachin@apollographql.com>
Relax `@interfaceObject` validation for Fed 1 subgraphs
6
+
7
+
Previously, any use of `@interfaceObject` in a Fed 2 subgraph caused an `INTERFACE_OBJECT_USAGE_ERROR` if any Fed 1 subgraph was present in the composition, regardless of whether the types conflicted.
8
+
9
+
The check is now per-type: an error is only raised when a Fed 2 subgraph uses `@interfaceObject` on type `T`**and** a Fed 1 subgraph has `@key` on an interface also named `T`. `@key` on an interface in a Fed 1 subgraph does not mean it can fulfill the `__typename`-resolution requirement that `@interfaceObject` depends on — but they are otherwise compatible with `@interfaceObject` usage on unrelated types.
'The @interfaceObject directive can only be used if all subgraphs have federation 2 subgraph schema (schema with a `@link` to "https://specs.apollo.dev/federation" version 2.0 or newer): '+
277
-
'@interfaceObject is used in subgraph "s1" but subgraph "s2" is not a federation 2 subgraph schema.',
275
+
'The @interfaceObject directive is used on type "A" in subgraph "s1", which requires other subgraphs to resolve its type name via an interface @key. However, @key on an interface in a federation 1 subgraph does not mean it can fulfill the __typename-resolution requirement that @interfaceObject depends on. For subgraph "s2", either upgrade them to federation 2 subgraphs or remove @key from the type.',
276
+
]);
277
+
});
278
+
279
+
test('allow @interfaceObject in fed2 subgraph when no fed1 subgraph has @key on the same interface type',()=>{
280
+
// When a fed2 subgraph uses @interfaceObject on a type but no fed1 subgraph has @key on an interface
281
+
// of the same name, composition should succeed. The fed1 subgraph may define an interface type with
282
+
// the same name, but since it has no @interfaceObject-incompatible interface @key, no error is expected.
'The @interfaceObject directive is used on type "A" in subgraphs "s1" and "s2", which requires other subgraphs to resolve its type name via an interface @key. However, @key on an interface in a federation 1 subgraph does not mean it can fulfill the __typename-resolution requirement that @interfaceObject depends on. For subgraph "s3", either upgrade them to federation 2 subgraphs or remove @key from the type.',
495
+
]);
496
+
});
497
+
498
+
test('error message includes all fed1 subgraphs with @key on the same interface type',()=>{
499
+
// When multiple fed1 subgraphs all have @key on the same interface type, all their
500
+
// names must appear in the error message (the "For ..." part).
'The @interfaceObject directive is used on type "A" in subgraph "s1", which requires other subgraphs to resolve its type name via an interface @key. However, @key on an interface in a federation 1 subgraph does not mean it can fulfill the __typename-resolution requirement that @interfaceObject depends on. For subgraphs "s2" and "s3", either upgrade them to federation 2 subgraphs or remove @key from the type.',
// Note that we exit this method early if everything is a fed2 schema, so we know at least one of them wasn't.
275
-
errors=[ERRORS.INTERFACE_OBJECT_USAGE_ERROR.err(
276
-
'The @interfaceObject directive can only be used if all subgraphs have federation 2 subgraph schema (schema with a `@link` to "https://specs.apollo.dev/federation" version 2.0 or newer): '
277
-
+`@interfaceObject is used in ${printSubgraphNames(subgraphsUsingInterfaceObject)} but ${printSubgraphNames(fed1Subgraphs)}${fed1Subgraphs.length>1 ? 'are not' : 'is not a'} federation 2 subgraph schema.`,
`The @interfaceObject directive is used on type "${typeName}" in ${printSubgraphNames([...interfaceObjectSubgraphs])}, which requires other subgraphs to resolve its type name via an interface @key. However, @key on an interface in a federation 1 subgraph does not mean it can fulfill the __typename-resolution requirement that @interfaceObject depends on. For ${printSubgraphNames([...interfaceKeySubgraphs])}, either upgrade them to federation 2 subgraphs or remove @key from the type.`,
0 commit comments