Skip to content
This repository was archived by the owner on Sep 3, 2021. It is now read-only.

Commit 3e16662

Browse files
authored
Merge pull request #374 from Videodock/interfaced-relations-fix
Interfaced relations fix
2 parents ea66d52 + 7bb40e7 commit 3e16662

File tree

6 files changed

+189
-5
lines changed

6 files changed

+189
-5
lines changed

example/apollo-server/movies.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { augmentTypeDefs, augmentSchema } from '../../src/index';
22
import { ApolloServer, gql, makeExecutableSchema } from 'apollo-server';
3-
import { v1 as neo4j } from 'neo4j-driver';
3+
import neo4j from 'neo4j-driver';
44
import { typeDefs, resolvers } from './movies-schema';
55

66
const schema = makeExecutableSchema({

src/translate.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,11 @@ export const nodeTypeFieldOnRelationType = ({
379379
return {
380380
selection: relationTypeMutationPayloadField({
381381
...fieldInfo,
382-
parentSelectionInfo
382+
schemaType,
383+
isInlineFragment,
384+
parentSelectionInfo,
385+
innerSchemaType,
386+
resolveInfo
383387
}),
384388
subSelection: fieldInfo.subSelection
385389
};
@@ -405,17 +409,27 @@ const relationTypeMutationPayloadField = ({
405409
initial,
406410
fieldName,
407411
variableName,
412+
nestedVariable,
408413
subSelection,
409414
skipLimit,
410415
commaIfTail,
411416
tailParams,
412-
parentSelectionInfo
417+
parentSelectionInfo,
418+
isInlineFragment,
419+
resolveInfo,
420+
innerSchemaType
413421
}) => {
414422
const safeVariableName = safeVar(variableName);
423+
const fragmentTypeParams = isInlineFragment
424+
? derivedTypesParams(resolveInfo.schema, innerSchemaType.name)
425+
: {};
426+
subSelection[1] = { ...subSelection[1], ...fragmentTypeParams };
415427
return {
416428
initial: `${initial}${fieldName}: ${safeVariableName} {${
417-
subSelection[0]
418-
}}${skipLimit} ${commaIfTail}`,
429+
isInlineFragment
430+
? `${fragmentType(nestedVariable, innerSchemaType.name)},`
431+
: ''
432+
}${subSelection[0]}}${skipLimit} ${commaIfTail}`,
419433
...tailParams,
420434
variableName:
421435
fieldName === 'from' ? parentSelectionInfo.to : parentSelectionInfo.from

test/helpers/cypherTestHelpers.js

+3
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ export function augmentedSchemaCypherTestRunner(
208208
MergeUserFriends: checkCypherMutation,
209209
UpdateUserFriends: checkCypherMutation,
210210
RemoveUserFriends: checkCypherMutation,
211+
AddActorKnows: checkCypherMutation,
212+
MergeActorKnows: checkCypherMutation,
213+
RemoveActorKnows: checkCypherMutation,
211214
currentUserId: checkCypherMutation,
212215
computedObjectWithCypherParams: checkCypherMutation,
213216
computedStringList: checkCypherMutation,

test/helpers/testSchema.js

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export const testSchema = /* GraphQL */ `
8787
userId: ID!
8888
name: String
8989
movies: [Movie] @relation(name: "ACTED_IN", direction: "OUT")
90+
knows: [Person] @relation(name: "KNOWS", direction: "OUT")
9091
}
9192
9293
type User implements Person {

test/unit/augmentSchemaTest.test.js

+50
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,14 @@ test.cb('Test augmented schema', t => {
427427
movies_none: _MovieFilter
428428
movies_single: _MovieFilter
429429
movies_every: _MovieFilter
430+
knows: _PersonFilter
431+
knows_not: _PersonFilter
432+
knows_in: [_PersonFilter!]
433+
knows_not_in: [_PersonFilter!]
434+
knows_some: _PersonFilter
435+
knows_none: _PersonFilter
436+
knows_single: _PersonFilter
437+
knows_every: _PersonFilter
430438
}
431439
432440
input _StateFilter {
@@ -866,6 +874,12 @@ test.cb('Test augmented schema', t => {
866874
orderBy: [_MovieOrdering]
867875
filter: _MovieFilter
868876
): [Movie] @relation(name: "ACTED_IN", direction: "OUT")
877+
knows(
878+
first: Int
879+
offset: Int
880+
orderBy: [_PersonOrdering]
881+
filter: _PersonFilter
882+
): [Person] @relation(name: "KNOWS", direction: "OUT")
869883
_id: String
870884
}
871885
@@ -1503,6 +1517,24 @@ test.cb('Test augmented schema', t => {
15031517
): _MergeActorMoviesPayload
15041518
@MutationMeta(relationship: "ACTED_IN", from: "Actor", to: "Movie")
15051519
@hasScope(scopes: ["Actor: Merge", "Movie: Merge"])
1520+
AddActorKnows(
1521+
from: _ActorInput!
1522+
to: _PersonInput!
1523+
): _AddActorKnowsPayload
1524+
@MutationMeta(relationship: "KNOWS", from: "Actor", to: "Person")
1525+
@hasScope(scopes: ["Actor: Create", "Person: Create"])
1526+
RemoveActorKnows(
1527+
from: _ActorInput!
1528+
to: _PersonInput!
1529+
): _RemoveActorKnowsPayload
1530+
@MutationMeta(relationship: "KNOWS", from: "Actor", to: "Person")
1531+
@hasScope(scopes: ["Actor: Delete", "Person: Delete"])
1532+
MergeActorKnows(
1533+
from: _ActorInput!
1534+
to: _PersonInput!
1535+
): _MergeActorKnowsPayload
1536+
@MutationMeta(relationship: "KNOWS", from: "Actor", to: "Person")
1537+
@hasScope(scopes: ["Actor: Merge", "Person: Merge"])
15061538
CreateActor(userId: ID, name: String): Actor
15071539
@hasScope(scopes: ["Actor: Create"])
15081540
UpdateActor(userId: ID!, name: String): Actor
@@ -1901,6 +1933,24 @@ test.cb('Test augmented schema', t => {
19011933
to: Movie
19021934
}
19031935
1936+
type _AddActorKnowsPayload
1937+
@relation(name: "KNOWS", from: "Actor", to: "Person") {
1938+
from: Actor
1939+
to: Person
1940+
}
1941+
1942+
type _MergeActorKnowsPayload
1943+
@relation(name: "KNOWS", from: "Actor", to: "Person") {
1944+
from: Actor
1945+
to: Person
1946+
}
1947+
1948+
type _RemoveActorKnowsPayload
1949+
@relation(name: "KNOWS", from: "Actor", to: "Person") {
1950+
from: Actor
1951+
to: Person
1952+
}
1953+
19041954
type _AddUserRatedPayload
19051955
@relation(name: "RATED", from: "User", to: "Movie") {
19061956
from: User

test/unit/cypherTest.test.js

+116
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,122 @@ test('Update reflexive relationship mutation with relationship property', t => {
13431343
);
13441344
});
13451345

1346+
test('Add interfaced relationship mutation', t => {
1347+
const graphQLQuery = `mutation someMutation {
1348+
AddActorKnows(
1349+
from: { userId: "123" },
1350+
to: { userId: "456" }
1351+
) {
1352+
from {
1353+
userId
1354+
name
1355+
}
1356+
to {
1357+
userId
1358+
name
1359+
}
1360+
}
1361+
}`,
1362+
expectedCypherQuery = `
1363+
MATCH (\`actor_from\`:\`Actor\` {userId: $from.userId})
1364+
MATCH (\`person_to\`:\`Person\` {userId: $to.userId})
1365+
CREATE (\`actor_from\`)-[\`knows_relation\`:\`KNOWS\`]->(\`person_to\`)
1366+
RETURN \`knows_relation\` { from: \`actor_from\` { .userId , .name } ,to: \`person_to\` {FRAGMENT_TYPE: head( [ label IN labels(person_to) WHERE label IN $Person_derivedTypes ] ), .userId , .name } } AS \`_AddActorKnowsPayload\`;
1367+
`;
1368+
1369+
t.plan(1);
1370+
return augmentedSchemaCypherTestRunner(
1371+
t,
1372+
graphQLQuery,
1373+
{
1374+
from: { userId: '123' },
1375+
to: { userId: '456' },
1376+
first: -1,
1377+
offset: 0
1378+
},
1379+
expectedCypherQuery,
1380+
{}
1381+
);
1382+
});
1383+
1384+
test('Merge interfaced relationship mutation', t => {
1385+
const graphQLQuery = `mutation someMutation {
1386+
MergeActorKnows(
1387+
from: { userId: "123" },
1388+
to: { userId: "456" }
1389+
) {
1390+
from {
1391+
userId
1392+
name
1393+
}
1394+
to {
1395+
userId
1396+
name
1397+
}
1398+
}
1399+
}`,
1400+
expectedCypherQuery = `
1401+
MATCH (\`actor_from\`:\`Actor\` {userId: $from.userId})
1402+
MATCH (\`person_to\`:\`Person\` {userId: $to.userId})
1403+
MERGE (\`actor_from\`)-[\`knows_relation\`:\`KNOWS\`]->(\`person_to\`)
1404+
RETURN \`knows_relation\` { from: \`actor_from\` { .userId , .name } ,to: \`person_to\` {FRAGMENT_TYPE: head( [ label IN labels(person_to) WHERE label IN $Person_derivedTypes ] ), .userId , .name } } AS \`_MergeActorKnowsPayload\`;
1405+
`;
1406+
1407+
t.plan(1);
1408+
return augmentedSchemaCypherTestRunner(
1409+
t,
1410+
graphQLQuery,
1411+
{
1412+
from: { userId: '123' },
1413+
to: { userId: '456' },
1414+
first: -1,
1415+
offset: 0
1416+
},
1417+
expectedCypherQuery,
1418+
{}
1419+
);
1420+
});
1421+
1422+
test('Remove interfaced relationship mutation', t => {
1423+
const graphQLQuery = `mutation someMutation {
1424+
RemoveActorKnows(
1425+
from: { userId: "123" },
1426+
to: { userId: "456" }
1427+
) {
1428+
from {
1429+
userId
1430+
name
1431+
}
1432+
to {
1433+
userId
1434+
name
1435+
}
1436+
}
1437+
}`,
1438+
expectedCypherQuery = `
1439+
MATCH (\`actor_from\`:\`Actor\` {userId: $from.userId})
1440+
MATCH (\`person_to\`:\`Person\` {userId: $to.userId})
1441+
OPTIONAL MATCH (\`actor_from\`)-[\`actor_fromperson_to\`:\`KNOWS\`]->(\`person_to\`)
1442+
DELETE \`actor_fromperson_to\`
1443+
WITH COUNT(*) AS scope, \`actor_from\` AS \`_actor_from\`, \`person_to\` AS \`_person_to\`
1444+
RETURN {from: \`_actor_from\` { .userId , .name } ,to: \`_person_to\` {FRAGMENT_TYPE: head( [ label IN labels(_person_to) WHERE label IN $Person_derivedTypes ] ), .userId , .name } } AS \`_RemoveActorKnowsPayload\`;
1445+
`;
1446+
1447+
t.plan(1);
1448+
return augmentedSchemaCypherTestRunner(
1449+
t,
1450+
graphQLQuery,
1451+
{
1452+
from: { userId: '123' },
1453+
to: { userId: '456' },
1454+
first: -1,
1455+
offset: 0
1456+
},
1457+
expectedCypherQuery,
1458+
{}
1459+
);
1460+
});
1461+
13461462
test('Remove relationship mutation', t => {
13471463
const graphQLQuery = `mutation someMutation {
13481464
RemoveMovieGenres(

0 commit comments

Comments
 (0)