Skip to content

Commit 87cda81

Browse files
Alan-ChaErikWittern
authored andcommitted
Fix input object type, no properties object schema
Fix #219 Signed-off-by: Alan Cha <[email protected]>
1 parent bf4f03b commit 87cda81

File tree

8 files changed

+142
-10
lines changed

8 files changed

+142
-10
lines changed

packages/openapi-to-graphql/lib/oas_3_tools.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/oas_3_tools.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/schema_builder.js

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/lib/schema_builder.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ function createOrReuseOt({
229229
typeof schema.description !== 'undefined'
230230
? schema.description
231231
: 'No description available.'
232+
232233
def.ot = new GraphQLObjectType({
233234
name: def.otName,
234235
description,
@@ -248,7 +249,7 @@ function createOrReuseOt({
248249
}
249250
// CASE: mutation - create or reuse IOT
250251
} else {
251-
if (typeof def.iot !== 'undefined') {
252+
if (def.iot && typeof def.iot !== 'undefined') {
252253
translationLog(
253254
`Reuse Input Object Type '${def.iotName}'` +
254255
(typeof operation === 'object'
@@ -264,6 +265,28 @@ function createOrReuseOt({
264265
: '')
265266
)
266267

268+
/**
269+
* If the schema does not contain any properties, then OpenAPI-to-GraphQL
270+
* cannot create a GraphQL Object Type for it because in GraphQL, all Object
271+
* Type properties must be named.
272+
*
273+
* Instead, store response in an arbitray JSON type.
274+
*/
275+
if (typeof def.schema.properties === 'undefined') {
276+
handleWarning({
277+
typeKey: 'OBJECT_MISSING_PROPERTIES',
278+
message:
279+
`The operation ` +
280+
`'${operation.operationString}' contains ` +
281+
`a object schema ${JSON.stringify(def)} with no properties. ` +
282+
`GraphQL objects must have well-defined properties so a one to ` +
283+
`one conversion cannot be achieved.`,
284+
data,
285+
log: translationLog
286+
})
287+
return GraphQLJSON
288+
}
289+
267290
schema.description =
268291
typeof schema.description !== 'undefined'
269292
? schema.description

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,13 +1260,14 @@ test('Content property in parameter object', () => {
12601260
})
12611261
})
12621262

1263+
// TODO: Change trashcans2 to trashcans
12631264
test('Handle objects without defined properties with arbitrary GraphQL JSON type', () => {
12641265
const query = `{
12651266
trashcan(username:"arlene") {
12661267
brand,
12671268
contents
12681269
}
1269-
trashcans {
1270+
trashcans2 {
12701271
contents
12711272
}
12721273
}`
@@ -1286,7 +1287,7 @@ test('Handle objects without defined properties with arbitrary GraphQL JSON type
12861287
}
12871288
]
12881289
},
1289-
trashcans: [
1290+
trashcans2: [
12901291
{
12911292
contents: [
12921293
{
@@ -1324,6 +1325,43 @@ test('Handle objects without defined properties with arbitrary GraphQL JSON type
13241325
})
13251326
})
13261327

1328+
test('Handle input objects without defined properties with arbitrary GraphQL JSON type', () => {
1329+
const query = `mutation {
1330+
postOfficeTrashCan(trashcansInput: {
1331+
type: "sandwich",
1332+
message: "moldy",
1333+
tasteRating: 0
1334+
}, username: "arlene") {
1335+
brand
1336+
contents
1337+
}
1338+
}`
1339+
return graphql(createdSchema, query).then(result => {
1340+
expect(result).toEqual({
1341+
data: {
1342+
postOfficeTrashCan: {
1343+
brand: 'Garbage Emporium',
1344+
contents: [
1345+
{
1346+
type: 'apple',
1347+
message: 'Half-eaten'
1348+
},
1349+
{
1350+
type: 'sock',
1351+
message: 'Lost one'
1352+
},
1353+
{
1354+
type: 'sandwich',
1355+
message: 'moldy',
1356+
tasteRating: 0
1357+
}
1358+
]
1359+
}
1360+
}
1361+
})
1362+
})
1363+
})
1364+
13271365
test('Generate "Equivalent to..." messages', () => {
13281366
const options: Options = {
13291367
// Used to simplify test. Otherwise viewers will polute query/mutation fields.

packages/openapi-to-graphql/test/example_api_server.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ function startServer(PORT) {
231231
}
232232
}
233233

234-
const Trash = {
234+
const TrashCans = {
235235
arlene: {
236236
brand: 'Garbage Emporium',
237237
contents: [
@@ -673,13 +673,28 @@ function startServer(PORT) {
673673

674674
app.get('/api/trashcans', (req, res) => {
675675
console.log(req.method, req.path)
676-
res.send(Array.from(Object.values(Trash)))
676+
res.send(Array.from(Object.values(TrashCans)))
677677
})
678678

679679
app.get('/api/trashcans/:username', (req, res) => {
680680
console.log(req.method, req.path)
681681
if (req.params.username in Users) {
682-
res.send(Trash[req.params.username])
682+
res.send(TrashCans[req.params.username])
683+
} else {
684+
res.status(404).send({
685+
message: 'Wrong username.'
686+
})
687+
}
688+
})
689+
690+
app.post('/api/trashcans/:username', (req, res) => {
691+
console.log(req.method, req.path)
692+
const trashItem = req.body
693+
694+
if (req.params.username in Users) {
695+
const trashCan = TrashCans[req.params.username]
696+
trashCan.contents.push(trashItem)
697+
res.send(TrashCans[req.params.username])
683698
} else {
684699
res.status(404).send({
685700
message: 'Wrong username.'

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,42 @@
924924
}
925925
}
926926
}
927+
},
928+
"post": {
929+
"operationId": "postOfficeTrashCan",
930+
"description": "Add new contents to the trashcan of a specific owner",
931+
"parameters": [
932+
{
933+
"name": "username",
934+
"in": "path",
935+
"required": true,
936+
"schema": {
937+
"type": "string"
938+
},
939+
"description": "Identifier of a user."
940+
}
941+
],
942+
"requestBody": {
943+
"content": {
944+
"application/json": {
945+
"schema": {
946+
"type": "object"
947+
}
948+
}
949+
}
950+
},
951+
"responses": {
952+
"200": {
953+
"description": "A trashcan",
954+
"content": {
955+
"application/json": {
956+
"schema": {
957+
"$ref": "#/components/schemas/trashcan"
958+
}
959+
}
960+
}
961+
}
962+
}
927963
}
928964
},
929965
"/trashcans": {

0 commit comments

Comments
 (0)