diff --git a/.circleci/config.yml b/.circleci/config.yml index 18f4d47..0ad483e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,7 @@ workflows: version: '14' - publish: <<: *only_master - version: '12' + version: '14' context: common-env-vars requires: - node-10 diff --git a/src/__tests__/valid-federated-with-multiple-primary-keys.graphql b/src/__tests__/valid-federated-with-multiple-primary-keys.graphql new file mode 100644 index 0000000..4beacc5 --- /dev/null +++ b/src/__tests__/valid-federated-with-multiple-primary-keys.graphql @@ -0,0 +1,16 @@ +type Sale @key(fields: "id") { + id: ID! + name: String + seller: User +} + +extend type User @key(fields: "id") @key(fields: "netsuiteInternalId") { + id: ID! @external + netsuiteInternalId: Int + sales: [Sale] + numberOfSales: Int +} + +extend type Query { + sales: [Sale] +} diff --git a/src/__tests__/validateSchema.test.ts b/src/__tests__/validateSchema.test.ts index 788cdde..3b65692 100644 --- a/src/__tests__/validateSchema.test.ts +++ b/src/__tests__/validateSchema.test.ts @@ -12,6 +12,11 @@ function expectError(filename: string, isFederated: boolean) { throw new Error('Expected validateSchema to throw'); } +function expectSuccess(filename: string, isFederated: boolean) { + validateSchema(filename, isFederated); + return expect(true); +} + test('non-existant.graphql', () => { expectError(__dirname + '/non-existant.graphql', false).toMatchInlineSnapshot( `"Could not find the schema at src/__tests__/non-existant.graphql"`, @@ -92,3 +97,7 @@ test('invalid-federated-schema-2.graphql', () => { " `); }); + +test('valid-federated-with-multiple-primary-keys.graphql', () => { + expectSuccess(__dirname + '/valid-federated-with-multiple-primary-keys.graphql', true).toBeTruthy(); +}); diff --git a/src/validateSchema.ts b/src/validateSchema.ts index d96720b..7d5c0d2 100644 --- a/src/validateSchema.ts +++ b/src/validateSchema.ts @@ -3,6 +3,8 @@ import {relative} from 'path'; import {GraphQLError} from 'graphql/error'; import {parse, DocumentNode} from 'graphql/language'; import {validateSDL} from 'graphql/validation/validate'; +import {specifiedSDLRules} from 'graphql/validation/specifiedRules'; +import {UniqueDirectivesPerLocationRule} from 'graphql'; import {codeFrameColumns} from '@babel/code-frame'; import ExpectedError from './ExpectedError'; import chalk from 'chalk'; @@ -13,6 +15,9 @@ directive @requires(fields: _FieldSet!) on FIELD_DEFINITION directive @provides(fields: _FieldSet!) on FIELD_DEFINITION directive @key(fields: _FieldSet!) on OBJECT | INTERFACE `; + +const OMITTED_VALIDATION_RULES = [UniqueDirectivesPerLocationRule.name]; + export default function validateSchema(filename: string, isFederated: boolean): {source: string} { let schemaString: string; try { @@ -87,7 +92,8 @@ export default function validateSchema(filename: string, isFederated: boolean): }); } - const errors = validateSDL(parsedSchema); + const rules = specifiedSDLRules.filter((rule) => !OMITTED_VALIDATION_RULES.includes(rule.name)); + const errors = validateSDL(parsedSchema, undefined, rules); if (errors.length) { throw new ExpectedError( `${chalk.red(`GraphQL schema ${errors.length > 1 ? 'errors' : 'error'} in`)} ${chalk.cyan(