mirror of
https://github.com/strapi/strapi.git
synced 2025-07-06 08:31:30 +00:00
132 lines
4.0 KiB
JavaScript
132 lines
4.0 KiB
JavaScript
![]() |
'use strict';
|
||
|
|
||
|
const _ = require('lodash');
|
||
|
const pathToRegexp = require('path-to-regexp');
|
||
|
|
||
|
const queryParams = require('../query-params');
|
||
|
const buildApiRequests = require('./build-api-requests');
|
||
|
const buildApiResponses = require('./build-api-responses');
|
||
|
|
||
|
/**
|
||
|
* @description Parses a route with ':variable'
|
||
|
*
|
||
|
* @param {string} routePath - The route's path property
|
||
|
* @returns '{variable}'
|
||
|
*/
|
||
|
const parsePathWithVariables = routePath => {
|
||
|
return pathToRegexp
|
||
|
.parse(routePath)
|
||
|
.map(token => {
|
||
|
if (_.isObject(token)) {
|
||
|
return token.prefix + '{' + token.name + '}';
|
||
|
}
|
||
|
|
||
|
return token;
|
||
|
})
|
||
|
.join('');
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @description Builds the required object for a path parameter
|
||
|
*
|
||
|
* @param {string} routePath - The route's path property
|
||
|
*
|
||
|
* @returns Swagger path params object
|
||
|
*/
|
||
|
const getPathParams = routePath => {
|
||
|
return pathToRegexp
|
||
|
.parse(routePath)
|
||
|
.filter(token => _.isObject(token))
|
||
|
.map(param => {
|
||
|
return {
|
||
|
name: param.name,
|
||
|
in: 'path',
|
||
|
description: '',
|
||
|
deprecated: false,
|
||
|
required: true,
|
||
|
schema: { type: 'string' },
|
||
|
};
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {array} routes - The routes for a given api or plugin
|
||
|
* @param {object} attributes - The attributes for a given api or plugin
|
||
|
* @param {string} tag - A descriptor for OpenAPI
|
||
|
*
|
||
|
* @returns object of OpenAPI paths for each route
|
||
|
*/
|
||
|
const getPaths = (routes, attributes, tag) => {
|
||
|
const paths = routes.reduce(
|
||
|
(acc, route) => {
|
||
|
// TODO: Find a more reliable way to determine list of entities vs a single entity
|
||
|
const isListOfEntities = route.handler.split('.').pop() === 'find';
|
||
|
const hasPathParams = route.path.includes('/:');
|
||
|
const methodVerb = route.method.toLowerCase();
|
||
|
const routePath = hasPathParams ? parsePathWithVariables(route.path) : route.path;
|
||
|
|
||
|
const { responses } = buildApiResponses(attributes, route, isListOfEntities);
|
||
|
_.set(acc.paths, `${routePath}.${methodVerb}.responses`, responses);
|
||
|
_.set(acc.paths, `${routePath}.${methodVerb}.tags`, [_.upperFirst(tag)]);
|
||
|
|
||
|
if (isListOfEntities) {
|
||
|
_.set(acc.paths, `${routePath}.${methodVerb}.parameters`, queryParams);
|
||
|
}
|
||
|
|
||
|
if (hasPathParams) {
|
||
|
const pathParams = getPathParams(route.path);
|
||
|
_.set(acc.paths, `${routePath}.${methodVerb}.parameters`, pathParams);
|
||
|
}
|
||
|
|
||
|
if (methodVerb === 'post' || methodVerb === 'put') {
|
||
|
const { requestBody } = buildApiRequests(attributes, route);
|
||
|
|
||
|
_.set(acc.paths, `${routePath}.${methodVerb}.requestBody`, requestBody);
|
||
|
}
|
||
|
|
||
|
return acc;
|
||
|
},
|
||
|
{ paths: {} }
|
||
|
);
|
||
|
|
||
|
return paths;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @description - Builds the Swagger paths object for each api
|
||
|
*
|
||
|
* @param {object} api - Information about the current api
|
||
|
* @property {string} api.name - The name of the api
|
||
|
* @property {string} api.getter - The getter for the api (api | plugin)
|
||
|
* @property {array} api.ctNames - The name of all contentTypes found on the api
|
||
|
*
|
||
|
* @returns
|
||
|
*/
|
||
|
module.exports = api => {
|
||
|
if (!api.ctNames.length && api.getter === 'plugin') {
|
||
|
// Set arbitrary attributes
|
||
|
const attributes = { foo: { type: 'string' } };
|
||
|
const routes = strapi.plugin(api.name).routes['admin'].routes;
|
||
|
|
||
|
return getPaths(routes, attributes, api.name);
|
||
|
}
|
||
|
|
||
|
// An api could have multiple contentTypes
|
||
|
for (const contentTypeName of api.ctNames) {
|
||
|
// Get the attributes found on the api's contentType
|
||
|
const attributes = strapi.contentType(`${api.getter}::${api.name}.${contentTypeName}`)
|
||
|
.attributes;
|
||
|
|
||
|
// Get the routes for the current api
|
||
|
const routes =
|
||
|
api.getter === 'plugin'
|
||
|
? strapi.plugin(api.name).routes['content-api'].routes
|
||
|
: strapi.api[api.name].routes[contentTypeName].routes;
|
||
|
|
||
|
// Parse an identifier for OpenAPI tag if the api name and contentType name don't match
|
||
|
const tag = api.name === contentTypeName ? api.name : `${api.name} - ${contentTypeName}`;
|
||
|
return getPaths(routes, attributes, tag);
|
||
|
}
|
||
|
};
|