Federation referenceBy broken since v9.2.0: representation parameter undefined
**Describe the bug**
The auto-generated `@ResolveReference()` method created by the `referenceBy` configuration option fails in Apollo Federation when using `@nestjs/graphql` v13+. The method receives `undefined` for the `representation` parameter, causing a crash when trying to access the key field.
This regression was introduced in v9.2.0 with the DataLoader implementation from PR #391 and #396.
**Have you read the [Contributing Guidelines](https://github.com/tripss/nestjs-query/blob/master/CONTRIBUTING.md)?**
Yes
**To Reproduce**
1. Create a NestJS project with Apollo Federation v2
2. Configure a basic entity with `referenceBy`:
```typescript
// user.entity.ts
import { Directive, Field, ID, ObjectType } from '@nestjs/graphql';
@ObjectType()
@Directive('@key(fields: "id")')
export class User {
@Field(() => ID)
id!: string;
@Field()
name!: string;
}
// user.module.ts
import { Module } from '@nestjs/common';
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
import { User } from './user.entity';
import { UserService } from './user.service';
const nestQueryModule = NestjsQueryGraphQLModule.forFeature({
imports: [NestjsQueryTypeOrmModule.forFeature([User])],
services: [UserService],
resolvers: [
{
DTOClass: User,
EntityClass: User,
ServiceClass: UserService,
referenceBy: { key: 'id' }, // This generates broken resolver
},
],
});
@Module({
imports: [nestQueryModule],
exports: [nestQueryModule],
})
export class UserModule {}
```
3. Make a federated `_entities` query
4. Observe crash: `Cannot read properties of undefined (reading 'id')`
**Expected behavior**
The auto-generated `@ResolveReference()` method should correctly receive the `representation` parameter and resolve the entity.
**Root Cause**
In v9.2.0, the auto-generated `resolveReference` method was enhanced with DataLoader support, adding `@Context()` and `@InjectDataLoaderConfig()` parameter decorators:
```typescript
async resolveReference(representation, @Context() context, @InjectDataLoaderConfig() dataLoaderConfig) {
const id = representation[key]; // Crashes: representation is undefined
// ...
}
```
However, `@nestjs/graphql`'s `@ResolveReference()` decorator has known incompatibilities with parameter decorators (see NestJS issues [#945](https://github.com/nestjs/graphql/issues/945), [#2127](https://github.com/nestjs/graphql/issues/2127), [#712](https://github.com/nestjs/graphql/issues/712)). When parameter decorators are present, the `representation` parameter becomes `undefined`.
**Test Coverage Gap**
https://github.com/TriPSs/nestjs-query/pull/396 added comprehensive tests for N+1 query prevention, but these tests only cover regular GraphQL queries (e.g., `todoLists { items { ... } }`). The tests do **not** exercise the Apollo Federation `_entities` query or the `@ResolveReference()` code path that the PR modified.
The PR's integration tests validate DataLoader usage in nested field resolvers (`@ResolveField()`), but never test the `referenceBy` auto-generated resolver or make any `_entities` queries. This is why the regression was not caught - the actual federation entity resolution was never tested.
**Reproducible Test Case**
Here's a minimal test that reproduces the issue:
```typescript
// federated-user.spec.ts
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { getApolloServer } from '@nestjs/apollo';
import { ApolloServer } from '@apollo/server';
import { TypedDocumentNode } from '@graphql-typed-document-node/core';
import { gql } from 'graphql-tag';
import { AppModule } from './app.module'; // Your app module
describe('Federated User', () => {
let app: INestApplication;
let server: ApolloServer;
const FederatedUserQuery: TypedDocumentNode<any, any> = gql`
query FederatedUser($_representations: [_Any!]!) {
_entities(representations: $_representations) {
... on User {
id
name
}
}
}
`;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleRef.createNestApplication();
await app.init();
server = getApolloServer(app);
// Create a test user in your database
// (implementation depends on your setup)
});
afterAll(async () => {
await app.close();
});
it('should resolve user via _entities query', async () => {
const response = await server.executeOperation({
query: FederatedUserQuery,
variables: {
_representations: [
{ __typename: 'User', id: 'test-user-id' }
],
},
});
// This will fail with: Cannot read properties of undefined (reading 'id')
expect(response.body.kind).toBe('single');
if (response.body.kind === 'single') {
expect(response.body.singleResult.errors).toBeUndefined();
expect(response.body.singleResult.data?._entities[0]).toMatchObject({
id: 'test-user-id',
name: expect.any(String),
});
}
});
});
```
**Desktop**
- `@ptc-org/nestjs-query-core`: 9.2.1
- `@ptc-org/nestjs-query-graphql`: 9.2.1
- `@ptc-org/nestjs-query-typeorm`: 9.2.1
- `@nestjs/graphql`: 13.2.0
- `@nestjs/apollo`: 13.2.1
- `@apollo/subgraph`: 2.12.1
- `@nestjs/core`: 11.1.9
- Node: v24.5.0
**Additional context**
This worked correctly in v9.1.0 before the DataLoader changes. The issue affects all federated entities using `referenceBy` with `@nestjs/graphql` v13+.
This was generated by Claude Code
2 条评论