mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Temporary fix - Member.id is not globally unique (#4790)
This commit is contained in:
parent
3540722f29
commit
8d98266eb6
26 changed files with 294 additions and 87 deletions
|
|
@ -78,9 +78,14 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
files: ['packages/web/app/**/*.graphql'],
|
||||
plugins: ['@graphql-eslint'],
|
||||
plugins: ['@graphql-eslint', 'hive'],
|
||||
rules: {
|
||||
'@graphql-eslint/require-id-when-available': 'error',
|
||||
// Require temporaryFixId field when available.
|
||||
// We need it to be able to cache Member objects in the frontend properly.
|
||||
// Member.id is not unique, so we need to use Member.temporaryFixId instead.
|
||||
// Once we have a better solution, we can remove this rule.
|
||||
'hive/graphql-require-selection': ['error'],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export default gql`
|
|||
|
||||
type Member {
|
||||
id: ID!
|
||||
temporaryFixId: ID!
|
||||
user: User!
|
||||
isOwner: Boolean!
|
||||
organizationAccessScopes: [OrganizationAccessScope!]!
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ export const resolvers: AuthModule.Resolvers & {
|
|||
TOKENS_WRITE: TargetAccessScope.TOKENS_WRITE,
|
||||
},
|
||||
Member: {
|
||||
temporaryFixId(member) {
|
||||
return `${member.organization}:${member.id}`;
|
||||
},
|
||||
organizationAccessScopes(member, _, { injector }) {
|
||||
return injector.get(AuthManager).getMemberOrganizationScopes({
|
||||
user: member.id,
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ const AdminStatsQuery = graphql(`
|
|||
name
|
||||
owner {
|
||||
id
|
||||
temporaryFixId
|
||||
user {
|
||||
id
|
||||
email
|
||||
|
|
@ -177,6 +178,7 @@ const AdminStatsQuery = graphql(`
|
|||
members {
|
||||
nodes {
|
||||
id
|
||||
temporaryFixId
|
||||
user {
|
||||
id
|
||||
email
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const ProjectLayoutQuery = graphql(`
|
|||
name
|
||||
me {
|
||||
id
|
||||
temporaryFixId
|
||||
...CanAccessProject_MemberFragment
|
||||
}
|
||||
projects {
|
||||
|
|
|
|||
|
|
@ -49,14 +49,6 @@ export function TargetSelector(props: {
|
|||
const targets = currentProject?.targets.nodes;
|
||||
const currentTarget = targets?.find(node => node.cleanId === props.currentTargetCleanId);
|
||||
|
||||
console.log({
|
||||
organizations,
|
||||
props,
|
||||
currentOrganization,
|
||||
currentProject,
|
||||
currentTarget,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{currentOrganization ? (
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ const TargetLayoutQuery = graphql(`
|
|||
name
|
||||
me {
|
||||
id
|
||||
temporaryFixId
|
||||
...CanAccessTarget_MemberFragment
|
||||
}
|
||||
projects {
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ const UsePermissionManager_OrganizationFragment = graphql(`
|
|||
const UsePermissionManager_MemberFragment = graphql(`
|
||||
fragment UsePermissionManager_MemberFragment on Member {
|
||||
id
|
||||
temporaryFixId
|
||||
targetAccessScopes
|
||||
projectAccessScopes
|
||||
organizationAccessScopes
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ const OrganizationMemberRoleSwitcher_AssignRoleMutation = graphql(`
|
|||
ok {
|
||||
updatedMember {
|
||||
id
|
||||
temporaryFixId
|
||||
user {
|
||||
id
|
||||
displayName
|
||||
|
|
@ -65,6 +66,7 @@ const OrganizationMemberRoleSwitcher_OrganizationFragment = graphql(`
|
|||
cleanId
|
||||
me {
|
||||
id
|
||||
temporaryFixId
|
||||
isAdmin
|
||||
organizationAccessScopes
|
||||
projectAccessScopes
|
||||
|
|
@ -72,6 +74,7 @@ const OrganizationMemberRoleSwitcher_OrganizationFragment = graphql(`
|
|||
}
|
||||
owner {
|
||||
id
|
||||
temporaryFixId
|
||||
}
|
||||
memberRoles {
|
||||
id
|
||||
|
|
@ -95,6 +98,7 @@ const OrganizationMemberRoleSwitcher_OrganizationFragment = graphql(`
|
|||
const OrganizationMemberRoleSwitcher_MemberFragment = graphql(`
|
||||
fragment OrganizationMemberRoleSwitcher_MemberFragment on Member {
|
||||
id
|
||||
temporaryFixId
|
||||
organizationAccessScopes
|
||||
projectAccessScopes
|
||||
targetAccessScopes
|
||||
|
|
@ -317,6 +321,7 @@ const OrganizationMemberRow_DeleteMember = graphql(`
|
|||
const OrganizationMemberRow_MemberFragment = graphql(`
|
||||
fragment OrganizationMemberRow_MemberFragment on Member {
|
||||
id
|
||||
temporaryFixId
|
||||
user {
|
||||
id
|
||||
provider
|
||||
|
|
|
|||
|
|
@ -363,6 +363,7 @@ const OrganizationMemberRolesMigrationGroup_Migrate = graphql(`
|
|||
members {
|
||||
nodes {
|
||||
id
|
||||
temporaryFixId
|
||||
organizationAccessScopes
|
||||
projectAccessScopes
|
||||
targetAccessScopes
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ const ChangePermissionsModal_OrganizationFragment = graphql(`
|
|||
|
||||
export const ChangePermissionsModal_MemberFragment = graphql(`
|
||||
fragment ChangePermissionsModal_MemberFragment on Member {
|
||||
temporaryFixId
|
||||
...UsePermissionManager_MemberFragment
|
||||
}
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ const TransferOrganizationOwnership_Members = graphql(`
|
|||
name
|
||||
members {
|
||||
nodes {
|
||||
temporaryFixId
|
||||
isOwner
|
||||
...MemberFields
|
||||
user {
|
||||
|
|
@ -53,6 +54,7 @@ const TransferOrganizationOwnership_Members = graphql(`
|
|||
const MemberFields = graphql(`
|
||||
fragment MemberFields on Member {
|
||||
id
|
||||
temporaryFixId
|
||||
user {
|
||||
id
|
||||
fullName
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export { OrganizationAccessScope };
|
|||
const CanAccessOrganization_MemberFragment = graphql(`
|
||||
fragment CanAccessOrganization_MemberFragment on Member {
|
||||
id
|
||||
temporaryFixId
|
||||
organizationAccessScopes
|
||||
}
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export { TargetAccessScope };
|
|||
export const CanAccessTarget_MemberFragment = graphql(`
|
||||
fragment CanAccessTarget_MemberFragment on Member {
|
||||
id
|
||||
temporaryFixId
|
||||
targetAccessScopes
|
||||
}
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import type { CreateOperationMutationType } from '@/components/target/laboratory
|
|||
import type { DeleteCollectionMutationType } from '@/components/target/laboratory/delete-collection-modal';
|
||||
import type { DeleteOperationMutationType } from '@/components/target/laboratory/delete-operation-modal';
|
||||
import type { CreateAccessToken_CreateTokenMutation } from '@/components/v2/modals/create-access-token';
|
||||
import type { CreateOrganizationMutation } from '@/components/v2/modals/create-organization';
|
||||
import type { CreateProjectMutation } from '@/components/v2/modals/create-project';
|
||||
import type { CreateTarget_CreateTargetMutation } from '@/components/v2/modals/create-target';
|
||||
import type { DeleteOrganizationDocument } from '@/components/v2/modals/delete-organization';
|
||||
|
|
@ -68,6 +69,14 @@ const deleteAlerts: TypedDocumentNodeUpdateResolver<
|
|||
}
|
||||
};
|
||||
|
||||
const createOrganization: TypedDocumentNodeUpdateResolver<typeof CreateOrganizationMutation> = (
|
||||
_data,
|
||||
_args,
|
||||
cache,
|
||||
) => {
|
||||
cache.invalidate('Query', 'organizations');
|
||||
};
|
||||
|
||||
const deleteOrganization: TypedDocumentNodeUpdateResolver<typeof DeleteOrganizationDocument> = (
|
||||
{ deleteOrganization },
|
||||
_args,
|
||||
|
|
@ -334,6 +343,7 @@ const createOperationInDocumentCollection: TypedDocumentNodeUpdateResolver<
|
|||
|
||||
// UpdateResolver
|
||||
export const Mutation = {
|
||||
createOrganization,
|
||||
deleteOrganization,
|
||||
createProject,
|
||||
deleteProject,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ export const urqlClient = createClient({
|
|||
Mutation,
|
||||
},
|
||||
keys: {
|
||||
// Member.id is not globally unique, it's really User.id
|
||||
// In order to avoid conflicts or cache issues, let's use Member.temporaryFixId.
|
||||
// This is a temporary solution until we have a better way to handle this.
|
||||
Member: ({ temporaryFixId }) => `Member:${temporaryFixId}`,
|
||||
RequestsOverTime: noKey,
|
||||
FailuresOverTime: noKey,
|
||||
DurationOverTime: noKey,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ function useOidcProviderId() {
|
|||
}
|
||||
|
||||
function SupertokensRoutingComponent() {
|
||||
console.log('SupertokensRoutingComponent');
|
||||
const routingComponent = getRoutingComponent([
|
||||
ThirdPartyEmailPasswordPreBuiltUI,
|
||||
EmailVerificationPreBuiltUI,
|
||||
|
|
@ -97,7 +96,6 @@ const isOkta = () =>
|
|||
* Route for showing the SuperTokens login page.
|
||||
*/
|
||||
export function AuthPage() {
|
||||
console.log('AuthPage');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const oidcProvider = useOidcProviderId();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const OrganizationPolicyPageQuery = graphql(`
|
|||
organization {
|
||||
id
|
||||
me {
|
||||
temporaryFixId
|
||||
...CanAccessOrganization_MemberFragment
|
||||
}
|
||||
projects {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ const OrganizationTransferPage_GetRequest = graphql(`
|
|||
name
|
||||
owner {
|
||||
id
|
||||
temporaryFixId
|
||||
user {
|
||||
id
|
||||
displayName
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ const ProjectPolicyPageQuery = graphql(`
|
|||
id
|
||||
me {
|
||||
id
|
||||
temporaryFixId
|
||||
...CanAccessProject_MemberFragment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -827,6 +827,7 @@ const TargetLaboratoryPageQuery = graphql(`
|
|||
id
|
||||
me {
|
||||
id
|
||||
temporaryFixId
|
||||
...CanAccessTarget_MemberFragment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1033,6 +1033,7 @@ const TargetSettingsPageQuery = graphql(`
|
|||
cleanId
|
||||
...TargetSettingsPage_OrganizationFragment
|
||||
me {
|
||||
temporaryFixId
|
||||
...CDNAccessTokens_MeFragment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ import { TargetLaboratoryPage } from './pages/target-laboratory';
|
|||
import { TargetSettingsPage } from './pages/target-settings';
|
||||
|
||||
if (globalThis.window) {
|
||||
console.log('Initializing SuperTokens');
|
||||
SuperTokens.init(frontendConfig());
|
||||
if (env.sentry) {
|
||||
init({
|
||||
|
|
|
|||
112
pnpm-lock.yaml
112
pnpm-lock.yaml
|
|
@ -67,7 +67,7 @@ importers:
|
|||
version: 5.0.2(graphql@16.8.1)
|
||||
'@graphql-codegen/cli':
|
||||
specifier: 5.0.2
|
||||
version: 5.0.2(@babel/core@7.24.0)(@types/node@20.12.12)(encoding@0.1.13)(enquirer@2.3.6)(graphql@16.8.1)(typescript@5.4.5)
|
||||
version: 5.0.2(@babel/core@7.22.9)(@types/node@20.12.12)(encoding@0.1.13)(enquirer@2.3.6)(graphql@16.8.1)(typescript@5.4.5)
|
||||
'@graphql-codegen/client-preset':
|
||||
specifier: 4.2.6
|
||||
version: 4.2.6(encoding@0.1.13)(graphql@16.8.1)
|
||||
|
|
@ -91,7 +91,7 @@ importers:
|
|||
version: 3.0.0(graphql@16.8.1)
|
||||
'@graphql-eslint/eslint-plugin':
|
||||
specifier: 3.20.1
|
||||
version: 3.20.1(patch_hash=n437g5o7zq7pnxdxldn52uql2q)(@babel/core@7.24.0)(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)
|
||||
version: 3.20.1(patch_hash=n437g5o7zq7pnxdxldn52uql2q)(@babel/core@7.22.9)(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)
|
||||
'@graphql-inspector/cli':
|
||||
specifier: 4.0.3
|
||||
version: 4.0.3(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)
|
||||
|
|
@ -1982,7 +1982,7 @@ importers:
|
|||
version: 1.0.7(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@theguild/components':
|
||||
specifier: 6.5.3
|
||||
version: 6.5.3(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(webpack@5.89.0(@swc/core@1.5.7(@swc/helpers@0.5.5))(esbuild@0.19.11))
|
||||
version: 6.5.3(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(webpack@5.89.0(@swc/core@1.5.7(@swc/helpers@0.5.5))(esbuild@0.19.11))
|
||||
clsx:
|
||||
specifier: 2.1.1
|
||||
version: 2.1.1
|
||||
|
|
@ -1994,13 +1994,13 @@ importers:
|
|||
version: 4.0.3
|
||||
next:
|
||||
specifier: 14.2.3
|
||||
version: 14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next-sitemap:
|
||||
specifier: 4.2.3
|
||||
version: 4.2.3(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||
version: 4.2.3(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||
next-themes:
|
||||
specifier: '*'
|
||||
version: 0.2.1(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
version: 0.2.1(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react:
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1
|
||||
|
|
@ -19746,7 +19746,7 @@ snapshots:
|
|||
graphql: 16.8.1
|
||||
tslib: 2.6.2
|
||||
|
||||
'@graphql-codegen/cli@5.0.2(@babel/core@7.24.0)(@types/node@20.12.12)(encoding@0.1.13)(enquirer@2.3.6)(graphql@16.8.1)(typescript@5.4.5)':
|
||||
'@graphql-codegen/cli@5.0.2(@babel/core@7.22.9)(@types/node@20.12.12)(encoding@0.1.13)(enquirer@2.3.6)(graphql@16.8.1)(typescript@5.4.5)':
|
||||
dependencies:
|
||||
'@babel/generator': 7.23.6
|
||||
'@babel/template': 7.22.15
|
||||
|
|
@ -19756,7 +19756,7 @@ snapshots:
|
|||
'@graphql-codegen/plugin-helpers': 5.0.3(graphql@16.8.1)
|
||||
'@graphql-tools/apollo-engine-loader': 8.0.0(encoding@0.1.13)(graphql@16.8.1)
|
||||
'@graphql-tools/code-file-loader': 8.1.0(graphql@16.8.1)
|
||||
'@graphql-tools/git-loader': 8.0.1(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/git-loader': 8.0.1(@babel/core@7.22.9)(graphql@16.8.1)
|
||||
'@graphql-tools/github-loader': 8.0.0(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)
|
||||
'@graphql-tools/graphql-file-loader': 8.0.0(graphql@16.8.1)
|
||||
'@graphql-tools/json-file-loader': 8.0.0(graphql@16.8.1)
|
||||
|
|
@ -19960,11 +19960,11 @@ snapshots:
|
|||
- encoding
|
||||
- supports-color
|
||||
|
||||
'@graphql-eslint/eslint-plugin@3.20.1(patch_hash=n437g5o7zq7pnxdxldn52uql2q)(@babel/core@7.24.0)(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)':
|
||||
'@graphql-eslint/eslint-plugin@3.20.1(patch_hash=n437g5o7zq7pnxdxldn52uql2q)(@babel/core@7.22.9)(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.21.4
|
||||
'@graphql-tools/code-file-loader': 7.3.23(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/code-file-loader': 7.3.23(@babel/core@7.22.9)(graphql@16.8.1)
|
||||
'@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.22.9)(graphql@16.8.1)
|
||||
'@graphql-tools/utils': 9.2.1(graphql@16.8.1)
|
||||
chalk: 4.1.2
|
||||
debug: 4.3.4(supports-color@8.1.1)
|
||||
|
|
@ -20035,7 +20035,7 @@ snapshots:
|
|||
'@graphql-inspector/graphql-loader': 4.0.2(graphql@16.8.1)
|
||||
'@graphql-inspector/introspect-command': 4.0.3(@graphql-inspector/config@4.0.2(graphql@16.8.1))(@graphql-inspector/loaders@4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1))(graphql@16.8.1)(yargs@17.7.2)
|
||||
'@graphql-inspector/json-loader': 4.0.2(graphql@16.8.1)
|
||||
'@graphql-inspector/loaders': 4.0.3(@babel/core@7.24.0)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1)
|
||||
'@graphql-inspector/loaders': 4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1)
|
||||
'@graphql-inspector/serve-command': 4.0.3(@graphql-inspector/config@4.0.2(graphql@16.8.1))(@graphql-inspector/loaders@4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1))(graphql@16.8.1)(yargs@17.7.2)
|
||||
'@graphql-inspector/similar-command': 4.0.3(@graphql-inspector/config@4.0.2(graphql@16.8.1))(@graphql-inspector/loaders@4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1))(graphql@16.8.1)(yargs@17.7.2)
|
||||
'@graphql-inspector/url-loader': 4.0.2(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)
|
||||
|
|
@ -20062,7 +20062,7 @@ snapshots:
|
|||
'@graphql-inspector/commands@4.0.3(@graphql-inspector/config@4.0.2(graphql@16.8.1))(@graphql-inspector/loaders@4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1))(graphql@16.8.1)(yargs@17.7.2)':
|
||||
dependencies:
|
||||
'@graphql-inspector/config': 4.0.2(graphql@16.8.1)
|
||||
'@graphql-inspector/loaders': 4.0.3(@babel/core@7.24.0)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1)
|
||||
'@graphql-inspector/loaders': 4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1)
|
||||
graphql: 16.8.1
|
||||
tslib: 2.6.2
|
||||
yargs: 17.7.2
|
||||
|
|
@ -20165,10 +20165,10 @@ snapshots:
|
|||
graphql: 16.8.1
|
||||
tslib: 2.6.2
|
||||
|
||||
'@graphql-inspector/loaders@4.0.3(@babel/core@7.24.0)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1)':
|
||||
'@graphql-inspector/loaders@4.0.3(@babel/core@7.22.9)(@graphql-inspector/config@4.0.2(graphql@16.8.1))(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@graphql-inspector/config': 4.0.2(graphql@16.8.1)
|
||||
'@graphql-tools/code-file-loader': 8.0.1(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/code-file-loader': 8.0.1(@babel/core@7.22.9)(graphql@16.8.1)
|
||||
'@graphql-tools/load': 8.0.0(graphql@16.8.1)
|
||||
'@graphql-tools/utils': 10.0.3(graphql@16.8.1)
|
||||
graphql: 16.8.1
|
||||
|
|
@ -20277,9 +20277,9 @@ snapshots:
|
|||
tslib: 2.6.2
|
||||
value-or-promise: 1.0.12
|
||||
|
||||
'@graphql-tools/code-file-loader@7.3.23(@babel/core@7.24.0)(graphql@16.8.1)':
|
||||
'@graphql-tools/code-file-loader@7.3.23(@babel/core@7.22.9)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/graphql-tag-pluck': 7.5.2(@babel/core@7.22.9)(graphql@16.8.1)
|
||||
'@graphql-tools/utils': 9.2.1(graphql@16.8.1)
|
||||
globby: 11.1.0
|
||||
graphql: 16.8.1
|
||||
|
|
@ -20313,18 +20313,6 @@ snapshots:
|
|||
- '@babel/core'
|
||||
- supports-color
|
||||
|
||||
'@graphql-tools/code-file-loader@8.0.1(@babel/core@7.24.0)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@graphql-tools/graphql-tag-pluck': 8.0.1(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/utils': 10.2.0(graphql@16.8.1)
|
||||
globby: 11.1.0
|
||||
graphql: 16.8.1
|
||||
tslib: 2.6.2
|
||||
unixify: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- supports-color
|
||||
|
||||
'@graphql-tools/code-file-loader@8.1.0(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@graphql-tools/graphql-tag-pluck': 8.2.0(graphql@16.8.1)
|
||||
|
|
@ -20504,19 +20492,6 @@ snapshots:
|
|||
- '@babel/core'
|
||||
- supports-color
|
||||
|
||||
'@graphql-tools/git-loader@8.0.1(@babel/core@7.24.0)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@graphql-tools/graphql-tag-pluck': 8.0.1(@babel/core@7.24.0)(graphql@16.8.1)
|
||||
'@graphql-tools/utils': 10.2.0(graphql@16.8.1)
|
||||
graphql: 16.8.1
|
||||
is-glob: 4.0.3
|
||||
micromatch: 4.0.5
|
||||
tslib: 2.6.2
|
||||
unixify: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- supports-color
|
||||
|
||||
'@graphql-tools/github-loader@8.0.0(@types/node@20.12.12)(encoding@0.1.13)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@ardatan/sync-fetch': 0.0.1(encoding@0.1.13)
|
||||
|
|
@ -20550,10 +20525,10 @@ snapshots:
|
|||
tslib: 2.6.2
|
||||
unixify: 1.0.0
|
||||
|
||||
'@graphql-tools/graphql-tag-pluck@7.5.2(@babel/core@7.24.0)(graphql@16.8.1)':
|
||||
'@graphql-tools/graphql-tag-pluck@7.5.2(@babel/core@7.22.9)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@babel/parser': 7.24.0
|
||||
'@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.24.0)
|
||||
'@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.22.9)
|
||||
'@babel/traverse': 7.24.0
|
||||
'@babel/types': 7.24.0
|
||||
'@graphql-tools/utils': 9.2.1(graphql@16.8.1)
|
||||
|
|
@ -20589,19 +20564,6 @@ snapshots:
|
|||
- '@babel/core'
|
||||
- supports-color
|
||||
|
||||
'@graphql-tools/graphql-tag-pluck@8.0.1(@babel/core@7.24.0)(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@babel/parser': 7.24.0
|
||||
'@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.24.0)
|
||||
'@babel/traverse': 7.24.0
|
||||
'@babel/types': 7.24.0
|
||||
'@graphql-tools/utils': 10.2.0(graphql@16.8.1)
|
||||
graphql: 16.8.1
|
||||
tslib: 2.6.2
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- supports-color
|
||||
|
||||
'@graphql-tools/graphql-tag-pluck@8.2.0(graphql@16.8.1)':
|
||||
dependencies:
|
||||
'@babel/core': 7.24.0
|
||||
|
|
@ -24973,16 +24935,16 @@ snapshots:
|
|||
|
||||
'@theguild/buddy@0.1.0(patch_hash=ryylgra5xglhidfoiaxehn22hq)': {}
|
||||
|
||||
'@theguild/components@6.5.3(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(webpack@5.89.0(@swc/core@1.5.7(@swc/helpers@0.5.5))(esbuild@0.19.11))':
|
||||
'@theguild/components@6.5.3(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)(webpack@5.89.0(@swc/core@1.5.7(@swc/helpers@0.5.5))(esbuild@0.19.11))':
|
||||
dependencies:
|
||||
'@giscus/react': 3.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@next/bundle-analyzer': 13.4.2
|
||||
clsx: 2.1.0
|
||||
fuzzy: 0.1.3
|
||||
next: 14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next: 14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next-videos: 1.5.0(webpack@5.89.0(@swc/core@1.5.7(@swc/helpers@0.5.5))(esbuild@0.19.11))
|
||||
nextra: 3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)
|
||||
nextra-theme-docs: 3.0.0-alpha.22(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
nextra: 3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)
|
||||
nextra-theme-docs: 3.0.0-alpha.22(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-paginate: 8.2.0(react@18.3.1)
|
||||
|
|
@ -32474,17 +32436,17 @@ snapshots:
|
|||
|
||||
neo-async@2.6.2: {}
|
||||
|
||||
next-sitemap@4.2.3(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
|
||||
next-sitemap@4.2.3(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
|
||||
dependencies:
|
||||
'@corex/deepmerge': 4.0.43
|
||||
'@next/env': 13.5.6
|
||||
fast-glob: 3.3.2
|
||||
minimist: 1.2.8
|
||||
next: 14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next: 14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
|
||||
next-themes@0.2.1(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
next-themes@0.2.1(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
next: 14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next: 14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
|
|
@ -32496,7 +32458,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- webpack
|
||||
|
||||
next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@next/env': 14.2.3
|
||||
'@swc/helpers': 0.5.5
|
||||
|
|
@ -32506,7 +32468,7 @@ snapshots:
|
|||
postcss: 8.4.31
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
styled-jsx: 5.1.1(@babel/core@7.24.0)(react@18.3.1)
|
||||
styled-jsx: 5.1.1(@babel/core@7.22.9)(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 14.2.3
|
||||
'@next/swc-darwin-x64': 14.2.3
|
||||
|
|
@ -32522,7 +32484,7 @@ snapshots:
|
|||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
nextra-theme-docs@3.0.0-alpha.22(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
nextra-theme-docs@3.0.0-alpha.22(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@popperjs/core': 2.11.8
|
||||
|
|
@ -32531,15 +32493,15 @@ snapshots:
|
|||
flexsearch: 0.7.43
|
||||
focus-visible: 5.2.0
|
||||
intersection-observer: 0.12.2
|
||||
next: 14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next-themes: 0.2.1(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
nextra: 3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)
|
||||
next: 14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next-themes: 0.2.1(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
nextra: 3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
scroll-into-view-if-needed: 3.1.0
|
||||
zod: 3.23.8
|
||||
|
||||
nextra@3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5):
|
||||
nextra@3.0.0-alpha.22(@types/react@18.3.2)(next@14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5):
|
||||
dependencies:
|
||||
'@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@mdx-js/mdx': 3.0.1
|
||||
|
|
@ -32557,7 +32519,7 @@ snapshots:
|
|||
gray-matter: 4.0.3
|
||||
hast-util-to-estree: 3.1.0
|
||||
katex: 0.16.9
|
||||
next: 14.2.3(@babel/core@7.24.0)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next: 14.2.3(@babel/core@7.22.9)(@opentelemetry/api@1.8.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
p-limit: 4.0.0
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
|
@ -35445,12 +35407,12 @@ snapshots:
|
|||
hey-listen: 1.0.8
|
||||
tslib: 2.6.2
|
||||
|
||||
styled-jsx@5.1.1(@babel/core@7.24.0)(react@18.3.1):
|
||||
styled-jsx@5.1.1(@babel/core@7.22.9)(react@18.3.1):
|
||||
dependencies:
|
||||
client-only: 0.0.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@babel/core': 7.24.0
|
||||
'@babel/core': 7.22.9
|
||||
|
||||
stylehacks@6.1.1(postcss@8.4.38):
|
||||
dependencies:
|
||||
|
|
|
|||
211
rules/graphql-require-selection.cjs
Normal file
211
rules/graphql-require-selection.cjs
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/// @ts-check
|
||||
const {
|
||||
requireGraphQLSchemaFromContext,
|
||||
requireSiblingsOperations,
|
||||
} = require('@graphql-eslint/eslint-plugin');
|
||||
|
||||
const {
|
||||
Kind,
|
||||
TypeInfo,
|
||||
visit,
|
||||
visitWithTypeInfo,
|
||||
GraphQLObjectType,
|
||||
GraphQLInterfaceType,
|
||||
GraphQLUnionType,
|
||||
isListType,
|
||||
isNonNullType,
|
||||
} = require('graphql');
|
||||
|
||||
function getBaseType(type) {
|
||||
if (isNonNullType(type) || isListType(type)) {
|
||||
return getBaseType(type.ofType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
const RULE_ID = 'graphql-require-selections';
|
||||
const idNames = ['temporaryFixId'];
|
||||
|
||||
/// Ported https://github.com/dimaMachina/graphql-eslint/blob/3c1020888472eb6579ffddc1e8e5ec16df8fad74/packages/plugin/src/rules/require-selections.ts
|
||||
|
||||
/**
|
||||
* @type {import('@graphql-eslint/eslint-plugin').GraphQLESLintRule}
|
||||
*/
|
||||
const rule = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
[RULE_ID]:
|
||||
"Field{{ pluralSuffix }} {{ fieldName }} must be selected when it's available on a type.\nInclude it in your selection set{{ addition }}.",
|
||||
},
|
||||
docs: {
|
||||
category: 'Operations',
|
||||
description: 'Enforce selecting specific fields when they are available on the GraphQL type.',
|
||||
requiresSchema: true,
|
||||
requiresSiblings: true,
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const schema = requireGraphQLSchemaFromContext(RULE_ID, context);
|
||||
const siblings = requireSiblingsOperations(RULE_ID, context);
|
||||
|
||||
// Check selections only in OperationDefinition,
|
||||
// skip selections of OperationDefinition and InlineFragment
|
||||
const selector =
|
||||
'OperationDefinition SelectionSet[parent.kind!=/(^OperationDefinition|InlineFragment)$/]';
|
||||
const typeInfo = new TypeInfo(schema);
|
||||
|
||||
function checkFragments(node) {
|
||||
for (const selection of node.selections) {
|
||||
if (selection.kind !== Kind.FRAGMENT_SPREAD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const [foundSpread] = siblings.getFragment(selection.name.value);
|
||||
if (!foundSpread) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const checkedFragmentSpreads = new Set();
|
||||
const visitor = visitWithTypeInfo(typeInfo, {
|
||||
SelectionSet(node, key, _parent) {
|
||||
const parent = _parent;
|
||||
if (parent.kind === Kind.FRAGMENT_DEFINITION) {
|
||||
checkedFragmentSpreads.add(parent.name.value);
|
||||
} else if (parent.kind !== Kind.INLINE_FRAGMENT) {
|
||||
checkSelections(
|
||||
node,
|
||||
typeInfo.getType(),
|
||||
selection.loc.start,
|
||||
parent,
|
||||
checkedFragmentSpreads,
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
visit(foundSpread.document, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
function checkSelections(
|
||||
node,
|
||||
type,
|
||||
// Fragment can be placed in separate file
|
||||
// Provide actual fragment spread location instead of location in fragment
|
||||
loc,
|
||||
// Can't access to node.parent in GraphQL AST.Node, so pass as argument
|
||||
parent,
|
||||
checkedFragmentSpreads = new Set(),
|
||||
) {
|
||||
const rawType = getBaseType(type);
|
||||
|
||||
if (rawType instanceof GraphQLObjectType || rawType instanceof GraphQLInterfaceType) {
|
||||
checkFields(rawType);
|
||||
} else if (rawType instanceof GraphQLUnionType) {
|
||||
for (const selection of node.selections) {
|
||||
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
||||
const types = rawType.getTypes();
|
||||
const t = types.find(t => t.name === selection.typeCondition.name.value);
|
||||
if (t) {
|
||||
checkFields(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkFields(rawType) {
|
||||
const fields = rawType.getFields();
|
||||
const hasIdFieldInType = idNames.some(name => fields[name]);
|
||||
|
||||
if (!hasIdFieldInType) {
|
||||
return;
|
||||
}
|
||||
|
||||
function hasIdField({ selections }) {
|
||||
return selections.some(selection => {
|
||||
if (selection.kind === Kind.FIELD) {
|
||||
if (selection.alias && idNames.includes(selection.alias.value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return idNames.includes(selection.name.value);
|
||||
}
|
||||
|
||||
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
||||
return hasIdField(selection.selectionSet);
|
||||
}
|
||||
|
||||
if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
||||
const [foundSpread] = siblings.getFragment(selection.name.value);
|
||||
if (foundSpread) {
|
||||
const fragmentSpread = foundSpread.document;
|
||||
checkedFragmentSpreads.add(fragmentSpread.name.value);
|
||||
return hasIdField(fragmentSpread.selectionSet);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
const hasId = hasIdField(node);
|
||||
|
||||
checkFragments(node);
|
||||
|
||||
if (hasId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pluralSuffix = idNames.length > 1 ? 's' : '';
|
||||
const fieldName = idNames.join(',');
|
||||
|
||||
const addition =
|
||||
checkedFragmentSpreads.size === 0
|
||||
? ''
|
||||
: ` or add to used fragment${
|
||||
checkedFragmentSpreads.size > 1 ? 's' : ''
|
||||
} ${Array.from(checkedFragmentSpreads).join(', ')}`;
|
||||
|
||||
const problem = {
|
||||
loc,
|
||||
messageId: RULE_ID,
|
||||
data: {
|
||||
pluralSuffix,
|
||||
fieldName,
|
||||
addition,
|
||||
},
|
||||
};
|
||||
|
||||
// Don't provide suggestions for selections in fragments as fragment can be in a separate file
|
||||
if ('type' in node) {
|
||||
problem.suggest = idNames.map(idName => ({
|
||||
desc: `Add \`${idName}\` selection`,
|
||||
fix: fixer => {
|
||||
let insertNode = node.selections[0];
|
||||
insertNode =
|
||||
insertNode.kind === Kind.INLINE_FRAGMENT
|
||||
? insertNode.selectionSet.selections[0]
|
||||
: insertNode;
|
||||
return fixer.insertTextBefore(insertNode, `${idName} `);
|
||||
},
|
||||
}));
|
||||
}
|
||||
context.report(problem);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[selector](node) {
|
||||
const typeInfo = node.typeInfo();
|
||||
if (typeInfo.gqlType) {
|
||||
checkSelections(node, typeInfo.gqlType, node.loc.start, node.parent);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = rule;
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
rules: {
|
||||
'enforce-deps-in-dev': require('./enforce-deps-in-dev.cjs'),
|
||||
'graphql-require-selection': require('./graphql-require-selection.cjs'),
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue