@strapi/plugin-documentation 0.0.0-113ff29005

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.
Files changed (72) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +151 -0
  3. package/__mocks__/strapi.js +41 -0
  4. package/__tests__/build-component-schema.test.js +271 -0
  5. package/admin/src/components/FieldActionWrapper/index.js +14 -0
  6. package/admin/src/components/PluginIcon/index.js +12 -0
  7. package/admin/src/index.js +80 -0
  8. package/admin/src/pages/PluginPage/index.js +199 -0
  9. package/admin/src/pages/PluginPage/tests/index.test.js +873 -0
  10. package/admin/src/pages/PluginPage/tests/server.js +23 -0
  11. package/admin/src/pages/SettingsPage/index.js +181 -0
  12. package/admin/src/pages/SettingsPage/tests/index.test.js +612 -0
  13. package/admin/src/pages/SettingsPage/tests/server.js +18 -0
  14. package/admin/src/pages/utils/api.js +31 -0
  15. package/admin/src/pages/utils/schema.js +11 -0
  16. package/admin/src/pages/utils/useReactQuery.js +46 -0
  17. package/admin/src/permissions.js +19 -0
  18. package/admin/src/pluginId.js +5 -0
  19. package/admin/src/translations/ar.json +20 -0
  20. package/admin/src/translations/cs.json +21 -0
  21. package/admin/src/translations/de.json +26 -0
  22. package/admin/src/translations/dk.json +39 -0
  23. package/admin/src/translations/en.json +39 -0
  24. package/admin/src/translations/es.json +39 -0
  25. package/admin/src/translations/fr.json +26 -0
  26. package/admin/src/translations/id.json +24 -0
  27. package/admin/src/translations/it.json +26 -0
  28. package/admin/src/translations/ko.json +39 -0
  29. package/admin/src/translations/ms.json +23 -0
  30. package/admin/src/translations/nl.json +21 -0
  31. package/admin/src/translations/pl.json +39 -0
  32. package/admin/src/translations/pt-BR.json +21 -0
  33. package/admin/src/translations/pt.json +21 -0
  34. package/admin/src/translations/ru.json +28 -0
  35. package/admin/src/translations/sk.json +24 -0
  36. package/admin/src/translations/th.json +24 -0
  37. package/admin/src/translations/tr.json +20 -0
  38. package/admin/src/translations/uk.json +23 -0
  39. package/admin/src/translations/vi.json +24 -0
  40. package/admin/src/translations/zh-Hans.json +28 -0
  41. package/admin/src/translations/zh.json +24 -0
  42. package/admin/src/utils/getTrad.js +5 -0
  43. package/admin/src/utils/index.js +2 -0
  44. package/admin/src/utils/openWithNewTab.js +20 -0
  45. package/package.json +66 -0
  46. package/server/bootstrap.js +54 -0
  47. package/server/config/default-plugin-config.js +74 -0
  48. package/server/config/index.js +7 -0
  49. package/server/controllers/documentation.js +241 -0
  50. package/server/controllers/index.js +7 -0
  51. package/server/index.js +17 -0
  52. package/server/middlewares/documentation.js +25 -0
  53. package/server/middlewares/index.js +7 -0
  54. package/server/middlewares/restrict-access.js +24 -0
  55. package/server/public/index.html +70 -0
  56. package/server/public/login.html +145 -0
  57. package/server/register.js +11 -0
  58. package/server/routes/index.js +84 -0
  59. package/server/services/documentation.js +209 -0
  60. package/server/services/helpers/build-api-endpoint-path.js +185 -0
  61. package/server/services/helpers/build-component-schema.js +159 -0
  62. package/server/services/helpers/index.js +9 -0
  63. package/server/services/helpers/utils/clean-schema-attributes.js +212 -0
  64. package/server/services/helpers/utils/get-api-responses.js +105 -0
  65. package/server/services/helpers/utils/get-schema-data.js +32 -0
  66. package/server/services/helpers/utils/loop-content-type-names.js +53 -0
  67. package/server/services/helpers/utils/pascal-case.js +9 -0
  68. package/server/services/helpers/utils/query-params.js +84 -0
  69. package/server/services/helpers/utils/routes.js +10 -0
  70. package/server/services/index.js +7 -0
  71. package/strapi-admin.js +3 -0
  72. package/strapi-server.js +3 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015-present Strapi Solutions SAS
