244 lines
7.1 KiB
JavaScript
Raw Normal View History

2021-09-02 11:25:24 +02:00
'use strict';
const _ = require('lodash');
const getSchemaData = require('./get-schema-data');
const pascalCase = require('./pascal-case');
2021-09-02 11:25:24 +02:00
/**
2022-03-17 16:54:37 +01:00
* @description - Converts types found on attributes to OpenAPI acceptable data types
*
2021-09-02 11:25:24 +02:00
* @param {object} attributes - The attributes found on a contentType
2023-03-09 11:38:01 +05:30
* @param {{ typeMap: Map, isRequest: boolean, didAddStrapiComponentsToSchemas: function, componentSchemaRefName: string }} opts
2021-09-02 11:25:24 +02:00
* @returns Attributes using OpenAPI acceptable data types
*/
2022-06-30 13:01:19 +02:00
const cleanSchemaAttributes = (
attributes,
2022-08-23 15:58:05 +02:00
{
typeMap = new Map(),
isRequest = false,
2023-03-09 11:38:01 +05:30
didAddStrapiComponentsToSchemas = () => {},
2022-08-23 15:58:05 +02:00
componentSchemaRefName = '',
} = {}
2022-06-30 13:01:19 +02:00
) => {
2021-09-02 11:25:24 +02:00
const attributesCopy = _.cloneDeep(attributes);
2022-08-08 23:33:39 +02:00
for (const prop of Object.keys(attributesCopy)) {
2021-09-02 11:25:24 +02:00
const attribute = attributesCopy[prop];
if (attribute.default) {
delete attributesCopy[prop].default;
}
switch (attribute.type) {
2021-10-19 10:55:11 +02:00
case 'password': {
if (!isRequest) {
delete attributesCopy[prop];
break;
}
attributesCopy[prop] = { type: 'string', format: 'password', example: '*******' };
break;
}
case 'email': {
attributesCopy[prop] = { type: 'string', format: 'email' };
break;
}
case 'string':
2021-10-13 12:39:34 -04:00
case 'text':
2021-10-19 10:55:11 +02:00
case 'richtext': {
2021-09-02 11:25:24 +02:00
attributesCopy[prop] = { type: 'string' };
break;
}
2021-10-19 10:55:11 +02:00
case 'timestamp': {
attributesCopy[prop] = { type: 'string', format: 'timestamp', example: Date.now() };
break;
}
case 'time': {
attributesCopy[prop] = { type: 'string', format: 'time', example: '12:54.000' };
break;
}
case 'date': {
attributesCopy[prop] = { type: 'string', format: 'date' };
break;
}
case 'datetime': {
attributesCopy[prop] = { type: 'string', format: 'date-time' };
break;
}
case 'boolean': {
attributesCopy[prop] = { type: 'boolean' };
break;
}
case 'enumeration': {
attributesCopy[prop] = { type: 'string', enum: attribute.enum };
break;
}
2021-10-13 12:39:34 -04:00
case 'decimal':
case 'float': {
2021-09-02 11:25:24 +02:00
attributesCopy[prop] = { type: 'number', format: 'float' };
break;
}
case 'integer': {
attributesCopy[prop] = { type: 'integer' };
break;
}
2021-10-19 10:55:11 +02:00
case 'biginteger': {
attributesCopy[prop] = { type: 'string', pattern: '^\\d*$', example: '123456789' };
break;
}
2021-09-02 11:25:24 +02:00
case 'json': {
attributesCopy[prop] = {};
break;
}
case 'uid': {
2021-10-19 10:55:11 +02:00
attributesCopy[prop] = { type: 'string' };
2021-09-02 11:25:24 +02:00
break;
}
case 'component': {
const componentAttributes = strapi.components[attribute.component].attributes;
2022-06-30 13:01:19 +02:00
const rawComponentSchema = {
type: 'object',
properties: {
2022-09-06 05:35:56 +00:00
...(isRequest ? {} : { id: { type: 'number' } }),
2022-06-30 13:01:19 +02:00
...cleanSchemaAttributes(componentAttributes, {
typeMap,
isRequest,
}),
},
};
const refComponentSchema = {
$ref: `#/components/schemas/${pascalCase(attribute.component)}Component`,
2022-06-30 13:01:19 +02:00
};
2023-03-09 11:38:01 +05:30
const componentExists = didAddStrapiComponentsToSchemas(
2022-06-30 13:01:19 +02:00
`${pascalCase(attribute.component)}Component`,
rawComponentSchema
);
const finalComponentSchema = componentExists ? refComponentSchema : rawComponentSchema;
2021-10-13 12:39:34 -04:00
if (attribute.repeatable) {
attributesCopy[prop] = {
type: 'array',
2022-06-30 13:01:19 +02:00
items: finalComponentSchema,
2021-10-13 12:39:34 -04:00
};
} else {
2022-06-30 13:01:19 +02:00
attributesCopy[prop] = finalComponentSchema;
}
break;
}
case 'dynamiczone': {
2022-08-08 23:33:39 +02:00
const components = attribute.components.map((component) => {
const componentAttributes = strapi.components[component].attributes;
2022-06-30 13:01:19 +02:00
const rawComponentSchema = {
type: 'object',
properties: {
2022-08-31 10:37:08 +00:00
...(isRequest ? {} : { id: { type: 'number' } }),
__component: { type: 'string' },
2022-08-23 15:58:05 +02:00
...cleanSchemaAttributes(componentAttributes, {
typeMap,
isRequest,
2023-03-09 11:38:01 +05:30
didAddStrapiComponentsToSchemas,
2022-08-23 15:58:05 +02:00
}),
2021-10-13 12:39:34 -04:00
},
};
2023-03-14 11:10:55 +01:00
const refComponentSchema = {
$ref: `#/components/schemas/${pascalCase(component)}Component`,
};
2023-03-09 11:38:01 +05:30
const componentExists = didAddStrapiComponentsToSchemas(
2023-03-14 11:10:55 +01:00
`${pascalCase(component)}Component`,
2023-03-09 11:38:01 +05:30
rawComponentSchema
);
2022-06-30 13:01:19 +02:00
const finalComponentSchema = componentExists ? refComponentSchema : rawComponentSchema;
return finalComponentSchema;
});
attributesCopy[prop] = {
type: 'array',
items: {
anyOf: components,
},
};
break;
}
case 'media': {
const imageAttributes = strapi.contentType('plugin::upload.file').attributes;
const isListOfEntities = attribute.multiple;
if (isRequest) {
const oneOfType = {
oneOf: [{ type: 'integer' }, { type: 'string' }],
example: 'string or id',
};
attributesCopy[prop] = isListOfEntities ? { type: 'array', items: oneOfType } : oneOfType;
break;
2021-10-13 12:39:34 -04:00
}
attributesCopy[prop] = {
type: 'object',
properties: {
2023-03-14 11:10:55 +01:00
data: getSchemaData(
isListOfEntities,
cleanSchemaAttributes(imageAttributes, { typeMap })
),
},
};
2021-09-02 11:25:24 +02:00
break;
}
2021-09-02 11:25:24 +02:00
case 'relation': {
const isListOfEntities = attribute.relation.includes('ToMany');
if (isRequest) {
const oneOfType = {
oneOf: [{ type: 'integer' }, { type: 'string' }],
example: 'string or id',
};
attributesCopy[prop] = isListOfEntities ? { type: 'array', items: oneOfType } : oneOfType;
break;
}
2022-05-05 12:32:22 +02:00
if (prop === 'localizations') {
attributesCopy[prop] = {
type: 'object',
2022-06-30 13:01:19 +02:00
properties: {
data: {
type: 'array',
items: componentSchemaRefName.length ? { $ref: componentSchemaRefName } : {},
},
},
2022-05-05 12:32:22 +02:00
};
break;
}
if (!attribute.target || typeMap.has(attribute.target)) {
attributesCopy[prop] = {
type: 'object',
properties: { data: getSchemaData(isListOfEntities, {}) },
};
break;
}
typeMap.set(attribute.target, true);
const targetAttributes = strapi.contentType(attribute.target).attributes;
2021-09-02 11:25:24 +02:00
attributesCopy[prop] = {
type: 'object',
properties: {
data: getSchemaData(
isListOfEntities,
cleanSchemaAttributes(targetAttributes, { typeMap, isRequest })
),
2021-09-02 11:25:24 +02:00
},
};
break;
}
default: {
throw new Error(`Invalid type ${attribute.type} while generating open api schema.`);
2021-10-13 12:39:34 -04:00
}
2021-09-02 11:25:24 +02:00
}
}
return attributesCopy;
};
module.exports = cleanSchemaAttributes;