diff --git a/.changeset/metal-mice-relate.md b/.changeset/metal-mice-relate.md new file mode 100644 index 00000000000..b9a9f6a2921 --- /dev/null +++ b/.changeset/metal-mice-relate.md @@ -0,0 +1,5 @@ +--- +'graphql-language-service': minor +--- + +getJSONSchemaFromGraphQLType: Support single-item coercion for lists diff --git a/packages/graphql-language-service/src/utils/__tests__/getVariablesJSONSchema.test.ts b/packages/graphql-language-service/src/utils/__tests__/getVariablesJSONSchema.test.ts index 7679e37ad90..575122582f2 100644 --- a/packages/graphql-language-service/src/utils/__tests__/getVariablesJSONSchema.test.ts +++ b/packages/graphql-language-service/src/utils/__tests__/getVariablesJSONSchema.test.ts @@ -301,14 +301,25 @@ describe('getVariablesJSONSchema', () => { description: 'nesting a whole object!\n\nChildInputType!', }, exampleList: { - type: ['array', 'null'], - items: { - description: 'ChildInputType', - oneOf: [ - { $ref: '#/definitions/ChildInputType' }, - { type: 'null' }, - ], - }, + anyOf: [ + { + description: 'ChildInputType', + oneOf: [ + { $ref: '#/definitions/ChildInputType' }, + { type: 'null' }, + ], + }, + { + type: ['array', 'null'], + items: { + description: 'ChildInputType', + oneOf: [ + { $ref: '#/definitions/ChildInputType' }, + { type: 'null' }, + ], + }, + }, + ], description: 'list type with default\n\n[ChildInputType]', default: [ { @@ -318,12 +329,20 @@ describe('getVariablesJSONSchema', () => { ], }, exampleScalarList: { - type: 'array', description: '[String]!', - items: { - type: ['string', 'null'], - description: 'String', - }, + anyOf: [ + { + type: ['string', 'null'], + description: 'String', + }, + { + type: 'array', + items: { + type: ['string', 'null'], + description: 'String', + }, + }, + ], default: ['something'], }, }, @@ -414,15 +433,27 @@ describe('getVariablesJSONSchema', () => { $ref: '#/definitions/ChildInputType', }, exampleList: { - type: ['array', 'null'], - items: { - description: 'ChildInputType', - markdownDescription: '```graphql\nChildInputType\n```', - oneOf: [ - { $ref: '#/definitions/ChildInputType' }, - { type: 'null' }, - ], - }, + anyOf: [ + { + description: 'ChildInputType', + markdownDescription: '```graphql\nChildInputType\n```', + oneOf: [ + { $ref: '#/definitions/ChildInputType' }, + { type: 'null' }, + ], + }, + { + type: ['array', 'null'], + items: { + description: 'ChildInputType', + markdownDescription: '```graphql\nChildInputType\n```', + oneOf: [ + { $ref: '#/definitions/ChildInputType' }, + { type: 'null' }, + ], + }, + }, + ], description: 'list type with default\n\n[ChildInputType]', markdownDescription: `list type with default\n\n${mdTicks( '[ChildInputType]', @@ -435,14 +466,23 @@ describe('getVariablesJSONSchema', () => { ], }, exampleScalarList: { - type: 'array', description: '[String]!', markdownDescription: mdTicks('[String]!'), - items: { - type: ['string', 'null'], - description: 'String', - markdownDescription: mdTicks('String'), - }, + anyOf: [ + { + type: ['string', 'null'], + description: 'String', + markdownDescription: mdTicks('String'), + }, + { + type: 'array', + items: { + type: ['string', 'null'], + description: 'String', + markdownDescription: mdTicks('String'), + }, + }, + ], default: ['something'], }, }, diff --git a/packages/graphql-language-service/src/utils/getVariablesJSONSchema.ts b/packages/graphql-language-service/src/utils/getVariablesJSONSchema.ts index 7aa77c66cdd..46ccb8c8a44 100644 --- a/packages/graphql-language-service/src/utils/getVariablesJSONSchema.ts +++ b/packages/graphql-language-service/src/utils/getVariablesJSONSchema.ts @@ -216,18 +216,16 @@ function getJSONSchemaFromGraphQLType( definition.enum.push(null); } } else if (isListType(baseType)) { - if (required) { - definition.type = 'array'; - } else { - definition.type = ['array', 'null']; - } - const { definition: def, definitions: defs } = getJSONSchemaFromGraphQLType( baseType.ofType, options, ); - definition.items = def; + // The GraphQL spec allows for passing a single list item as a list + definition.anyOf = [ + def, + { type: required ? 'array' : ['array', 'null'], items: def }, + ]; if (defs) { for (const defName of Object.keys(defs)) {