Skip to content

Commit

Permalink
Fix for input objects passed via query params on GET requests (#1370)
Browse files Browse the repository at this point in the history
* Add test for input objects passed via query params on GET requests

* Fix

---------

Co-authored-by: Arda TANRIKULU <[email protected]>
  • Loading branch information
nathanchapman and ardatan authored Nov 23, 2023
1 parent 3b6ce43 commit 028af74
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-sloths-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'sofa-api': patch
---

Handle nested query parameters
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"openapi-types": "^12.1.0",
"param-case": "^3.0.4",
"title-case": "^3.0.3",
"qs": "^6.11.2",
"tslib": "^2.5.0"
},
"scripts": {
Expand All @@ -80,6 +81,7 @@
"@types/node": "20.9.4",
"@types/swagger-ui-dist": "3.30.1",
"@types/yamljs": "0.2.31",
"@types/qs": "6.9.10",
"babel-jest": "29.5.0",
"bob-the-bundler": "7.0.1",
"chalk": "^4",
Expand Down
11 changes: 3 additions & 8 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import type { HTTPMethod, StatusCode } from 'fets/typings/typed-fetch';
import { isInPath, resolveParamSchema, resolveRequestBody, resolveResponse, resolveVariableDescription } from './open-api/operations.js';
import { buildSchemaObjectFromType } from './open-api/types.js';
import { parse as qsParse } from 'qs';

export type ErrorHandler = (errors: ReadonlyArray<any>) => Response;

Expand Down Expand Up @@ -521,12 +522,6 @@ function pickParam({
if (name in params) {
return params[name];
}
const searchParams = new URLSearchParams(url.split('?')[1]);
if (searchParams.has(name)) {
const values = searchParams.getAll(name);
return values.length === 1 ? values[0] : values;
}
if (body && body.hasOwnProperty(name)) {
return body[name];
}
const searchParams = qsParse(url.split('?')[1]);
return searchParams[name] || body[name];
}
62 changes: 56 additions & 6 deletions tests/router.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,56 @@ test('should work with Query and variables', async () => {
expect((spy.mock.calls[0] as any[])[1]).toEqual({ id: 'test-id' });
});

test('should work with input objects in URL params via GET', async () => {
const testUser = {
id: 'test-id',
name: 'Test User',
};
const spy = jest.fn(() => [testUser]);
const sofa = useSofa({
basePath: '/api',
schema: createSchema({
typeDefs: /* GraphQL */ `
type User {
id: ID
name: String
}
input UserFilterNestedInput {
id: ID!
}
input UserFilterInput {
nested: UserFilterNestedInput!
}
type Query {
users(where: UserFilterInput!): [User!]!
}
`,
resolvers: {
Query: {
users: spy,
},
},
}),
});

const res = await sofa.fetch(
'http://localhost:4000/api/users?where={"nested":{"id":"test-id"}}'
);
expect(res.status).toBe(200);
const resBody = await res.json();
expect(resBody).toEqual([testUser]);
expect((spy.mock.calls[0] as any[])[1]).toEqual({
where: {
nested: {
id: testUser.id,
},
},
});
});

test('should work with Mutation', async () => {
const pizza = { dough: 'dough', toppings: ['topping'] };
const spy = jest.fn(() => ({ __typename: 'Pizza', ...pizza }));
Expand Down Expand Up @@ -333,7 +383,7 @@ test('should return errors as json', async () => {
message: 'permission denied',
path: ['foo'],
extensions: { code: 'PERMISSION_DENIED' },
}
},
],
});
});
Expand Down Expand Up @@ -414,7 +464,7 @@ test('should respect http error extensions', async () => {
extensions: {
code: 'PERMISSION_DENIED',
},
}
},
],
});
});
Expand Down Expand Up @@ -514,19 +564,19 @@ test('primitive true boolean in requests should be handled as true', async () =>
// }),
// onRoute: spy,
// routes: {
// 'Query.foo': { description: 'this is overwrited query description' },
// 'Query.foo': { description: 'this is overwritten query description' },
// 'Mutation.bar': {
// description: 'this is overwrited mutation description',
// description: 'this is overwritten mutation description',
// },
// },
// });

// expect(spy).toBeCalledTimes(2);
// expect(spy.mock.calls[0][0].description).toEqual(
// 'this is overwrited query description'
// 'this is overwritten query description'
// );
// expect(spy.mock.calls[1][0].description).toEqual(
// 'this is overwrited mutation description'
// 'this is overwritten mutation description'
// );
// });

Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,11 @@
resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz"
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==

"@types/[email protected]":
version "6.9.10"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8"
integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==

"@types/range-parser@*":
version "1.2.4"
resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz"
Expand Down

0 comments on commit 028af74

Please sign in to comment.