@strapi/plugin-documentation 4.2.0-beta.0 → 4.2.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mocks__/strapi.js +41 -0
- package/__tests__/build-component-schema.test.js +269 -0
- package/admin/src/pages/PluginPage/index.js +1 -1
- package/admin/src/pages/SettingsPage/index.js +2 -2
- package/admin/src/translations/dk.json +0 -3
- package/admin/src/translations/en.json +0 -3
- package/admin/src/translations/es.json +0 -3
- package/admin/src/translations/ko.json +0 -3
- package/package.json +4 -4
- package/server/config/{default-config.js → default-plugin-config.js} +30 -1
- package/server/config/index.js +2 -2
- package/server/controllers/documentation.js +4 -4
- package/server/services/documentation.js +24 -17
- package/server/services/helpers/build-api-endpoint-path.js +185 -0
- package/server/services/helpers/build-component-schema.js +154 -0
- package/server/services/helpers/index.js +9 -0
- package/server/{utils → services/helpers/utils}/clean-schema-attributes.js +9 -2
- package/server/services/helpers/utils/get-api-responses.js +105 -0
- package/server/{utils → services/helpers/utils}/get-schema-data.js +0 -0
- package/server/services/helpers/utils/loop-content-type-names.js +52 -0
- package/server/services/helpers/utils/pascal-case.js +9 -0
- package/server/{utils → services/helpers/utils}/query-params.js +0 -0
- package/server/services/helpers/utils/routes.js +10 -0
- package/server/services/utils/components.json +0 -25
- package/server/services/utils/parametersOptions.json +0 -134
- package/server/services/utils/unknownComponent.json +0 -11
- package/server/utils/builders/build-api-endpoint-path.js +0 -180
- package/server/utils/builders/build-api-requests.js +0 -41
- package/server/utils/builders/build-api-responses.js +0 -109
- package/server/utils/builders/index.js +0 -11
- package/server/utils/error-response.js +0 -22
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"name": "_limit",
|
|
4
|
-
"in": "query",
|
|
5
|
-
"required": false,
|
|
6
|
-
"description": "Maximum number of results possible",
|
|
7
|
-
"schema": {
|
|
8
|
-
"type": "integer"
|
|
9
|
-
},
|
|
10
|
-
"deprecated": false
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "_sort",
|
|
14
|
-
"in": "query",
|
|
15
|
-
"required": false,
|
|
16
|
-
"description": "Sort according to a specific field.",
|
|
17
|
-
"schema": {
|
|
18
|
-
"type": "string"
|
|
19
|
-
},
|
|
20
|
-
"deprecated": false
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"name": "_start",
|
|
24
|
-
"in": "query",
|
|
25
|
-
"required": false,
|
|
26
|
-
"description": "Skip a specific number of entries (especially useful for pagination)",
|
|
27
|
-
"schema": {
|
|
28
|
-
"type": "integer"
|
|
29
|
-
},
|
|
30
|
-
"deprecated": false
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"name": "=",
|
|
34
|
-
"in": "query",
|
|
35
|
-
"required": false,
|
|
36
|
-
"description": "Get entries that matches exactly your input",
|
|
37
|
-
"schema": {
|
|
38
|
-
"type": "string"
|
|
39
|
-
},
|
|
40
|
-
"deprecated": false
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"name": "_ne",
|
|
44
|
-
"in": "query",
|
|
45
|
-
"required": false,
|
|
46
|
-
"description": "Get records that are not equals to something",
|
|
47
|
-
"schema": {
|
|
48
|
-
"type": "string"
|
|
49
|
-
},
|
|
50
|
-
"deprecated": false
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"name": "_lt",
|
|
54
|
-
"in": "query",
|
|
55
|
-
"required": false,
|
|
56
|
-
"description": "Get record that are lower than a value",
|
|
57
|
-
"schema": {
|
|
58
|
-
"type": "string"
|
|
59
|
-
},
|
|
60
|
-
"deprecated": false
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"name": "_lte",
|
|
64
|
-
"in": "query",
|
|
65
|
-
"required": false,
|
|
66
|
-
"description": "Get records that are lower than or equal to a value",
|
|
67
|
-
"schema": {
|
|
68
|
-
"type": "string"
|
|
69
|
-
},
|
|
70
|
-
"deprecated": false
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"name": "_gt",
|
|
74
|
-
"in": "query",
|
|
75
|
-
"required": false,
|
|
76
|
-
"description": "Get records that are greater than a value",
|
|
77
|
-
"schema": {
|
|
78
|
-
"type": "string"
|
|
79
|
-
},
|
|
80
|
-
"deprecated": false
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"name": "_gte",
|
|
84
|
-
"in": "query",
|
|
85
|
-
"required": false,
|
|
86
|
-
"description": "Get records that are greater than or equal a value",
|
|
87
|
-
"schema": {
|
|
88
|
-
"type": "string"
|
|
89
|
-
},
|
|
90
|
-
"deprecated": false
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"name": "_contains",
|
|
94
|
-
"in": "query",
|
|
95
|
-
"required": false,
|
|
96
|
-
"description": "Get records that contains a value",
|
|
97
|
-
"schema": {
|
|
98
|
-
"type": "string"
|
|
99
|
-
},
|
|
100
|
-
"deprecated": false
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
"name": "_containss",
|
|
104
|
-
"in": "query",
|
|
105
|
-
"required": false,
|
|
106
|
-
"description": "Get records that contains (case sensitive) a value",
|
|
107
|
-
"schema": {
|
|
108
|
-
"type": "string"
|
|
109
|
-
},
|
|
110
|
-
"deprecated": false
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
"name": "_in",
|
|
114
|
-
"in": "query",
|
|
115
|
-
"required": false,
|
|
116
|
-
"description": "Get records that matches any value in the array of values",
|
|
117
|
-
"schema": {
|
|
118
|
-
"type": "array",
|
|
119
|
-
"items": { "type": "string" }
|
|
120
|
-
},
|
|
121
|
-
"deprecated": false
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
"name": "_nin",
|
|
125
|
-
"in": "query",
|
|
126
|
-
"required": false,
|
|
127
|
-
"description": "Get records that doesn't match any value in the array of values",
|
|
128
|
-
"schema": {
|
|
129
|
-
"type": "array",
|
|
130
|
-
"items": { "type": "string" }
|
|
131
|
-
},
|
|
132
|
-
"deprecated": false
|
|
133
|
-
}
|
|
134
|
-
]
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const pathToRegexp = require('path-to-regexp');
|
|
5
|
-
|
|
6
|
-
const queryParams = require('../query-params');
|
|
7
|
-
const buildApiRequests = require('./build-api-requests');
|
|
8
|
-
const buildApiResponses = require('./build-api-responses');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @description Parses a route with ':variable'
|
|
12
|
-
*
|
|
13
|
-
* @param {string} routePath - The route's path property
|
|
14
|
-
* @returns {string}
|
|
15
|
-
*/
|
|
16
|
-
const parsePathWithVariables = routePath => {
|
|
17
|
-
return pathToRegexp
|
|
18
|
-
.parse(routePath)
|
|
19
|
-
.map(token => {
|
|
20
|
-
if (_.isObject(token)) {
|
|
21
|
-
return token.prefix + '{' + token.name + '}';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return token;
|
|
25
|
-
})
|
|
26
|
-
.join('');
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @description Builds the required object for a path parameter
|
|
31
|
-
*
|
|
32
|
-
* @param {string} routePath - The route's path property
|
|
33
|
-
*
|
|
34
|
-
* @returns {object } Swagger path params object
|
|
35
|
-
*/
|
|
36
|
-
const getPathParams = routePath => {
|
|
37
|
-
return pathToRegexp
|
|
38
|
-
.parse(routePath)
|
|
39
|
-
.filter(token => _.isObject(token))
|
|
40
|
-
.map(param => {
|
|
41
|
-
return {
|
|
42
|
-
name: param.name,
|
|
43
|
-
in: 'path',
|
|
44
|
-
description: '',
|
|
45
|
-
deprecated: false,
|
|
46
|
-
required: true,
|
|
47
|
-
schema: { type: 'string' },
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* @param {string} prefix - The route prefix
|
|
55
|
-
* @param {string} path - The route path
|
|
56
|
-
*
|
|
57
|
-
* @returns {string}
|
|
58
|
-
*/
|
|
59
|
-
const getPathWithPrefix = (prefix, path) => {
|
|
60
|
-
if (path.includes('localizations')) {
|
|
61
|
-
return path;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (path.endsWith('/')) {
|
|
65
|
-
return prefix;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return prefix.concat(path);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
*
|
|
73
|
-
* @param {object} api - Information about the api
|
|
74
|
-
* @param {object} api.routeInfo - The routes for a given api or plugin
|
|
75
|
-
* @param {string} api.routeInfo.prefix - The prefix for all routes
|
|
76
|
-
* @param {array} api.routeInfo.routes - The routes for the current api
|
|
77
|
-
* @param {object} api.attributes - The attributes for a given api or plugin
|
|
78
|
-
* @param {string} api.tag - A descriptor for OpenAPI
|
|
79
|
-
*
|
|
80
|
-
* @returns {object}
|
|
81
|
-
*/
|
|
82
|
-
const getPaths = ({ routeInfo, attributes, tag }) => {
|
|
83
|
-
const paths = routeInfo.routes.reduce((acc, route) => {
|
|
84
|
-
// TODO: Find a more reliable way to determine list of entities vs a single entity
|
|
85
|
-
const isListOfEntities = route.handler.split('.').pop() === 'find';
|
|
86
|
-
const methodVerb = route.method.toLowerCase();
|
|
87
|
-
|
|
88
|
-
const hasPathParams = route.path.includes('/:');
|
|
89
|
-
const pathWithPrefix = routeInfo.prefix
|
|
90
|
-
? getPathWithPrefix(routeInfo.prefix, route.path)
|
|
91
|
-
: route.path;
|
|
92
|
-
const routePath = hasPathParams ? parsePathWithVariables(pathWithPrefix) : pathWithPrefix;
|
|
93
|
-
|
|
94
|
-
const { responses } = buildApiResponses(attributes, route, isListOfEntities);
|
|
95
|
-
|
|
96
|
-
const swaggerConfig = {
|
|
97
|
-
responses,
|
|
98
|
-
tags: [_.upperFirst(tag)],
|
|
99
|
-
parameters: [],
|
|
100
|
-
operationId: `${methodVerb}${routePath}`,
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
if (isListOfEntities) {
|
|
104
|
-
swaggerConfig.parameters.push(...queryParams);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (hasPathParams) {
|
|
108
|
-
const pathParams = getPathParams(route.path);
|
|
109
|
-
swaggerConfig.parameters.push(...pathParams);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (['post', 'put'].includes(methodVerb)) {
|
|
113
|
-
const { requestBody } = buildApiRequests(attributes, route);
|
|
114
|
-
|
|
115
|
-
swaggerConfig.requestBody = requestBody;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
_.set(acc, `${routePath}.${methodVerb}`, swaggerConfig);
|
|
119
|
-
|
|
120
|
-
return acc;
|
|
121
|
-
}, {});
|
|
122
|
-
|
|
123
|
-
return { paths };
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @description - Builds the Swagger paths object for each api
|
|
128
|
-
*
|
|
129
|
-
* @param {object} api - Information about the current api
|
|
130
|
-
* @property {string} api.name - The name of the api
|
|
131
|
-
* @property {string} api.getter - The getter for the api (api | plugin)
|
|
132
|
-
* @property {array} api.ctNames - The name of all contentTypes found on the api
|
|
133
|
-
*
|
|
134
|
-
* @returns {object}
|
|
135
|
-
*/
|
|
136
|
-
module.exports = api => {
|
|
137
|
-
if (!api.ctNames.length && api.getter === 'plugin') {
|
|
138
|
-
// Set arbitrary attributes
|
|
139
|
-
const attributes = { foo: { type: 'string' } };
|
|
140
|
-
const routeInfo = strapi.plugin(api.name).routes['admin'];
|
|
141
|
-
|
|
142
|
-
const apiInfo = {
|
|
143
|
-
routeInfo,
|
|
144
|
-
attributes,
|
|
145
|
-
tag: api.name,
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
return getPaths(apiInfo);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// An api could have multiple contentTypes
|
|
152
|
-
let paths = {};
|
|
153
|
-
for (const contentTypeName of api.ctNames) {
|
|
154
|
-
// Get the attributes found on the api's contentType
|
|
155
|
-
const uid = `${api.getter}::${api.name}.${contentTypeName}`;
|
|
156
|
-
const ct = strapi.contentType(uid);
|
|
157
|
-
const attributes = ct.attributes;
|
|
158
|
-
|
|
159
|
-
// Get the routes for the current api
|
|
160
|
-
const routeInfo =
|
|
161
|
-
api.getter === 'plugin'
|
|
162
|
-
? strapi.plugin(api.name).routes['content-api']
|
|
163
|
-
: strapi.api[api.name].routes[contentTypeName];
|
|
164
|
-
|
|
165
|
-
// Parse an identifier for OpenAPI tag if the api name and contentType name don't match
|
|
166
|
-
const tag = api.name === contentTypeName ? api.name : `${api.name} - ${contentTypeName}`;
|
|
167
|
-
const apiInfo = {
|
|
168
|
-
routeInfo,
|
|
169
|
-
attributes,
|
|
170
|
-
tag,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
paths = {
|
|
174
|
-
...paths,
|
|
175
|
-
...getPaths(apiInfo).paths,
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return { paths };
|
|
180
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const cleanSchemaAttributes = require('../clean-schema-attributes');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {object} attributes - The attributes found on a contentType
|
|
8
|
-
* @param {object} route - The current route
|
|
9
|
-
*
|
|
10
|
-
* @returns The Swagger requestBody
|
|
11
|
-
*/
|
|
12
|
-
module.exports = (attributes, route) => {
|
|
13
|
-
const requiredAttributes = Object.entries(attributes)
|
|
14
|
-
.filter(([, attribute]) => attribute.required)
|
|
15
|
-
.map(([attributeName, attribute]) => {
|
|
16
|
-
return { [attributeName]: attribute };
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const requestAttributes =
|
|
20
|
-
route.method === 'POST' && requiredAttributes.length
|
|
21
|
-
? Object.assign({}, ...requiredAttributes)
|
|
22
|
-
: attributes;
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
requestBody: {
|
|
26
|
-
required: true,
|
|
27
|
-
content: {
|
|
28
|
-
'application/json': {
|
|
29
|
-
schema: {
|
|
30
|
-
properties: {
|
|
31
|
-
data: {
|
|
32
|
-
type: 'object',
|
|
33
|
-
properties: cleanSchemaAttributes(requestAttributes, { isRequest: true }),
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const getSchemaData = require('../get-schema-data');
|
|
4
|
-
const cleanSchemaAttributes = require('../clean-schema-attributes');
|
|
5
|
-
const errorResponse = require('../error-response');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @param {boolean} isSingleEntity - Checks for a single entity
|
|
10
|
-
* @returns {object} The correctly formatted meta object
|
|
11
|
-
*/
|
|
12
|
-
const getMeta = isListOfEntities => {
|
|
13
|
-
if (isListOfEntities) {
|
|
14
|
-
return {
|
|
15
|
-
type: 'object',
|
|
16
|
-
properties: {
|
|
17
|
-
pagination: {
|
|
18
|
-
properties: {
|
|
19
|
-
page: { type: 'integer' },
|
|
20
|
-
pageSize: { type: 'integer', minimum: 25 },
|
|
21
|
-
pageCount: { type: 'integer', maximum: 1 },
|
|
22
|
-
total: { type: 'integer' },
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return { type: 'object' };
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @description - Builds the Swagger response object for a given api
|
|
34
|
-
*
|
|
35
|
-
* @param {object} attributes - The attributes found on a contentType
|
|
36
|
-
* @param {object} route - The current route
|
|
37
|
-
* @param {boolean} isListOfEntities - Checks for a list of entitities
|
|
38
|
-
*
|
|
39
|
-
* @returns The Swagger responses
|
|
40
|
-
*/
|
|
41
|
-
module.exports = (attributes, route, isListOfEntities = false) => {
|
|
42
|
-
let schema;
|
|
43
|
-
if (route.method === 'DELETE') {
|
|
44
|
-
schema = {
|
|
45
|
-
type: 'integer',
|
|
46
|
-
format: 'int64',
|
|
47
|
-
};
|
|
48
|
-
} else {
|
|
49
|
-
schema = {
|
|
50
|
-
properties: {
|
|
51
|
-
data: getSchemaData(isListOfEntities, cleanSchemaAttributes(attributes)),
|
|
52
|
-
meta: getMeta(isListOfEntities),
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
responses: {
|
|
59
|
-
'200': {
|
|
60
|
-
description: 'OK',
|
|
61
|
-
content: {
|
|
62
|
-
'application/json': {
|
|
63
|
-
schema,
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
'400': {
|
|
68
|
-
description: 'Bad Request',
|
|
69
|
-
content: {
|
|
70
|
-
'application/json': {
|
|
71
|
-
schema: errorResponse,
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
'401': {
|
|
76
|
-
description: 'Unauthorized',
|
|
77
|
-
content: {
|
|
78
|
-
'application/json': {
|
|
79
|
-
schema: errorResponse,
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
'403': {
|
|
84
|
-
description: 'Forbidden',
|
|
85
|
-
content: {
|
|
86
|
-
'application/json': {
|
|
87
|
-
schema: errorResponse,
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
'404': {
|
|
92
|
-
description: 'Not Found',
|
|
93
|
-
content: {
|
|
94
|
-
'application/json': {
|
|
95
|
-
schema: errorResponse,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
'500': {
|
|
100
|
-
description: 'Internal Server Error',
|
|
101
|
-
content: {
|
|
102
|
-
'application/json': {
|
|
103
|
-
schema: errorResponse,
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const buildApiResponses = require('./build-api-responses');
|
|
4
|
-
const buildApiRequests = require('./build-api-requests');
|
|
5
|
-
const builApiEndpointPath = require('./build-api-endpoint-path');
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
buildApiResponses,
|
|
9
|
-
buildApiRequests,
|
|
10
|
-
builApiEndpointPath,
|
|
11
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
type: 'object',
|
|
5
|
-
required: ['error'],
|
|
6
|
-
properties: {
|
|
7
|
-
error: {
|
|
8
|
-
type: 'object',
|
|
9
|
-
properties: {
|
|
10
|
-
status: {
|
|
11
|
-
type: 'integer',
|
|
12
|
-
},
|
|
13
|
-
name: {
|
|
14
|
-
type: 'string',
|
|
15
|
-
},
|
|
16
|
-
message: {
|
|
17
|
-
type: 'string',
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
};
|