Skip to content

Commit

Permalink
chore: switch to importing validation rules from graphql's public API
Browse files Browse the repository at this point in the history
I'm looking into cleaning up how validation rules are exported in
`15.0.0`. So I decided to refactor this code and switch rules imports to
use `*Rule` that is public API instead of importing internal files
directly. Sadly we forget to expose `ExecutableDefinitions` rule in
public API but I will fix it in `15.0.0` and backport into `14.x.x`
  • Loading branch information
IvanGoncharov authored and acao committed Jan 26, 2020
1 parent bcb2753 commit 599610a
Showing 1 changed file with 35 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
*
*/

import { DocumentNode, TypeDefinitionNode } from 'graphql/language';
import { GraphQLError } from 'graphql/error';
import { GraphQLSchema } from 'graphql/type';
import { CustomValidationRule } from 'graphql-language-service-types';

import { specifiedRules, TypeInfo, validate } from 'graphql';
import {
DocumentNode,
Kind,
specifiedRules,
validate,
GraphQLError,
GraphQLSchema,
NoUnusedFragmentsRule,
KnownFragmentNamesRule,
} from 'graphql';
import { ExecutableDefinitions } from 'graphql/validation/rules/ExecutableDefinitions';

/**
* Validate a GraphQL Document optionally with custom validation rules.
Expand All @@ -23,54 +30,34 @@ export function validateWithCustomRules(
customRules?: Array<CustomValidationRule>,
isRelayCompatMode?: boolean,
): Array<GraphQLError> {
// Because every fragment is considered for determing model subsets that may
// be used anywhere in the codebase they're all technically "used" by clients
// of graphql-data. So we remove this rule from the validators.
const {
NoUnusedFragments,
} = require('graphql/validation/rules/NoUnusedFragments');
const {
ExecutableDefinitions,
} = require('graphql/validation/rules/ExecutableDefinitions');
const rulesToSkip = [NoUnusedFragments, ExecutableDefinitions];
if (isRelayCompatMode) {
const {
KnownFragmentNames,
} = require('graphql/validation/rules/KnownFragmentNames');
rulesToSkip.push(KnownFragmentNames);
}

const rules = specifiedRules.filter(
rule => !rulesToSkip.some(r => r === rule),
);

const typeInfo = new TypeInfo(schema);
const rules = specifiedRules.filter(rule => {
// Because every fragment is considered for determing model subsets that may
// be used anywhere in the codebase they're all technically "used" by clients
// of graphql-data. So we remove this rule from the validators.
if (rule === NoUnusedFragmentsRule && rule === ExecutableDefinitions) {
return false;
}
if (isRelayCompatMode && rule === KnownFragmentNamesRule) {
return false;
}
return true;
});

if (customRules) {
Array.prototype.push.apply(rules, customRules);
}

const errors: Readonly<Array<GraphQLError>> = validate(
schema,
ast,
rules,
typeInfo,
);

if (errors.length > 0) {
return errors.filter(error => {
if (error.message.indexOf('Unknown directive') === -1) {
return true;
const errors = validate(schema, ast, rules);
return errors.filter(error => {
if (error.message.indexOf('Unknown directive') !== -1 && error.nodes) {
const node = error.nodes[0];
if (node && node.kind === Kind.DIRECTIVE) {
const name = node.name.value;
if (name === 'arguments' || name === 'argumentDefinitions') {
return false;
}
}
if (error.nodes && (error.nodes[0] as TypeDefinitionNode)) {
const node = <TypeDefinitionNode>error.nodes[0];
return !(
(node.name && node.name.value === 'arguments') ||
node.name.value === 'argumentDefinitions'
);
}
});
}

return [];
}
return true;
});
}

2 comments on commit 599610a

@vehbisurem
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thnx

@vehbisurem
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thnx

Please sign in to comment.