fix: type generation for block fields with no blocks (#7765)

This commit is contained in:
Paul
2024-08-19 16:34:19 -06:00
committed by GitHub
parent ebd43c7763
commit 0c36cbde73
2 changed files with 168 additions and 30 deletions

View File

@@ -62,6 +62,137 @@ describe('configToJSONSchema', () => {
}) })
}) })
it('should handle block fields with no blocks', async () => {
// @ts-expect-error
const config: Config = {
collections: [
{
slug: 'test',
fields: [
{
name: 'blockField',
type: 'blocks',
blocks: [],
},
{
name: 'blockFieldRequired',
type: 'blocks',
blocks: [],
required: true,
},
{
name: 'blockFieldWithFields',
type: 'blocks',
blocks: [
{
slug: 'test',
fields: [
{
name: 'field',
type: 'text',
},
],
},
],
},
{
name: 'blockFieldWithFieldsRequired',
type: 'blocks',
blocks: [
{
slug: 'test',
fields: [
{
name: 'field',
type: 'text',
required: true,
},
],
},
],
},
],
timestamps: false,
},
],
}
const sanitizedConfig = await sanitizeConfig(config)
const schema = configToJSONSchema(sanitizedConfig, 'text')
expect(schema?.definitions?.test).toStrictEqual({
type: 'object',
additionalProperties: false,
properties: {
id: {
type: 'string',
},
blockField: {
type: ['array', 'null'],
items: {},
},
blockFieldRequired: {
type: 'array',
items: {},
},
blockFieldWithFields: {
type: ['array', 'null'],
items: {
oneOf: [
{
type: 'object',
additionalProperties: false,
properties: {
id: {
type: ['string', 'null'],
},
blockName: {
type: ['string', 'null'],
},
blockType: {
const: 'test',
},
field: {
type: ['string', 'null'],
},
},
required: ['blockType'],
},
],
},
},
blockFieldWithFieldsRequired: {
type: ['array', 'null'],
items: {
oneOf: [
{
type: 'object',
additionalProperties: false,
properties: {
id: {
type: ['string', 'null'],
},
blockName: {
type: ['string', 'null'],
},
blockType: {
const: 'test',
},
field: {
type: 'string',
},
},
required: ['blockType', 'field'],
},
],
},
},
},
required: ['id', 'blockFieldRequired'],
title: 'Test',
})
})
it('should handle tabs and named tabs with required fields', async () => { it('should handle tabs and named tabs with required fields', async () => {
// @ts-expect-error // @ts-expect-error
const config: Config = { const config: Config = {

View File

@@ -396,40 +396,47 @@ export function fieldsToJSONSchema(
} }
case 'blocks': { case 'blocks': {
// Check for a case where no blocks are provided.
// We need to generate an empty array for this case, note that JSON schema 4 doesn't support empty arrays
// so the best we can get is `unknown[]`
const hasBlocks = Boolean(field.blocks.length)
fieldSchema = { fieldSchema = {
type: withNullableJSONSchemaType('array', isRequired), type: withNullableJSONSchemaType('array', isRequired),
items: { items: hasBlocks
oneOf: field.blocks.map((block) => { ? {
const blockFieldSchemas = fieldsToJSONSchema( oneOf: field.blocks.map((block) => {
collectionIDFieldTypes, const blockFieldSchemas = fieldsToJSONSchema(
block.fields, collectionIDFieldTypes,
interfaceNameDefinitions, block.fields,
config, interfaceNameDefinitions,
) config,
)
const blockSchema: JSONSchema4 = { const blockSchema: JSONSchema4 = {
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
properties: { properties: {
...blockFieldSchemas.properties, ...blockFieldSchemas.properties,
blockType: { blockType: {
const: block.slug, const: block.slug,
}, },
}, },
required: ['blockType', ...blockFieldSchemas.required], required: ['blockType', ...blockFieldSchemas.required],
}
if (block.interfaceName) {
interfaceNameDefinitions.set(block.interfaceName, blockSchema)
return {
$ref: `#/definitions/${block.interfaceName}`,
}
}
return blockSchema
}),
} }
: {},
if (block.interfaceName) {
interfaceNameDefinitions.set(block.interfaceName, blockSchema)
return {
$ref: `#/definitions/${block.interfaceName}`,
}
}
return blockSchema
}),
},
} }
break break
} }