Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/plugins/response-cache/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ export type UseResponseCacheParameter<PluginContext extends Record<string, any>
* Defaults to `["id"]`
*/
idFields?: Array<string>;
/**
* List of SchemaCoordinates in format {ObjectType}.{FieldName} which are ignored during scan for entities.
* Defaults to `[]`
*/
ignoreIdFieldsBySchemaCoordinate?: Array<string>;
/**
* Whether the mutation execution result should be used for invalidating resources.
* Defaults to `true`
Expand Down Expand Up @@ -294,6 +299,7 @@ export function useResponseCache<PluginContext extends Record<string, any> = {}>
ttlPerSchemaCoordinate = {},
scopePerSchemaCoordinate = {},
idFields = ['id'],
ignoreIdFieldsBySchemaCoordinate = [],
invalidateViaMutation = true,
buildResponseCacheKey = defaultBuildResponseCacheKey,
getDocumentString = defaultGetDocumentString,
Expand Down Expand Up @@ -361,7 +367,11 @@ export function useResponseCache<PluginContext extends Record<string, any> = {}>
const resultTypeNames = unwrapTypenames(fieldConfig.type);
typePerSchemaCoordinateMap.set(schemaCoordinates, resultTypeNames);

if (idFields.includes(fieldName) && !idFieldByTypeName.has(typeName)) {
if (
idFields.includes(fieldName) &&
!idFieldByTypeName.has(typeName) &&
!ignoreIdFieldsBySchemaCoordinate?.includes(schemaCoordinates)
) {
idFieldByTypeName.set(typeName, fieldName);
}

Expand Down
126 changes: 126 additions & 0 deletions packages/plugins/response-cache/test/response-cache.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4031,3 +4031,129 @@ it('calls enabled fn after context building', async () => {
},
});
});

it('id field in body is returned as is and not overwritten', async () => {
expect.assertions(1);
const queryResult = {
id: 'idString',
header: { id: { fieldA: 'Tick', fieldB: 'Trick', fieldC: 'Track' }, someField: 'someData' },
};
const schema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
type Query {
subgraphObject: SubgraphObject
}
type SubgraphObject {
id: String
header: Header
}
type Header {
id: IdObject
someField: String
}
type IdObject {
fieldA: String
fieldB: String
fieldC: String
}
`,
resolvers: { Query: { subgraphObject: () => queryResult } },
});
const testkit = createTestkit(
[
useEngine({ ...GraphQLJS, execute: normalizedExecutor, subscribe: normalizedExecutor }),
useResponseCache({
session: () => null,
ttl: 0,
ignoreIdFieldsBySchemaCoordinate: ['Header.id'],
}),
],
schema,
);

const document = /* GraphQL */ `
query {
subgraphObject {
id
header {
id {
fieldA
fieldB
fieldC
}
someField
}
}
}
`;

const result = await testkit.execute(document);
assertSingleExecutionValue(result);
expect(result).toMatchObject({
data: {
subgraphObject: queryResult,
},
});
});

it('id field in body overwritten and request fails', async () => {
expect.assertions(1);
const queryResult = {
id: 'idString',
header: { id: { fieldA: 'Tick', fieldB: 'Trick', fieldC: 'Track' }, someField: 'someData' },
};
const schema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
type Query {
subgraphObject: SubgraphObject
}
type SubgraphObject {
id: String
header: Header!
}
type Header {
id: IdObject!
someField: String
}
type IdObject {
fieldA: String!
fieldB: String!
fieldC: String!
}
`,
resolvers: { Query: { subgraphObject: () => queryResult } },
});
const testkit = createTestkit(
[
useEngine({ ...GraphQLJS, execute: normalizedExecutor, subscribe: normalizedExecutor }),
useResponseCache({
enabled(context: any): boolean {
return true;
},
session(context: any): string | undefined | null {
return 'sessionString';
},
ttl: 0,
}),
],
schema,
);

const document = /* GraphQL */ `
query {
subgraphObject {
id
header {
id {
fieldA
fieldB
fieldC
}
someField
}
}
}
`;

await expect(testkit.execute(document)).rejects.toThrow(TypeError);
});