2
+
3
+ Portions of the Strapi software are licensed as follows:
4
+
5
+ * All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
6
+
7
+ * All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
8
+
9
+ MIT Expat License
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Plugin documentation
2
+
3
+ This plugin automates your API documentation creation. It basically generates a swagger file. It follows the [Open API specification version 3.0.1](https://swagger.io/specification/).
4
+
5
+ ## Usage
6
+
7
+ - Config
8
+ - Creating a new documentation version
9
+ - Generated files
10
+ - full_documentation.json structure
11
+ - Overriding the suggested documentation
12
+ - FAQ
13
+ - How does it generate the others plugins documentation ?
14
+ - I have created a route into a common API (like product) that query another model. How to automate this?
15
+ - TODO
16
+
17
+ ### Config
18
+
19
+ Create a `settings.json` file located in `src/extensions/documentation/config` folder where you can specify all your environment variables, licenses, external documentation and so one...
20
+ You can add all the entries listed in the [specification](https://swagger.io/specification/).
21
+
22
+ _NOTE_ if you need to add a custom key you can do it by prefixing your key by `x-{something}`
23
+
24
+ ### Creating a new documentation version
25
+
26
+ In order to create a new version you need to change the `info.version` key in the `settings.json` file.
27
+
28
+ This will automatically create a new version.
29
+
30
+ ### Generated files
31
+
32
+ When you start your server with this plugin installed it will automatically create the following files in your APIs (we will see how it works for the plugins).
33
+
34
+ - api
35
+ - my-api
36
+ - documentation
37
+ - documentationVersion // 1.0.0
38
+ - my-api.json // File containing all the identified path
39
+ - unclassified.json // File containing the manually added paths
40
+ - overrides // Folder to override the generated documentation
41
+ - plugins
42
+ - ...
43
+ - documentation
44
+ - documentation
45
+ - 1.0.0
46
+ - full_documentation.json
47
+
48
+ #### full_documentation.json
49
+
50
+ The combined documentation is merged into the `full_documentation.json` file and it's located in `src/extensions/documentation/documentation/{version}/full_documentation.json`
51
+
52
+ It has the following structure
53
+
54
+ ```
55
+ {
56
+ "openapi": "3.0.0" // do not change this version
57
+ "info": {
58
+ "version": "1.0.0" // change this line to create a new version
59
+ ...
60
+ }
61
+ "x-strapi-config": {
62
+ "path": "/documentation", // Change this line to change to url of the doc
63
+ "showGeneratedFiles": true // Do not change this line at the moment...
64
+ },
65
+ "servers" {} // Your servers config (it will be automated),
66
+ "externalDocs": {},
67
+ "paths": {} // All your Api routes,
68
+ "tags": [] // Group of route
69
+ "components": {} // Default generated components and custom ones
70
+ }
71
+ ```
72
+
73
+ ### Overriding the suggested documentation
74
+
75
+ Currently the plugin writes a json file for each API.
76
+
77
+ In order to customize the responses or to add information to a path you need to create a file in the associated `overrides/<file-name>.json` (the name of the file matters so make sure they are similar). Then you just need to identify the path you want to modify.
78
+ You can modify the default generated tags by adding a new one at the end of the file. Same for the components.
79
+
80
+ **_NOTE 1_**
81
+
82
+ Overriding the `full_documentation.json` is a bad idea since it will be regenerated each time you change a model.
83
+
84
+ **_NOTE 2_**
85
+
86
+ You can modify the `tags`, `paths`, and `components` keys on the generated documentation by providing replacement values. You can see how the API is used in the users-permissions plugin: `packages/plugins/users-permissions/server/register.js`
87
+
88
+ ### FAQ
89
+
90
+ #### How does it generate the others plugins documentation ?
91
+
92
+ In other to reference a plugin's route into the documentation you need to add a `description` key in the `config` object.
93
+
94
+ For example this is the plugin email routes.json file
95
+
96
+ ```
97
+ {
98
+ "routes": [
99
+ {
100
+ "method": "POST",
101
+ "path": "/",
102
+ "handler": "Email.send",
103
+ "config": {
104
+ "policies": [],
105
+ "description": "Send an email",
106
+ "tag": {
107
+ "plugin": "email",
108
+ "name": "Email"
109
+ }
110
+ }
111
+ },
112
+ {
113
+ "method": "GET",
114
+ "path": "/environments",
115
+ "handler": "Email.getEnvironments",
116
+ "config": {
117
+ "policies": []
118
+ }
119
+ },
120
+ {
121
+ "method": "GET",
122
+ "path": "/settings/:environment",
123
+ "handler": "Email.getSettings",
124
+ "config": {
125
+ "policies": []
126
+ }
127
+ },
128
+ {
129
+ "method": "PUT",
130
+ "path": "/settings/:environment",
131
+ "handler": "Email.updateSettings",
132
+ "config": {
133
+ "policies": []
134
+ }
135
+ }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ In this file we have only one route that we want to reference in our documentation (`/`). Usually, the tag object is used for the SWAGGER UI, it will group this route under the `Email - Email` dropdown in the documentation. Furthermore, the algorithm will try to find the model to generate the best response possible. If the model is unknown it generates a response like the following `{ foo: "string" }` that you can easily override later.
141
+
142
+ There's another property to guide the algorithm to create the best response possible, the `actionType` key.
143
+ When we can't know by the controller name the type of the returned response (like `find` and `findOne`) you can specify it with this key. There's an example in `./plugins/users-permissions/config/routes.json`.
144
+
145
+ #### I have created a route in a common API (like product) that query another model. How to automate this ?
146
+
147
+ You can use the `tag` key in your route. If you provide a `tag` which is a string like `"tag": "Product"` the algorithm will know that the end-point retrieves data from the **`Product`** table. Creating a tag object `{ "tag": { "name": "User", "plugin": "User-Permissions } }` will result in generating a response with the **`User`** model from the plugin users-permissions.
148
+
149
+ ---
150
+
151
+ Each entry of the object is easily customisable take look at the users-permissions ones they are a good example on how to do it.
@@ -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,271 @@
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
+ type: 'object',
37
+ properties: {
38
+ data: {
39
+ type: 'object',
40
+ properties: {
41
+ id: { type: 'string' },
42
+ attributes: { type: 'object', properties: { test: { type: 'string' } } },
43
+ },
44
+ },
45
+ meta: { type: 'object' },
46
+ },
47
+ };
48
+
49
+ expect(schemaNames.length).toBe(2);
50
+ expect(pluginResponseName).toBe('UsersPermissionsRoleResponse');
51
+ expect(apiResponseName).toBe('RestaurantResponse');
52
+ expect(pluginResponseValue).toStrictEqual(expectedShape);
53
+ expect(apiResponseValue).toStrictEqual(expectedShape);
54
+ });
55
+
56
+ it('builds the ResponseList schema', () => {
57
+ global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
58
+ { method: 'GET', path: '/test', handler: 'test.find' },
59
+ ];
60
+ global.strapi.api.restaurant.routes.restaurant.routes = [
61
+ { method: 'GET', path: '/test', handler: 'test.find' },
62
+ ];
63
+
64
+ const apiMocks = [
65
+ {
66
+ name: 'users-permissions',
67
+ getter: 'plugin',
68
+ ctNames: ['role'],
69
+ },
70
+ { name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
71
+ ];
72
+
73
+ let schemas = {};
74
+ for (const mock of apiMocks) {
75
+ schemas = {
76
+ ...schemas,
77
+ ...buildComponentSchema(mock),
78
+ };
79
+ }
80
+
81
+ const schemaNames = Object.keys(schemas);
82
+ const pluginListResponseValue = schemas.UsersPermissionsRoleListResponse;
83
+ const apiListResponseValue = schemas.RestaurantListResponse;
84
+
85
+ const expectedShape = {
86
+ type: 'object',
87
+ properties: {
88
+ data: {
89
+ type: 'array',
90
+ items: {
91
+ type: 'object',
92
+ properties: {
93
+ id: { type: 'string' },
94
+ attributes: { type: 'object', properties: { test: { type: 'string' } } },
95
+ },
96
+ },
97
+ },
98
+ meta: {
99
+ type: 'object',
100
+ properties: {
101
+ pagination: {
102
+ properties: {
103
+ page: { type: 'integer' },
104
+ pageSize: { type: 'integer', minimum: 25 },
105
+ pageCount: { type: 'integer', maximum: 1 },
106
+ total: { type: 'integer' },
107
+ },
108
+ },
109
+ },
110
+ },
111
+ },
112
+ };
113
+
114
+ expect(schemaNames.length).toBe(4);
115
+ expect(schemaNames.includes('UsersPermissionsRoleListResponse')).toBe(true);
116
+ expect(schemaNames.includes('RestaurantListResponse')).toBe(true);
117
+ expect(pluginListResponseValue).toStrictEqual(expectedShape);
118
+ expect(apiListResponseValue).toStrictEqual(expectedShape);
119
+ });
120
+
121
+ it('builds the Request schema', () => {
122
+ global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
123
+ { method: 'POST', path: '/test', handler: 'test.create' },
124
+ ];
125
+ global.strapi.api.restaurant.routes.restaurant.routes = [
126
+ { method: 'POST', path: '/test', handler: 'test.create' },
127
+ ];
128
+
129
+ const apiMocks = [
130
+ {
131
+ name: 'users-permissions',
132
+ getter: 'plugin',
133
+ ctNames: ['role'],
134
+ },
135
+ { name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
136
+ ];
137
+
138
+ let schemas = {};
139
+ for (const mock of apiMocks) {
140
+ schemas = {
141
+ ...schemas,
142
+ ...buildComponentSchema(mock),
143
+ };
144
+ }
145
+
146
+ const schemaNames = Object.keys(schemas);
147
+ const pluginListResponseValue = schemas.UsersPermissionsRoleRequest;
148
+ const apiListResponseValue = schemas.RestaurantRequest;
149
+
150
+ const expectedShape = {
151
+ type: 'object',
152
+ required: ['data'],
153
+ properties: {
154
+ data: {
155
+ required: [],
156
+ type: 'object',
157
+ properties: { test: { type: 'string' } },
158
+ },
159
+ },
160
+ };
161
+
162
+ expect(schemaNames.length).toBe(4);
163
+ expect(schemaNames.includes('UsersPermissionsRoleRequest')).toBe(true);
164
+ expect(schemaNames.includes('RestaurantRequest')).toBe(true);
165
+ expect(pluginListResponseValue).toStrictEqual(expectedShape);
166
+ expect(apiListResponseValue).toStrictEqual(expectedShape);
167
+ });
168
+
169
+ it('builds the LocalizationResponse schema', () => {
170
+ global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
171
+ { method: 'GET', path: '/localizations', handler: 'test' },
172
+ ];
173
+ global.strapi.api.restaurant.routes.restaurant.routes = [
174
+ { method: 'GET', path: '/localizations', handler: 'test' },
175
+ ];
176
+
177
+ const apiMocks = [
178
+ {
179
+ name: 'users-permissions',
180
+ getter: 'plugin',
181
+ ctNames: ['role'],
182
+ },
183
+ { name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
184
+ ];
185
+
186
+ let schemas = {};
187
+ for (const mock of apiMocks) {
188
+ schemas = {
189
+ ...schemas,
190
+ ...buildComponentSchema(mock),
191
+ };
192
+ }
193
+
194
+ const schemaNames = Object.keys(schemas);
195
+ const pluginListResponseValue = schemas.UsersPermissionsRoleLocalizationResponse;
196
+ const apiListResponseValue = schemas.RestaurantLocalizationResponse;
197
+
198
+ const expectedShape = {
199
+ type: 'object',
200
+ properties: {
201
+ id: { type: 'string' },
202
+ test: { type: 'string' },
203
+ },
204
+ };
205
+
206
+ expect(schemaNames.length).toBe(4);
207
+ expect(schemaNames.includes('UsersPermissionsRoleLocalizationResponse')).toBe(true);
208
+ expect(schemaNames.includes('RestaurantLocalizationResponse')).toBe(true);
209
+ expect(pluginListResponseValue).toStrictEqual(expectedShape);
210
+ expect(apiListResponseValue).toStrictEqual(expectedShape);
211
+ });
212
+
213
+ it('builds the LocalizationRequest schema', () => {
214
+ global.strapi.plugins['users-permissions'].routes['content-api'].routes = [
215
+ { method: 'POST', path: '/localizations', handler: 'test' },
216
+ ];
217
+ global.strapi.api.restaurant.routes.restaurant.routes = [
218
+ { method: 'POST', path: '/localizations', handler: 'test' },
219
+ ];
220
+
221
+ const apiMocks = [
222
+ {
223
+ name: 'users-permissions',
224
+ getter: 'plugin',
225
+ ctNames: ['role'],
226
+ },
227
+ { name: 'restaurant', getter: 'api', ctNames: ['restaurant'] },
228
+ ];
229
+
230
+ let schemas = {};
231
+ for (const mock of apiMocks) {
232
+ schemas = {
233
+ ...schemas,
234
+ ...buildComponentSchema(mock),
235
+ };
236
+ }
237
+
238
+ const schemaNames = Object.keys(schemas);
239
+ const pluginListResponseValue = schemas.UsersPermissionsRoleLocalizationRequest;
240
+ const apiListResponseValue = schemas.RestaurantLocalizationRequest;
241
+
242
+ const expectedShape = {
243
+ type: 'object',
244
+ required: ['locale'],
245
+ properties: { test: { type: 'string' } },
246
+ };
247
+
248
+ expect(schemaNames.length).toBe(8);
249
+ expect(schemaNames.includes('UsersPermissionsRoleLocalizationRequest')).toBe(true);
250
+ expect(schemaNames.includes('RestaurantLocalizationRequest')).toBe(true);
251
+ expect(pluginListResponseValue).toStrictEqual(expectedShape);
252
+ expect(apiListResponseValue).toStrictEqual(expectedShape);
253
+ });
254
+
255
+ it('creates the correct name given multiple content types', () => {
256
+ const apiMock = {
257
+ name: 'users-permissions',
258
+ getter: 'plugin',
259
+ ctNames: ['permission', 'role', 'user'],
260
+ };
261
+
262
+ const schemas = buildComponentSchema(apiMock);
263
+ const schemaNames = Object.keys(schemas);
264
+ const [permission, role, user] = schemaNames;
265
+
266
+ expect(schemaNames.length).toBe(3);
267
+ expect(permission).toBe('UsersPermissionsPermissionResponse');
268
+ expect(role).toBe('UsersPermissionsRoleResponse');
269
+ expect(user).toBe('UsersPermissionsUserResponse');
270
+ });
271
+ });
@@ -0,0 +1,14 @@
1
+ import styled from 'styled-components';
2
+ import { FieldAction } from '@strapi/design-system/Field';
3
+
4
+ const FieldActionWrapper = styled(FieldAction)`
5
+ svg {
6
+ height: 1rem;
7
+ width: 1rem;
8
+ path {
9
+ fill: ${({ theme }) => theme.colors.neutral600};
10
+ }
11
+ }
12
+ `;
13
+
14
+ export default FieldActionWrapper;
@@ -0,0 +1,12 @@
1
+ /**
2
+ *
3
+ * PluginIcon
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ import Information from '@strapi/icons/Information';
9
+
10
+ const PluginIcon = () => <Information />;
11
+
12
+ export default PluginIcon;
@@ -0,0 +1,80 @@
1
+ // NOTE TO PLUGINS DEVELOPERS:
2
+ // If you modify this file by adding new options to the plugin entry point
3
+ // Here's the file: strapi/docs/3.0.0-beta.x/plugin-development/frontend-field-api.md
4
+ // Here's the file: strapi/docs/3.0.0-beta.x/guides/registering-a-field-in-admin.md
5
+ // Also the strapi-generate-plugins/files/admin/src/index.js needs to be updated
6
+ // IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED
7
+ import { prefixPluginTranslations } from '@strapi/helper-plugin';
8
+ import pluginPkg from '../../package.json';
9
+ import PluginIcon from './components/PluginIcon';
10
+ import pluginPermissions from './permissions';
11
+ import pluginId from './pluginId';
12
+
13
+ const name = pluginPkg.strapi.name;
14
+
15
+ export default {
16
+ register(app) {
17
+ app.addMenuLink({
18
+ to: `/plugins/${pluginId}`,
19
+ icon: PluginIcon,
20
+ intlLabel: {
21
+ id: `${pluginId}.plugin.name`,
22
+ defaultMessage: 'Documentation',
23
+ },
24
+ permissions: pluginPermissions.main,
25
+ async Component() {
26
+ const component = await import(
27
+ /* webpackChunkName: "documentation-page" */ './pages/PluginPage'
28
+ );
29
+
30
+ return component;
31
+ },
32
+ });
33
+
34
+ app.registerPlugin({
35
+ id: pluginId,
36
+ name,
37
+ });
38
+ },
39
+ bootstrap(app) {
40
+ app.addSettingsLink('global', {
41
+ intlLabel: {
42
+ id: `${pluginId}.plugin.name`,
43
+ defaultMessage: 'Documentation',
44
+ },
45
+ id: 'documentation',
46
+ to: `/settings/${pluginId}`,
47
+ async Component() {
48
+ const component = await import(
49
+ /* webpackChunkName: "documentation-settings" */ './pages/SettingsPage'
50
+ );
51
+
52
+ return component;
53
+ },
54
+ permissions: pluginPermissions.main,
55
+ });
56
+ },
57
+ async registerTrads({ locales }) {
58
+ const importedTrads = await Promise.all(
59
+ locales.map((locale) => {
60
+ return import(
61
+ /* webpackChunkName: "documentation-translation-[request]" */ `./translations/${locale}.json`
62
+ )
63
+ .then(({ default: data }) => {
64
+ return {
65
+ data: prefixPluginTranslations(data, pluginId),
66
+ locale,
67
+ };
68
+ })
69
+ .catch(() => {
70
+ return {
71
+ data: {},
72
+ locale,
73
+ };
74
+ });
75
+ })
76
+ );
77
+
78
+ return Promise.resolve(importedTrads);
79
+ },
80
+ };