Skip to content

Commit

Permalink
fix caching issues for no-unreachable-types / no-unused-fields ru…
Browse files Browse the repository at this point in the history
…les for multi projects (#2455)

* aa

* update tests

* fix lint
  • Loading branch information
dimaMachina authored Jul 31, 2024
1 parent 7e23fa4 commit 08a8a13
Show file tree
Hide file tree
Showing 9 changed files with 31 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-seals-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-eslint/eslint-plugin': patch
---

fix caching issues for `no-unreachable-types` / `no-unused-fields` rules for multi projects
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { custom } from 'custom-graphql-tag';

/* MyGraphQL */ `
fragment UserFields on User {
fragment UserFields on AnotherUser {
firstName
lastName
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
type User {
type AnotherUser {
firstName: String
lastName: String
}

type Query {
users: [User]
users: [AnotherUser]
}
8 changes: 4 additions & 4 deletions packages/plugin/__tests__/__snapshots__/examples.spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ exports[`Examples > should work in multiple projects 1`] = `
desc: Rename to \`users\`,
fix: {
range: [
141,
141,
148,
148,
],
text: query users ,
},
Expand Down Expand Up @@ -268,10 +268,10 @@ Accepted type: ID.,
messages: [
{
column: 6,
endColumn: 10,
endColumn: 17,
endLine: 1,
line: 1,
message: type "User" must have exactly one non-nullable unique identifier.
message: type "AnotherUser" must have exactly one non-nullable unique identifier.
Accepted name: id.
Accepted type: ID.,
nodeType: Name,
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin/src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import debugFactory from 'debug';

const log = debugFactory('graphql-eslint:ModuleCache');

export class ModuleCache<T, K = any> {
export class ModuleCache<K, T> {
map = new Map<K, { lastSeen: [number, number]; result: T }>();

set(cacheKey: K, result: T): void {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin/src/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ModuleCache } from './cache.js';
import { Pointer } from './types.js';

const debug = debugFactory('graphql-eslint:operations');
const operationsCache = new ModuleCache<Source[]>();
const operationsCache = new ModuleCache<GraphQLProjectConfig['documents'], Source[]>();

const handleVirtualPath = (documents: Source[]): Source[] => {
const filepathMap: Record<string, number> = Object.create(null);
Expand Down
14 changes: 8 additions & 6 deletions packages/plugin/src/rules/no-unreachable-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
NameNode,
visit,
} from 'graphql';
import { GraphQLProjectConfig } from 'graphql-config';
import lowerCase from 'lodash.lowercase';
import { ModuleCache } from '../cache.js';
import { GraphQLESTreeNode } from '../estree-converter/index.js';
import { GraphQLESLintRule } from '../types.js';
import { getTypeName, requireGraphQLSchemaFromContext } from '../utils.js';
Expand All @@ -33,7 +35,7 @@ const KINDS = [

type ReachableTypes = Set<string>;

let reachableTypesCache: ReachableTypes;
const reachableTypesCache = new ModuleCache<GraphQLProjectConfig['schema'], ReachableTypes>();

const RequestDirectiveLocations = new Set<string>([
DirectiveLocation.QUERY,
Expand All @@ -49,8 +51,9 @@ const RequestDirectiveLocations = new Set<string>([
function getReachableTypes(schema: GraphQLSchema): ReachableTypes {
// We don't want cache reachableTypes on test environment
// Otherwise reachableTypes will be same for all tests
if (process.env.NODE_ENV !== 'test' && reachableTypesCache) {
return reachableTypesCache;
const cachedValue = reachableTypesCache.get(schema);
if (process.env.NODE_ENV !== 'test' && cachedValue) {
return cachedValue;
}
const reachableTypes: ReachableTypes = new Set();

Expand Down Expand Up @@ -106,9 +109,8 @@ function getReachableTypes(schema: GraphQLSchema): ReachableTypes {
}
}
}

reachableTypesCache = reachableTypes;
return reachableTypesCache;
reachableTypesCache.set(schema, reachableTypes);
return reachableTypes;
}

export const rule: GraphQLESLintRule = {
Expand Down
13 changes: 8 additions & 5 deletions packages/plugin/src/rules/no-unused-fields.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { GraphQLSchema, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
import { GraphQLProjectConfig } from 'graphql-config';
import { ModuleCache } from '../cache.js';
import { SiblingOperations } from '../siblings.js';
import { GraphQLESLintRule } from '../types.js';
import { requireGraphQLSchemaFromContext, requireSiblingsOperations } from '../utils.js';
Expand All @@ -7,13 +9,14 @@ const RULE_ID = 'no-unused-fields';

type UsedFields = Record<string, Set<string>>;

let usedFieldsCache: UsedFields;
const usedFieldsCache = new ModuleCache<GraphQLProjectConfig['schema'], UsedFields>();

function getUsedFields(schema: GraphQLSchema, operations: SiblingOperations): UsedFields {
// We don't want cache usedFields on test environment
// Otherwise usedFields will be same for all tests
if (process.env.NODE_ENV !== 'test' && usedFieldsCache) {
return usedFieldsCache;
const cachedValue = usedFieldsCache.get(schema);
if (process.env.NODE_ENV !== 'test' && cachedValue) {
return cachedValue;
}
const usedFields: UsedFields = Object.create(null);
const typeInfo = new TypeInfo(schema);
Expand All @@ -37,8 +40,8 @@ function getUsedFields(schema: GraphQLSchema, operations: SiblingOperations): Us
for (const { document } of allDocuments) {
visit(document, visitor);
}
usedFieldsCache = usedFields;
return usedFieldsCache;
usedFieldsCache.set(schema, usedFields);
return usedFields;
}

export const rule: GraphQLESLintRule = {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { GraphQLProjectConfig } from 'graphql-config';
import { ModuleCache } from './cache.js';
import { Pointer, Schema } from './types.js';

const schemaCache = new ModuleCache<GraphQLSchema>();
const schemaCache = new ModuleCache<GraphQLProjectConfig['schema'], GraphQLSchema>();
const debug = debugFactory('graphql-eslint:schema');

export function getSchema(project: GraphQLProjectConfig): Schema {
Expand Down

0 comments on commit 08a8a13

Please sign in to comment.