@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
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const strapi = {
|
|
4
|
+
plugins: {
|
|
5
|
+
'users-permissions': {
|
|
6
|
+
contentTypes: {
|
|
7
|
+
role: {
|
|
8
|
+
attributes: {
|
|
9
|
+
name: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
routes: {
|
|
16
|
+
'content-api': {
|
|
17
|
+
routes: [],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
api: {
|
|
23
|
+
restaurant: {
|
|
24
|
+
contentTypes: {
|
|
25
|
+
restaurant: {
|
|
26
|
+
attributes: {
|
|
27
|
+
name: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
routes: {
|
|
34
|
+
restaurant: { routes: [] },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
contentType: () => ({ info: {}, attributes: { test: { type: 'string' } } }),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports = strapi;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const buildComponentSchema = require('../server/services/helpers/build-component-schema');
|
|
5
|
+
const strapi = require('../__mocks__/strapi');
|
|
6
|
+
|
|
7
|
+
describe('Build Component Schema', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
// Reset the mocked strapi instance
|
|
10
|
+
global.strapi = _.cloneDeep(strapi);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('builds the Response schema', () => {
|
|
14
|
+
const apiMocks = [
|
|
15
|
+
{
|
|
16
|
+
name: 'users-permissions',
|
|
17
|
+
getter: 'plugin',
|
|
18
|
+
ctNames: ['role'],
|
|
19
|
+
},
|
|
20
|
+
{ name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
let schemas = {};
|
|
24
|
+
for (const mock of apiMocks) {
|
|
25
|
+
schemas = {
|
|
26
|
+
...schemas,
|
|
27
|
+
...buildComponentSchema(mock),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const schemaNames = Object.keys(schemas);
|
|
32
|
+
const [pluginResponseName, apiResponseName] = Object.keys(schemas);
|
|
33
|
+
const [pluginResponseValue, apiResponseValue] = Object.values(schemas);
|
|
34
|
+
|
|
35
|
+
const expectedShape = {
|
|
36
|
+
properties: {
|
|
37
|
+
data: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
id: { type: 'string' },
|
|
41
|
+
attributes: { type: 'object', properties: { test: { type: 'string' } } },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
meta: { type: 'object' },
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
expect(schemaNames.length).toBe(2);
|
|
49
|
+
expect(pluginResponseName).toBe('UsersPermissionsRoleResponse');
|
|
50
|
+
expect(apiResponseName).toBe('RestaurantResponse');
|
|
51
|
+
expect(pluginResponseValue).toStrictEqual(expectedShape);
|
|
52
|
+
expect(apiResponseValue).toStrictEqual(expectedShape);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('builds the ResponseList schema', () => {
|
|
56
|
+
global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
|
|
57
|
+
{ method: 'GET', path: '/test', handler: 'test.find' },
|
|
58
|
+
];
|
|
59
|
+
global.strapi.api.restaurant.routes.restaurant.routes = [
|
|
60
|
+
{ method: 'GET', path: '/test', handler: 'test.find' },
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const apiMocks = [
|
|
64
|
+
{
|
|
65
|
+
name: 'users-permissions',
|
|
66
|
+
getter: 'plugin',
|
|
67
|
+
ctNames: ['role'],
|
|
68
|
+
},
|
|
69
|
+
{ name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
let schemas = {};
|
|
73
|
+
for (const mock of apiMocks) {
|
|
74
|
+
schemas = {
|
|
75
|
+
...schemas,
|
|
76
|
+
...buildComponentSchema(mock),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const schemaNames = Object.keys(schemas);
|
|
81
|
+
const pluginListResponseValue = schemas['UsersPermissionsRoleListResponse'];
|
|
82
|
+
const apiListResponseValue = schemas['RestaurantListResponse'];
|
|
83
|
+
|
|
84
|
+
const expectedShape = {
|
|
85
|
+
properties: {
|
|
86
|
+
data: {
|
|
87
|
+
type: 'array',
|
|
88
|
+
items: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
id: { type: 'string' },
|
|
92
|
+
attributes: { type: 'object', properties: { test: { type: 'string' } } },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
meta: {
|
|
97
|
+
type: 'object',
|
|
98
|
+
properties: {
|
|
99
|
+
pagination: {
|
|
100
|
+
properties: {
|
|
101
|
+
page: { type: 'integer' },
|
|
102
|
+
pageSize: { type: 'integer', minimum: 25 },
|
|
103
|
+
pageCount: { type: 'integer', maximum: 1 },
|
|
104
|
+
total: { type: 'integer' },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
expect(schemaNames.length).toBe(4);
|
|
113
|
+
expect(schemaNames.includes('UsersPermissionsRoleListResponse')).toBe(true);
|
|
114
|
+
expect(schemaNames.includes('RestaurantListResponse')).toBe(true);
|
|
115
|
+
expect(pluginListResponseValue).toStrictEqual(expectedShape);
|
|
116
|
+
expect(apiListResponseValue).toStrictEqual(expectedShape);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('builds the Request schema', () => {
|
|
120
|
+
global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
|
|
121
|
+
{ method: 'POST', path: '/test', handler: 'test.create' },
|
|
122
|
+
];
|
|
123
|
+
global.strapi.api.restaurant.routes.restaurant.routes = [
|
|
124
|
+
{ method: 'POST', path: '/test', handler: 'test.create' },
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const apiMocks = [
|
|
128
|
+
{
|
|
129
|
+
name: 'users-permissions',
|
|
130
|
+
getter: 'plugin',
|
|
131
|
+
ctNames: ['role'],
|
|
132
|
+
},
|
|
133
|
+
{ name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
let schemas = {};
|
|
137
|
+
for (const mock of apiMocks) {
|
|
138
|
+
schemas = {
|
|
139
|
+
...schemas,
|
|
140
|
+
...buildComponentSchema(mock),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const schemaNames = Object.keys(schemas);
|
|
145
|
+
const pluginListResponseValue = schemas['UsersPermissionsRoleRequest'];
|
|
146
|
+
const apiListResponseValue = schemas['RestaurantRequest'];
|
|
147
|
+
|
|
148
|
+
const expectedShape = {
|
|
149
|
+
type: 'object',
|
|
150
|
+
required: ['data'],
|
|
151
|
+
properties: {
|
|
152
|
+
data: {
|
|
153
|
+
required: [],
|
|
154
|
+
type: 'object',
|
|
155
|
+
properties: { test: { type: 'string' } },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
expect(schemaNames.length).toBe(4);
|
|
161
|
+
expect(schemaNames.includes('UsersPermissionsRoleRequest')).toBe(true);
|
|
162
|
+
expect(schemaNames.includes('RestaurantRequest')).toBe(true);
|
|
163
|
+
expect(pluginListResponseValue).toStrictEqual(expectedShape);
|
|
164
|
+
expect(apiListResponseValue).toStrictEqual(expectedShape);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('builds the LocalizationResponse schema', () => {
|
|
168
|
+
global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
|
|
169
|
+
{ method: 'GET', path: '/localizations', handler: 'test' },
|
|
170
|
+
];
|
|
171
|
+
global.strapi.api.restaurant.routes.restaurant.routes = [
|
|
172
|
+
{ method: 'GET', path: '/localizations', handler: 'test' },
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
const apiMocks = [
|
|
176
|
+
{
|
|
177
|
+
name: 'users-permissions',
|
|
178
|
+
getter: 'plugin',
|
|
179
|
+
ctNames: ['role'],
|
|
180
|
+
},
|
|
181
|
+
{ name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
let schemas = {};
|
|
185
|
+
for (const mock of apiMocks) {
|
|
186
|
+
schemas = {
|
|
187
|
+
...schemas,
|
|
188
|
+
...buildComponentSchema(mock),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const schemaNames = Object.keys(schemas);
|
|
193
|
+
const pluginListResponseValue = schemas['UsersPermissionsRoleLocalizationResponse'];
|
|
194
|
+
const apiListResponseValue = schemas['RestaurantLocalizationResponse'];
|
|
195
|
+
|
|
196
|
+
const expectedShape = {
|
|
197
|
+
type: 'object',
|
|
198
|
+
properties: {
|
|
199
|
+
id: { type: 'string' },
|
|
200
|
+
test: { type: 'string' },
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
expect(schemaNames.length).toBe(4);
|
|
205
|
+
expect(schemaNames.includes('UsersPermissionsRoleLocalizationResponse')).toBe(true);
|
|
206
|
+
expect(schemaNames.includes('RestaurantLocalizationResponse')).toBe(true);
|
|
207
|
+
expect(pluginListResponseValue).toStrictEqual(expectedShape);
|
|
208
|
+
expect(apiListResponseValue).toStrictEqual(expectedShape);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('builds the LocalizationRequest schema', () => {
|
|
212
|
+
global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
|
|
213
|
+
{ method: 'POST', path: '/localizations', handler: 'test' },
|
|
214
|
+
];
|
|
215
|
+
global.strapi.api.restaurant.routes.restaurant.routes = [
|
|
216
|
+
{ method: 'POST', path: '/localizations', handler: 'test' },
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
const apiMocks = [
|
|
220
|
+
{
|
|
221
|
+
name: 'users-permissions',
|
|
222
|
+
getter: 'plugin',
|
|
223
|
+
ctNames: ['role'],
|
|
224
|
+
},
|
|
225
|
+
{ name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
let schemas = {};
|
|
229
|
+
for (const mock of apiMocks) {
|
|
230
|
+
schemas = {
|
|
231
|
+
...schemas,
|
|
232
|
+
...buildComponentSchema(mock),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const schemaNames = Object.keys(schemas);
|
|
237
|
+
const pluginListResponseValue = schemas['UsersPermissionsRoleLocalizationRequest'];
|
|
238
|
+
const apiListResponseValue = schemas['RestaurantLocalizationRequest'];
|
|
239
|
+
|
|
240
|
+
const expectedShape = {
|
|
241
|
+
type: 'object',
|
|
242
|
+
required: ['locale'],
|
|
243
|
+
properties: { test: { type: 'string' } },
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
expect(schemaNames.length).toBe(8);
|
|
247
|
+
expect(schemaNames.includes('UsersPermissionsRoleLocalizationRequest')).toBe(true);
|
|
248
|
+
expect(schemaNames.includes('RestaurantLocalizationRequest')).toBe(true);
|
|
249
|
+
expect(pluginListResponseValue).toStrictEqual(expectedShape);
|
|
250
|
+
expect(apiListResponseValue).toStrictEqual(expectedShape);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('creates the correct name given multiple content types', () => {
|
|
254
|
+
const apiMock = {
|
|
255
|
+
name: 'users-permissions',
|
|
256
|
+
getter: 'plugin',
|
|
257
|
+
ctNames: ['permission', 'role', 'user'],
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const schemas = buildComponentSchema(apiMock);
|
|
261
|
+
const schemaNames = Object.keys(schemas);
|
|
262
|
+
const [permission, role, user] = schemaNames;
|
|
263
|
+
|
|
264
|
+
expect(schemaNames.length).toBe(3);
|
|
265
|
+
expect(permission).toBe('UsersPermissionsPermissionResponse');
|
|
266
|
+
expect(role).toBe('UsersPermissionsRoleResponse');
|
|
267
|
+
expect(user).toBe('UsersPermissionsUserResponse');
|
|
268
|
+
});
|
|
269
|
+
});
|
|
@@ -92,7 +92,7 @@ const SettingsPage = () => {
|
|
|
92
92
|
<Stack spacing={4}>
|
|
93
93
|
<Typography variant="delta" as="h2">
|
|
94
94
|
{formatMessage({
|
|
95
|
-
id:
|
|
95
|
+
id: 'global.settings',
|
|
96
96
|
defaultMessage: 'Settings',
|
|
97
97
|
})}
|
|
98
98
|
</Typography>
|
|
@@ -125,7 +125,7 @@ const SettingsPage = () => {
|
|
|
125
125
|
<GridItem col={6} s={12}>
|
|
126
126
|
<TextInput
|
|
127
127
|
label={formatMessage({
|
|
128
|
-
id:
|
|
128
|
+
id: 'global.password',
|
|
129
129
|
defaultMessage: 'Password',
|
|
130
130
|
})}
|
|
131
131
|
name="password"
|
|
@@ -26,14 +26,11 @@
|
|
|
26
26
|
"pages.PluginPage.Button.open": "Åben dokumentation",
|
|
27
27
|
"pages.PluginPage.header.description": "Konfigurér dokumentations pluginnet",
|
|
28
28
|
"pages.PluginPage.table.generated": "Sidst genereret",
|
|
29
|
-
"pages.PluginPage.table.icon.delete": "Slet {target}",
|
|
30
29
|
"pages.PluginPage.table.icon.regenerate": "Regenerér {target}",
|
|
31
30
|
"pages.PluginPage.table.icon.show": "Åben {target}",
|
|
32
31
|
"pages.PluginPage.table.version": "Version",
|
|
33
32
|
"pages.SettingsPage.Button.description": "Konfigurér dokumentations pluginnet",
|
|
34
33
|
"pages.SettingsPage.header.save": "Gem",
|
|
35
|
-
"pages.SettingsPage.password.label": "Kodeord",
|
|
36
|
-
"pages.SettingsPage.title": "Indstillinger",
|
|
37
34
|
"pages.SettingsPage.toggle.hint": "Gør dokumentationens endpoint privat",
|
|
38
35
|
"pages.SettingsPage.toggle.label": "Begrænset adgang",
|
|
39
36
|
"plugin.description.long": "Opret et OpenAPI dokument og visualisér dit API med SWAGGER UI.",
|
|
@@ -26,14 +26,11 @@
|
|
|
26
26
|
"pages.PluginPage.Button.open": "Open documentation",
|
|
27
27
|
"pages.PluginPage.header.description": "Configure the documentation plugin",
|
|
28
28
|
"pages.PluginPage.table.generated": "Last generated",
|
|
29
|
-
"pages.PluginPage.table.icon.delete": "Delete {target}",
|
|
30
29
|
"pages.PluginPage.table.icon.regenerate": "Regenerate {target}",
|
|
31
30
|
"pages.PluginPage.table.icon.show": "Open {target}",
|
|
32
31
|
"pages.PluginPage.table.version": "Version",
|
|
33
32
|
"pages.SettingsPage.Button.description": "Configure the documentation plugin",
|
|
34
33
|
"pages.SettingsPage.header.save": "Save",
|
|
35
|
-
"pages.SettingsPage.password.label": "Password",
|
|
36
|
-
"pages.SettingsPage.title": "Settings",
|
|
37
34
|
"pages.SettingsPage.toggle.hint": "Make the documentation endpoint private",
|
|
38
35
|
"pages.SettingsPage.toggle.label": "Restricted Access",
|
|
39
36
|
"plugin.description.long": "Create an OpenAPI Document and visualize your API with SWAGGER UI.",
|
|
@@ -26,14 +26,11 @@
|
|
|
26
26
|
"pages.PluginPage.Button.open": "Abrir documentación",
|
|
27
27
|
"pages.PluginPage.header.description": "Configura el plugin de documentación",
|
|
28
28
|
"pages.PluginPage.table.generated": "Último generado",
|
|
29
|
-
"pages.PluginPage.table.icon.delete": "Eliminar {target}",
|
|
30
29
|
"pages.PluginPage.table.icon.regenerate": "Regenerar {target}",
|
|
31
30
|
"pages.PluginPage.table.icon.show": "Abrir {target}",
|
|
32
31
|
"pages.PluginPage.table.version": "Versión",
|
|
33
32
|
"pages.SettingsPage.Button.description": "Configura el plugin de documentación",
|
|
34
33
|
"pages.SettingsPage.header.save": "Guardar",
|
|
35
|
-
"pages.SettingsPage.password.label": "Contraseña",
|
|
36
|
-
"pages.SettingsPage.title": "Ajustes",
|
|
37
34
|
"pages.SettingsPage.toggle.hint": "Hacer que la documentación sea privada",
|
|
38
35
|
"pages.SettingsPage.toggle.label": "Acceso restringido",
|
|
39
36
|
"plugin.description.long": "Cree un documento OpenAPI y visualice su API con SWAGGER UI.",
|
|
@@ -26,14 +26,11 @@
|
|
|
26
26
|
"pages.PluginPage.Button.open": "도큐멘테이션 열기",
|
|
27
27
|
"pages.PluginPage.header.description": "도큐멘테이션 플러그인 설정",
|
|
28
28
|
"pages.PluginPage.table.generated": "최종 생성일",
|
|
29
|
-
"pages.PluginPage.table.icon.delete": "{target} 삭제",
|
|
30
29
|
"pages.PluginPage.table.icon.regenerate": "{target} 재생성",
|
|
31
30
|
"pages.PluginPage.table.icon.show": "{target} 열기",
|
|
32
31
|
"pages.PluginPage.table.version": "버전",
|
|
33
32
|
"pages.SettingsPage.Button.description": "도큐멘테이션 플러그인 설정",
|
|
34
33
|
"pages.SettingsPage.header.save": "저장",
|
|
35
|
-
"pages.SettingsPage.password.label": "비밀번호",
|
|
36
|
-
"pages.SettingsPage.title": "설정",
|
|
37
34
|
"pages.SettingsPage.toggle.hint": "도큐멘테이션 엔드포인트를 비공개로 설정합니다.",
|
|
38
35
|
"pages.SettingsPage.toggle.label": "액세스 제한",
|
|
39
36
|
"plugin.description.long": "SWAGER UI를 사용하여 오픈 API 문서를 만들고 API를 시각화합니다.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/plugin-documentation",
|
|
3
|
-
"version": "4.2.0-beta.
|
|
3
|
+
"version": "4.2.0-beta.3",
|
|
4
4
|
"description": "Create an OpenAPI Document and visualize your API with SWAGGER UI.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"test": "echo \"no tests yet\""
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@strapi/helper-plugin": "4.2.0-beta.
|
|
28
|
-
"@strapi/utils": "4.2.0-beta.
|
|
27
|
+
"@strapi/helper-plugin": "4.2.0-beta.3",
|
|
28
|
+
"@strapi/utils": "4.2.0-beta.3",
|
|
29
29
|
"bcryptjs": "2.4.3",
|
|
30
30
|
"cheerio": "^1.0.0-rc.5",
|
|
31
31
|
"fs-extra": "10.0.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"description": "Create an OpenAPI Document and visualize your API with SWAGGER UI.",
|
|
58
58
|
"kind": "plugin"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "c4addbad6ecbc8ef7633bbba3806f3b0a2ae5f49"
|
|
61
61
|
}
|
|
@@ -21,7 +21,7 @@ module.exports = {
|
|
|
21
21
|
path: '/documentation',
|
|
22
22
|
showGeneratedFiles: true,
|
|
23
23
|
generateDefaultResponse: true,
|
|
24
|
-
plugins: ['email', 'upload'],
|
|
24
|
+
plugins: ['email', 'upload', 'users-permissions'],
|
|
25
25
|
},
|
|
26
26
|
servers: [],
|
|
27
27
|
externalDocs: {
|
|
@@ -41,5 +41,34 @@ module.exports = {
|
|
|
41
41
|
bearerFormat: 'JWT',
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
|
+
schemas: {
|
|
45
|
+
Error: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
required: ['error'],
|
|
48
|
+
properties: {
|
|
49
|
+
data: {
|
|
50
|
+
nullable: true,
|
|
51
|
+
oneOf: [{ type: 'object' }, { type: 'array', items: [] }],
|
|
52
|
+
},
|
|
53
|
+
error: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
status: {
|
|
57
|
+
type: 'integer',
|
|
58
|
+
},
|
|
59
|
+
name: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
},
|
|
62
|
+
message: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
},
|
|
65
|
+
details: {
|
|
66
|
+
type: 'object',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
44
73
|
},
|
|
45
74
|
};
|
package/server/config/index.js
CHANGED
|
@@ -49,7 +49,7 @@ module.exports = {
|
|
|
49
49
|
.getDocumentationVersion();
|
|
50
50
|
|
|
51
51
|
const openAPISpecsPath = path.join(
|
|
52
|
-
strapi.dirs.
|
|
52
|
+
strapi.dirs.app.extensions,
|
|
53
53
|
'documentation',
|
|
54
54
|
'documentation',
|
|
55
55
|
version,
|
|
@@ -82,7 +82,7 @@ module.exports = {
|
|
|
82
82
|
|
|
83
83
|
try {
|
|
84
84
|
const staticFolder = path.resolve(
|
|
85
|
-
strapi.dirs.
|
|
85
|
+
strapi.dirs.app.extensions,
|
|
86
86
|
'documentation',
|
|
87
87
|
'public'
|
|
88
88
|
);
|
|
@@ -120,7 +120,7 @@ module.exports = {
|
|
|
120
120
|
|
|
121
121
|
try {
|
|
122
122
|
const layoutPath = path.resolve(
|
|
123
|
-
strapi.dirs.
|
|
123
|
+
strapi.dirs.app.extensions,
|
|
124
124
|
'documentation',
|
|
125
125
|
'public',
|
|
126
126
|
'login.html'
|
|
@@ -131,7 +131,7 @@ module.exports = {
|
|
|
131
131
|
ctx.url = path.basename(`${ctx.url}/login.html`);
|
|
132
132
|
|
|
133
133
|
try {
|
|
134
|
-
const staticFolder = path.resolve(strapi.dirs.
|
|
134
|
+
const staticFolder = path.resolve(strapi.dirs.app.extensions, 'documentation', 'public');
|
|
135
135
|
return koaStatic(staticFolder)(ctx, next);
|
|
136
136
|
} catch (e) {
|
|
137
137
|
strapi.log.error(e);
|
|
@@ -5,8 +5,8 @@ const fs = require('fs-extra');
|
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const { getAbsoluteServerUrl } = require('@strapi/utils');
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const defaultPluginConfig = require('../config/default-plugin-config');
|
|
9
|
+
const { builApiEndpointPath, buildComponentSchema } = require('./helpers');
|
|
10
10
|
|
|
11
11
|
module.exports = ({ strapi }) => {
|
|
12
12
|
const config = strapi.config.get('plugin.documentation');
|
|
@@ -108,7 +108,7 @@ module.exports = ({ strapi }) => {
|
|
|
108
108
|
return [...apisToDocument, ...pluginsToDocument];
|
|
109
109
|
},
|
|
110
110
|
|
|
111
|
-
async
|
|
111
|
+
async getCustomConfig() {
|
|
112
112
|
const customConfigPath = this.getCustomDocumentationPath();
|
|
113
113
|
const pathExists = await fs.pathExists(customConfigPath);
|
|
114
114
|
if (pathExists) {
|
|
@@ -123,23 +123,31 @@ module.exports = ({ strapi }) => {
|
|
|
123
123
|
*/
|
|
124
124
|
async generateFullDoc(version = this.getDocumentationVersion()) {
|
|
125
125
|
let paths = {};
|
|
126
|
-
|
|
126
|
+
let schemas = {};
|
|
127
127
|
const apis = this.getPluginAndApiInfo();
|
|
128
128
|
for (const api of apis) {
|
|
129
129
|
const apiName = api.name;
|
|
130
130
|
const apiDirPath = path.join(this.getApiDocumentationPath(api), version);
|
|
131
131
|
|
|
132
132
|
const apiDocPath = path.join(apiDirPath, `${apiName}.json`);
|
|
133
|
-
const apiPathsObject = builApiEndpointPath(api);
|
|
134
133
|
|
|
135
|
-
|
|
134
|
+
const apiPath = builApiEndpointPath(api);
|
|
135
|
+
|
|
136
|
+
if (!apiPath) {
|
|
136
137
|
continue;
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
await fs.ensureFile(apiDocPath);
|
|
140
|
-
await fs.writeJson(apiDocPath,
|
|
141
|
+
await fs.writeJson(apiDocPath, apiPath, { spaces: 2 });
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
const componentSchema = buildComponentSchema(api);
|
|
144
|
+
|
|
145
|
+
schemas = {
|
|
146
|
+
...schemas,
|
|
147
|
+
...componentSchema,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
paths = { ...paths, ...apiPath };
|
|
143
151
|
}
|
|
144
152
|
|
|
145
153
|
const fullDocJsonPath = path.join(
|
|
@@ -148,27 +156,26 @@ module.exports = ({ strapi }) => {
|
|
|
148
156
|
'full_documentation.json'
|
|
149
157
|
);
|
|
150
158
|
|
|
151
|
-
const
|
|
159
|
+
const defaultConfig = _.cloneDeep(defaultPluginConfig);
|
|
152
160
|
|
|
153
161
|
const serverUrl = getAbsoluteServerUrl(strapi.config);
|
|
154
162
|
const apiPath = strapi.config.get('api.rest.prefix');
|
|
155
163
|
|
|
156
|
-
_.set(
|
|
164
|
+
_.set(defaultConfig, 'servers', [
|
|
157
165
|
{
|
|
158
166
|
url: `${serverUrl}${apiPath}`,
|
|
159
167
|
description: 'Development server',
|
|
160
168
|
},
|
|
161
169
|
]);
|
|
170
|
+
_.set(defaultConfig, ['info', 'x-generation-date'], new Date().toISOString());
|
|
171
|
+
_.set(defaultConfig, ['info', 'version'], version);
|
|
172
|
+
_.merge(defaultConfig.components, { schemas });
|
|
162
173
|
|
|
163
|
-
|
|
164
|
-
_.
|
|
165
|
-
|
|
166
|
-
const customSettings = await this.getCustomSettings();
|
|
167
|
-
|
|
168
|
-
const settings = _.merge(defaultSettings, customSettings);
|
|
174
|
+
const customConfig = await this.getCustomConfig();
|
|
175
|
+
const config = _.merge(defaultConfig, customConfig);
|
|
169
176
|
|
|
170
177
|
await fs.ensureFile(fullDocJsonPath);
|
|
171
|
-
await fs.writeJson(fullDocJsonPath, { ...
|
|
178
|
+
await fs.writeJson(fullDocJsonPath, { ...config, paths }, { spaces: 2 });
|
|
172
179
|
},
|
|
173
180
|
};
|
|
174
181
|
};
|