Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions src/schemaModelValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { schemaStringify } from './schemaParser.js';
import { print } from 'graphql';
import {gql} from 'graphql-tag'
import { loggerInfo, yellow } from "./logger.js";
import { GraphQLID } from 'graphql';

let quiet = false;
const typesToAdd = [];
Expand Down Expand Up @@ -136,7 +137,7 @@ function injectChanges(schemaModel) {

function addNode(def) {
let name = def.name.value;
const idField = getIdField(def);
const idField = getIdFieldWithDirective(def);

// Create Input type
typesToAdd.push(`input ${name}Input {\n${print(getInputFields(def))}\n}`);
Expand Down Expand Up @@ -211,23 +212,29 @@ function addFilterOptionsArguments(field) {
}


function getIdField(objTypeDef) {
function getIdFieldWithDirective(objTypeDef) {
return objTypeDef.fields.find(
field =>
field.directives && field.directives.some(directive => directive.name.value === 'id')
);
}

function getIdFieldByType(objTypeDef) {
return objTypeDef.fields.find(field => field.type?.type?.kind === 'NamedType' && field.type?.type?.name?.value === GraphQLID.name);
}


function createIdField() {
function createIdDirective() {
return {kind: 'Directive', name: {kind: 'Name', value: 'id'}, arguments: []};
}

function createIdFieldWithDirective() {
return {
kind: 'FieldDefinition',
name: { kind: 'Name', value: '_id' },
arguments: [],
type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } } },
directives: [
{ kind: 'Directive', name: { kind: 'Name', value: 'id' }, arguments: [] }
]
directives: [createIdDirective()]
};
}

Expand Down Expand Up @@ -265,8 +272,15 @@ function inferGraphDatabaseDirectives(schemaModel) {
currentType = def.name.value;

// Only add _id field to the object type if it doesn't have an ID field already
if (!getIdField(def)) {
def.fields.unshift(createIdField());
if (!getIdFieldWithDirective(def)) {
// there is no field with @id directive
const idFieldByType = getIdFieldByType(def);
if (idFieldByType) {
// there is an ID field, add the missing @id directive
idFieldByType.directives.unshift(createIdDirective());
} else {
def.fields.unshift(createIdFieldWithDirective());
}
}

addNode(def);
Expand Down
6 changes: 6 additions & 0 deletions src/test/directive-id.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ type User {
type Group {
name: String
}

type Role {
# id field does not have directive
roleId: ID!
name: String
}
8 changes: 8 additions & 0 deletions src/test/schemaModelValidator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@ describe('validatedSchemaModel', () => {
const objTypeDefs = model.definitions.filter(def => def.kind === 'ObjectTypeDefinition');
const userType = objTypeDefs.find(def => def.name.value === 'User');
const groupType = objTypeDefs.find(def => def.name.value === 'Group');
const roleType = objTypeDefs.find(def => def.name.value === 'Role');

expect(userType.fields).toHaveLength(3);
expect(groupType.fields).toHaveLength(2);
expect(roleType.fields).toHaveLength(2);

const userIdFields = getIdFields(userType);
const groupIdFields = getIdFields(groupType);
const roleIdFields = getIdFields(roleType);

expect(userIdFields).toHaveLength(1);
expect(groupIdFields).toHaveLength(1);
expect(roleIdFields).toHaveLength(1);
expect(userIdFields[0].name.value).toEqual('userId');
expect(groupIdFields[0].name.value).toEqual('_id');
expect(roleIdFields[0].name.value).toEqual('roleId');
});

test('should define the same ID fields on a type and its input type', () => {
Expand Down