Skip to content

Commit 82aeae1

Browse files
eokoneyoAlan-Cha
authored andcommitted
adds support for OAS query parameter serialization expection for generated http requests
Signed-off-by: Eyo O. Eyo <[email protected]>
1 parent 82dc653 commit 82aeae1

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

packages/openapi-to-graphql/src/resolver_builder.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1360,7 +1360,23 @@ export function extractRequestDataFromArgs<TSource, TContext, TArgs>(
13601360

13611361
// Query parameters
13621362
case 'query':
1363-
qs[param.name] = args[saneParamName]
1363+
// setting param style as form assumes explode is true by default
1364+
if (param.style === 'form' && Object.prototype.toString.call(args[saneParamName]) === '[object Object]') {
1365+
if (param.explode === false) {
1366+
qs[param.name] = Object.entries(args[saneParamName]).reduce((acc, val) => {
1367+
acc += val.join(',')
1368+
return acc
1369+
}, '')
1370+
} else {
1371+
Object.entries(args[saneParamName]).forEach(([key, value]) => {
1372+
qs[key] = value
1373+
})
1374+
}
1375+
} else if (Array.isArray(args[saneParamName]) && param.style === 'form' && param.explode !== false) {
1376+
qs[param.name] = args[saneParamName].join(',')
1377+
} else {
1378+
qs[param.name] = args[saneParamName]
1379+
}
13641380
break
13651381

13661382
// Header parameters

packages/openapi-to-graphql/test/example_api.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,3 +2411,32 @@ test('Non-nullable properties from nested allOf', () => {
24112411
})
24122412
})
24132413
})
2414+
2415+
test('it formats the request url appropriate when style and explode is set to true', async () => {
2416+
const LIMIT = 10
2417+
const OFFSET = 0
2418+
2419+
const query = `
2420+
query {
2421+
fetchAllOfficesWithFormStyleAndExplodeTrue(parameters: { limit: ${LIMIT}, offset: ${OFFSET} }) {
2422+
roomNumber
2423+
company {
2424+
id
2425+
}
2426+
}
2427+
}
2428+
`
2429+
2430+
await graphql(createdSchema, query).then((result) => {
2431+
// target error field because the corresponding server url is not implemented,
2432+
// also we get the full request url as in failed request errors
2433+
result.errors.forEach((error) => {
2434+
const url = new URL(error.extensions.url)
2435+
2436+
expect(url.searchParams.has('limit')).toBe(true)
2437+
expect(url.searchParams.get('limit')).toBe(String(LIMIT))
2438+
expect(url.searchParams.has('offset')).toBe(true)
2439+
expect(url.searchParams.get('offset')).toBe(String(OFFSET))
2440+
})
2441+
})
2442+
})

packages/openapi-to-graphql/test/fixtures/example_oas.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,46 @@
471471
}
472472
}
473473
},
474+
"/offices": {
475+
"get": {
476+
"x-graphql-field-name": "fetchAllOfficesWithFormStyleAndExplodeTrue",
477+
"operationId": "returnAllOffices",
478+
"description": "returns all offices",
479+
"parameters": [{
480+
"name": "parameters",
481+
"in": "query",
482+
"required": true,
483+
"style": "form",
484+
"explode": true,
485+
"schema": {
486+
"type": "object",
487+
"properties": {
488+
"limit": {
489+
"type": "integer"
490+
},
491+
"offset": {
492+
"type": "integer"
493+
}
494+
}
495+
}
496+
}],
497+
"responses": {
498+
"200": {
499+
"description": "A list of users.",
500+
"content": {
501+
"application/json": {
502+
"schema": {
503+
"type": "array",
504+
"items": {
505+
"$ref": "#/components/schemas/office"
506+
}
507+
}
508+
}
509+
}
510+
}
511+
}
512+
}
513+
},
474514
"/offices/{id}": {
475515
"get": {
476516
"operationId": "getOffice",

0 commit comments

Comments
 (0)