fix: type generation for block fields with no blocks (#7765)
This commit is contained in:
@@ -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 () => {
|
||||
// @ts-expect-error
|
||||
const config: Config = {
|
||||
|
||||
@@ -396,40 +396,47 @@ export function fieldsToJSONSchema(
|
||||
}
|
||||
|
||||
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 = {
|
||||
type: withNullableJSONSchemaType('array', isRequired),
|
||||
items: {
|
||||
oneOf: field.blocks.map((block) => {
|
||||
const blockFieldSchemas = fieldsToJSONSchema(
|
||||
collectionIDFieldTypes,
|
||||
block.fields,
|
||||
interfaceNameDefinitions,
|
||||
config,
|
||||
)
|
||||
items: hasBlocks
|
||||
? {
|
||||
oneOf: field.blocks.map((block) => {
|
||||
const blockFieldSchemas = fieldsToJSONSchema(
|
||||
collectionIDFieldTypes,
|
||||
block.fields,
|
||||
interfaceNameDefinitions,
|
||||
config,
|
||||
)
|
||||
|
||||
const blockSchema: JSONSchema4 = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
...blockFieldSchemas.properties,
|
||||
blockType: {
|
||||
const: block.slug,
|
||||
},
|
||||
},
|
||||
required: ['blockType', ...blockFieldSchemas.required],
|
||||
const blockSchema: JSONSchema4 = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
...blockFieldSchemas.properties,
|
||||
blockType: {
|
||||
const: block.slug,
|
||||
},
|
||||
},
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user