diff --git a/src/__tests__/restLink.ts b/src/__tests__/restLink.ts index 9eb44bf..e3356e8 100755 --- a/src/__tests__/restLink.ts +++ b/src/__tests__/restLink.ts @@ -2578,6 +2578,61 @@ describe('Mutation', () => { }); }); + it.only('returns null on empty object response without typePatcher', async () => { + expect.assertions(1); + + const link = new RestLink({ uri: '/api' }); + + const post = { id: '1', title: 'Love apollo' }; + fetchMock.post('/api/posts', { + status: 204, + body: {}, + }); + + const createPostMutation = gql` + mutation publishPost($input: PublishablePostInput!) { + publishedPost(input: $input) @rest(path: "/posts", method: "POST") + } + `; + const response = await toPromise( + execute(link, { + operationName: 'publishPost', + query: createPostMutation, + variables: { input: { title: post.title } }, + }), + ); + + expect(response.data.publishedPost).toEqual(null); + }); + + it.only('returns null on empty object response with typePatcher', async () => { + expect.assertions(1); + + const link = new RestLink({ + uri: '/api', + typePatcher: { Post: data => data }, + }); + + const post = { id: '1', title: 'Love apollo' }; + + fetchMock.post('/api/posts', { status: 204, body: {} }); + + const createPostMutation = gql` + mutation publishPost($input: PublishablePostInput!) { + publishedPost(input: $input) @rest(path: "/posts", method: "POST") + } + `; + const response = await toPromise( + execute(link, { + operationName: 'publishPost', + query: createPostMutation, + variables: { input: { title: post.title } }, + }), + ); + + expect(response.data.publishedPost).toEqual(null); + }); + it('returns an empty object on successful posts with zero Content-Length', async () => { // In Node.js parsing an empty body doesn't throw an error, so the best test is // to provide body data and ensure the zero length still triggers the empty response diff --git a/src/restLink.ts b/src/restLink.ts index e642b47..de60fd0 100755 --- a/src/restLink.ts +++ b/src/restLink.ts @@ -392,6 +392,7 @@ function insertNullsForAnyOmittedFields( currentSelectionSet: SelectionSetNode, ): void { if ( + currentSelectionSet == null || null == current || typeof current === 'number' || typeof current === 'boolean' || @@ -1183,6 +1184,8 @@ export class RestLink extends ApolloLink { if (typePatcher == null) { this.typePatcher = (result, __typename, _2) => { + if (!Object.keys(result).length) return null; + return { __typename, ...result }; }; } else if ( @@ -1202,6 +1205,8 @@ export class RestLink extends ApolloLink { outerType: string, patchDeeper: RestLink.FunctionalTypePatcher, ) => { + if (!Object.keys(data).length) return null; + const __typename = data.__typename || outerType; if (Array.isArray(data)) { return data.map(d => patchDeeper(d, __typename, patchDeeper));