Skip to content

Commit 7b4bb82

Browse files
committed
graphql-language-service: Support single-item coercion for lists
1 parent 0d9e51a commit 7b4bb82

File tree

3 files changed

+78
-35
lines changed

3 files changed

+78
-35
lines changed

.changeset/metal-mice-relate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphql-language-service': minor
3+
---
4+
5+
getJSONSchemaFromGraphQLType: Support single-item coercion for lists

packages/graphql-language-service/src/utils/__tests__/getVariablesJSONSchema.test.ts

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,25 @@ describe('getVariablesJSONSchema', () => {
301301
description: 'nesting a whole object!\n\nChildInputType!',
302302
},
303303
exampleList: {
304-
type: ['array', 'null'],
305-
items: {
306-
description: 'ChildInputType',
307-
oneOf: [
308-
{ $ref: '#/definitions/ChildInputType' },
309-
{ type: 'null' },
310-
],
311-
},
304+
anyOf: [
305+
{
306+
description: 'ChildInputType',
307+
oneOf: [
308+
{ $ref: '#/definitions/ChildInputType' },
309+
{ type: 'null' },
310+
],
311+
},
312+
{
313+
type: ['array', 'null'],
314+
items: {
315+
description: 'ChildInputType',
316+
oneOf: [
317+
{ $ref: '#/definitions/ChildInputType' },
318+
{ type: 'null' },
319+
],
320+
},
321+
},
322+
],
312323
description: 'list type with default\n\n[ChildInputType]',
313324
default: [
314325
{
@@ -318,12 +329,20 @@ describe('getVariablesJSONSchema', () => {
318329
],
319330
},
320331
exampleScalarList: {
321-
type: 'array',
322332
description: '[String]!',
323-
items: {
324-
type: ['string', 'null'],
325-
description: 'String',
326-
},
333+
anyOf: [
334+
{
335+
type: ['string', 'null'],
336+
description: 'String',
337+
},
338+
{
339+
type: 'array',
340+
items: {
341+
type: ['string', 'null'],
342+
description: 'String',
343+
},
344+
},
345+
],
327346
default: ['something'],
328347
},
329348
},
@@ -414,15 +433,27 @@ describe('getVariablesJSONSchema', () => {
414433
$ref: '#/definitions/ChildInputType',
415434
},
416435
exampleList: {
417-
type: ['array', 'null'],
418-
items: {
419-
description: 'ChildInputType',
420-
markdownDescription: '```graphql\nChildInputType\n```',
421-
oneOf: [
422-
{ $ref: '#/definitions/ChildInputType' },
423-
{ type: 'null' },
424-
],
425-
},
436+
anyOf: [
437+
{
438+
description: 'ChildInputType',
439+
markdownDescription: '```graphql\nChildInputType\n```',
440+
oneOf: [
441+
{ $ref: '#/definitions/ChildInputType' },
442+
{ type: 'null' },
443+
],
444+
},
445+
{
446+
type: ['array', 'null'],
447+
items: {
448+
description: 'ChildInputType',
449+
markdownDescription: '```graphql\nChildInputType\n```',
450+
oneOf: [
451+
{ $ref: '#/definitions/ChildInputType' },
452+
{ type: 'null' },
453+
],
454+
},
455+
},
456+
],
426457
description: 'list type with default\n\n[ChildInputType]',
427458
markdownDescription: `list type with default\n\n${mdTicks(
428459
'[ChildInputType]',
@@ -435,14 +466,23 @@ describe('getVariablesJSONSchema', () => {
435466
],
436467
},
437468
exampleScalarList: {
438-
type: 'array',
439469
description: '[String]!',
440470
markdownDescription: mdTicks('[String]!'),
441-
items: {
442-
type: ['string', 'null'],
443-
description: 'String',
444-
markdownDescription: mdTicks('String'),
445-
},
471+
anyOf: [
472+
{
473+
type: ['string', 'null'],
474+
description: 'String',
475+
markdownDescription: mdTicks('String'),
476+
},
477+
{
478+
type: 'array',
479+
items: {
480+
type: ['string', 'null'],
481+
description: 'String',
482+
markdownDescription: mdTicks('String'),
483+
},
484+
},
485+
],
446486
default: ['something'],
447487
},
448488
},

packages/graphql-language-service/src/utils/getVariablesJSONSchema.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,16 @@ function getJSONSchemaFromGraphQLType(
216216
definition.enum.push(null);
217217
}
218218
} else if (isListType(baseType)) {
219-
if (required) {
220-
definition.type = 'array';
221-
} else {
222-
definition.type = ['array', 'null'];
223-
}
224-
225219
const { definition: def, definitions: defs } = getJSONSchemaFromGraphQLType(
226220
baseType.ofType,
227221
options,
228222
);
229223

230-
definition.items = def;
224+
// The GraphQL spec allows for passing a single list item as a list
225+
definition.anyOf = [
226+
def,
227+
{ type: required ? 'array' : ['array', 'null'], items: def },
228+
];
231229

232230
if (defs) {
233231
for (const defName of Object.keys(defs)) {

0 commit comments

Comments
 (0)