Skip to content

Commit 96bd390

Browse files
authored
fix: do not cache edge types in graphql eslint (#7936)
1 parent 3452811 commit 96bd390

7 files changed

Lines changed: 147 additions & 9 deletions

File tree

.changeset/wicked-seals-study.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'hive': patch
3+
---
4+
5+
Do not cache edge types in graphql eslint. This fixes an issue where edge types were cached between
6+
runs and only the cached edge types would be referenced for subsequent runs

packages/services/api/src/modules/schema/providers/models/composite.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ export class CompositeModel {
241241
}),
242242
this.checks.policyCheck({
243243
selector,
244+
// if schema check does not compose then there's no point in linting. Pass in null in this case.
244245
incomingSdl: compositionCheck.result?.fullSchemaSdl ?? null,
245246
modifiedSdl: incoming.sdl,
246247
}),

packages/services/api/src/modules/schema/providers/models/single.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export class SingleModel {
107107
});
108108

109109
if (checksumResult === 'unchanged') {
110-
this.logger.debug('No changes detected, skipping schema check');
110+
this.logger.info('No changes detected, skipping schema check');
111111
return {
112112
conclusion: SchemaCheckConclusion.Skip,
113113
};

packages/services/api/src/modules/schema/providers/registry-checks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export class RegistryChecks {
225225
);
226226

227227
if (!args.existing) {
228-
this.logger.debug('No exiting version');
228+
this.logger.debug('No existing version');
229229
return 'initial' as const;
230230
}
231231

@@ -400,7 +400,7 @@ export class RegistryChecks {
400400
this.logger.debug('Skip policy check due to no SDL being composed.');
401401
return {
402402
status: 'skipped',
403-
};
403+
} satisfies CheckResult;
404404
}
405405

406406
const policyResult = await this.policy.checkPolicy(incomingSdl, modifiedSdl, selector);

packages/services/policy/__tests__/policy.spec.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,111 @@ describe('policy checks', () => {
105105
`);
106106
});
107107

108+
it('refreshes edge types per run', async () => {
109+
const caller = schemaPolicyApiRouter.createCaller({ req: { log: console } as any });
110+
const userSchema = `
111+
type Query {
112+
# 'first' limits results; 'after' is the cursor to start from
113+
users(first: Int, after: String): UserConnection!
114+
}
115+
116+
type UserConnection {
117+
edges: [UserEdge!]!
118+
pageInfo: PageInfo!
119+
totalCount: Int!
120+
}
121+
122+
type UserEdge {
123+
node: User!
124+
cursor: String!
125+
}
126+
127+
type PageInfo {
128+
hasNextPage: Boolean!
129+
endCursor: String
130+
}
131+
132+
interface Node {
133+
id: ID!
134+
}
135+
136+
type User {
137+
id: ID!
138+
name: String!
139+
}
140+
`;
141+
const result = await caller.checkPolicy({
142+
source: userSchema,
143+
schema: userSchema,
144+
target: '1',
145+
policy: {
146+
'relay-edge-types': [
147+
2,
148+
{
149+
withEdgeSuffix: true,
150+
shouldImplementNode: true,
151+
listTypeCanWrapOnlyEdgeType: false,
152+
},
153+
],
154+
},
155+
});
156+
157+
expect(result.length).toBe(1);
158+
expect(result[0].message).toBe("Edge type's field \`node\` must implement \`Node\` interface.");
159+
160+
const noUserSchema = `
161+
type Query {
162+
# 'first' limits results; 'after' is the cursor to start from
163+
noUsers(first: Int, after: String): NoUserConnection!
164+
}
165+
166+
type NoUserConnection {
167+
edges: [NoUserEdge!]!
168+
pageInfo: PageInfo!
169+
totalCount: Int!
170+
}
171+
172+
type NoUserEdge {
173+
node: NoUser!
174+
cursor: String!
175+
}
176+
177+
type PageInfo {
178+
hasNextPage: Boolean!
179+
endCursor: String
180+
}
181+
182+
interface Node {
183+
id: ID!
184+
}
185+
186+
type NoUser {
187+
id: ID!
188+
name: String!
189+
}
190+
`;
191+
const noUserResult = await caller.checkPolicy({
192+
source: noUserSchema,
193+
schema: noUserSchema,
194+
target: '1',
195+
policy: {
196+
'relay-edge-types': [
197+
2,
198+
{
199+
withEdgeSuffix: true,
200+
shouldImplementNode: true,
201+
listTypeCanWrapOnlyEdgeType: false,
202+
},
203+
],
204+
},
205+
});
206+
207+
expect(noUserResult.length).toBe(1);
208+
expect(noUserResult[0].message).toBe(
209+
"Edge type's field \`node\` must implement \`Node\` interface.",
210+
);
211+
});
212+
108213
/** To ensure existing policies dont break during upgrades */
109214
it.each(policies)('should support existing policies', async policy => {
110215
await expect(

patches/@graphql-eslint__eslint-plugin@3.20.1.patch

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,30 @@ index d952cee1e10976459e7c5836b86ba6540c45fdb6..d314997bfd26477c7d823cad397eb5d6
119119
+
120120
return {
121121
[ruleId]: {
122-
meta: {
122+
meta: {
123+
diff --git a/esm/rules/relay-edge-types.js b/esm/rules/relay-edge-types.js
124+
index 7a7eb179786103d9d72a4a84fb4bf811d11a4286..6fb12a5f56b71f56c9a14018d0494e9c7584f935 100644
125+
--- a/esm/rules/relay-edge-types.js
126+
+++ b/esm/rules/relay-edge-types.js
127+
@@ -12,11 +12,7 @@ const MESSAGE_MUST_BE_OBJECT_TYPE = "MESSAGE_MUST_BE_OBJECT_TYPE";
128+
const MESSAGE_MISSING_EDGE_SUFFIX = "MESSAGE_MISSING_EDGE_SUFFIX";
129+
const MESSAGE_LIST_TYPE_ONLY_EDGE_TYPE = "MESSAGE_LIST_TYPE_ONLY_EDGE_TYPE";
130+
const MESSAGE_SHOULD_IMPLEMENTS_NODE = "MESSAGE_SHOULD_IMPLEMENTS_NODE";
131+
-let edgeTypesCache;
132+
function getEdgeTypes(schema2) {
133+
- if (edgeTypesCache) {
134+
- return edgeTypesCache;
135+
- }
136+
const edgeTypes = /* @__PURE__ */ new Set();
137+
const visitor = {
138+
ObjectTypeDefinition(node) {
139+
@@ -38,8 +34,7 @@ function getEdgeTypes(schema2) {
140+
};
141+
const astNode = getDocumentNodeFromSchema(schema2);
142+
visit(astNode, visitor);
143+
- edgeTypesCache = edgeTypes;
144+
- return edgeTypesCache;
145+
+ return edgeTypes;
146+
}
147+
const schema = {
148+
type: "array",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)