Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/many-lamps-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-tools/stitching-directives': patch
---

Allow using merge directive without keyArg argument if resolver takes 0 arguments
72 changes: 72 additions & 0 deletions packages/stitch/tests/typeMerging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,78 @@ describe('merging using type merging', () => {
expect(userByIdData.chirps[1].author.email).not.toBe(null);
});

test('works without resolver args', async () => {
let chirpSchema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
type Stats {
totalChirps: Int!
}

type Query {
stats: Stats!
}
`,
});

chirpSchema = addMocksToSchema({ schema: chirpSchema });

let authorSchema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
type Stats {
totalUsers: Int!
}
type Query {
stats: Stats!
}
`,
});

authorSchema = addMocksToSchema({ schema: authorSchema });

const stitchedSchema = stitchSchemas({
subschemas: [
{
schema: chirpSchema,
merge: {
Stats: {
fieldName: 'stats',
args: () => ({}),
},
},
batch: true,
},
{
schema: authorSchema,
merge: {
Stats: {
fieldName: 'stats',
args: () => ({}),
},
},
batch: true,
},
],
});

const query = /* GraphQL */ `
query {
stats {
totalChirps
}
}
`;

const result = await graphql({
schema: stitchedSchema,
source: query,
});

expect(result.errors).toBeUndefined();
assertSome(result.data);
const statsData: any = result.data['stats'];
expect(statsData.totalChirps).not.toBe(null);
});

test('handle top level failures on subschema queries', async () => {
let userSchema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function stitchingDirectivesValidator(

const keyArg = mergeDirective['keyArg'];
if (keyArg == null) {
if (!mergeArgsExpr && args.length !== 1) {
if (!mergeArgsExpr && args.length > 1) {
throw new Error(
'Cannot use @merge directive without `keyArg` argument if resolver takes more than one argument.'
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,40 @@ describe('type merging directives', () => {
expect(() => makeExecutableSchema({ typeDefs })).not.toThrow();
expect(() => stitchingDirectivesValidator(makeExecutableSchema({ typeDefs }))).not.toThrow();
});

test('does not throw an error if merge used without arguments on a zero args endpoint', () => {
const typeDefs = /* GraphQL */ `
${allStitchingDirectivesTypeDefs}

type Query {
_stats: Stats @merge
}

type Stats {
firstStat: Int
secondStat: Int
}
`;

expect(() => makeExecutableSchema({ typeDefs })).not.toThrow();
expect(() => stitchingDirectivesValidator(makeExecutableSchema({ typeDefs }))).not.toThrow();
});

test('throws an error if merge used without arguments on a multiple args endpoint', () => {
const typeDefs = /* GraphQL */ `
${allStitchingDirectivesTypeDefs}

type Query {
_user(id: ID, name: String): User @merge
}

type User @key(selectionSet: "{ id name }") {
id: ID
name: String
}
`;

expect(() => makeExecutableSchema({ typeDefs })).not.toThrow();
expect(() => stitchingDirectivesValidator(makeExecutableSchema({ typeDefs }))).toThrow();
});
});