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 () => {
|
it('should handle tabs and named tabs with required fields', async () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user