@strapi/plugin-documentation 0.0.0-d0fee44d6f → 0.0.0-d36609ff26fb4e00a41a7e2b657f16c7466203fe

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 (33) hide show
  1. package/__tests__/build-component-schema.test.js +8 -8
  2. package/admin/src/index.js +3 -3
  3. package/admin/src/pages/PluginPage/index.js +3 -3
  4. package/admin/src/pages/PluginPage/tests/index.test.js +1 -1
  5. package/admin/src/pages/SettingsPage/index.js +3 -3
  6. package/admin/src/pages/SettingsPage/tests/index.test.js +1 -1
  7. package/admin/src/pages/utils/api.js +1 -1
  8. package/admin/src/pages/utils/useReactQuery.js +3 -3
  9. package/admin/src/translations/dk.json +1 -1
  10. package/admin/src/translations/en.json +1 -1
  11. package/admin/src/translations/es.json +1 -1
  12. package/admin/src/translations/ko.json +1 -1
  13. package/admin/src/translations/pl.json +1 -1
  14. package/admin/src/translations/sv.json +39 -0
  15. package/admin/src/translations/tr.json +37 -18
  16. package/admin/src/translations/zh.json +20 -5
  17. package/admin/src/utils/getTrad.js +1 -1
  18. package/admin/src/utils/openWithNewTab.js +1 -1
  19. package/package.json +12 -8
  20. package/server/bootstrap.js +2 -4
  21. package/server/controllers/documentation.js +3 -6
  22. package/server/public/index.html +27 -14
  23. package/server/public/login.html +131 -121
  24. package/server/routes/index.js +1 -0
  25. package/server/services/documentation.js +8 -7
  26. package/server/services/helpers/build-api-endpoint-path.js +10 -10
  27. package/server/services/helpers/build-component-schema.js +82 -22
  28. package/server/services/helpers/utils/clean-schema-attributes.js +51 -28
  29. package/server/services/helpers/utils/get-schema-data.js +2 -2
  30. package/server/services/helpers/utils/loop-content-type-names.js +1 -0
  31. package/server/services/helpers/utils/pascal-case.js +1 -1
  32. package/server/services/helpers/utils/query-params.js +22 -1
  33. package/server/services/helpers/utils/routes.js +2 -2
@@ -1,135 +1,145 @@
1
- <!DOCTYPE html><html><head>
2
- <title>Login - Documentation</title>
3
- <link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet">
4
- <style>
5
- html {
6
- font-size: 62.5%;
7
- height: 100%;
8
- margin: 0;
9
- padding: 0;
10
- }
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Login - Documentation</title>
5
+ <link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" />
6
+ <style>
7
+ html {
8
+ font-size: 62.5%;
9
+ height: 100%;
10
+ margin: 0;
11
+ padding: 0;
12
+ }
11
13
 
12
- body {
13
- height: 100%;
14
- margin: 0;
15
- background-color: #ffffff;
16
- font-family: 'Lato';
17
- font-size: 1.4rem;
18
- font-weight: 400;
19
- text-rendering: optimizeLegibility;
20
- -webkit-font-smoothing: antialiased;
21
- -moz-osx-font-smoothing: grayscale;
22
- }
14
+ body {
15
+ height: 100%;
16
+ margin: 0;
17
+ background-color: #ffffff;
18
+ font-family: 'Lato';
19
+ font-size: 1.4rem;
20
+ font-weight: 400;
21
+ text-rendering: optimizeLegibility;
22
+ -webkit-font-smoothing: antialiased;
23
+ -moz-osx-font-smoothing: grayscale;
24
+ }
23
25
 
24
- .login {
25
- height: 100%;
26
- background-color: #F6F9FC;
27
- }
26
+ .login {
27
+ height: 100%;
28
+ background-color: #f6f9fc;
29
+ }
28
30
 
29
- .login .login-form {
30
- height: calc(100% - 70px);
31
- padding: 68px 0 0;
32
- text-align: center;
33
- }
31
+ .login .login-form {
32
+ height: calc(100% - 70px);
33
+ padding: 68px 0 0;
34
+ text-align: center;
35
+ }
34
36
 
35
- .login .login-form form {
36
- position: relative;
37
- max-width: 460px;
38
- padding: 26px 30px;
39
- margin: 55px auto 0;
40
- background-color: #ffffff;
41
- border-radius: 3px;
42
- box-shadow: 0px 2px 4px rgba(91, 107, 174, .15);
43
- text-align: center;
44
- }
37
+ .login .login-form form {
38
+ position: relative;
39
+ max-width: 460px;
40
+ padding: 26px 30px;
41
+ margin: 55px auto 0;
42
+ background-color: #ffffff;
43
+ border-radius: 3px;
44
+ box-shadow: 0px 2px 4px rgba(91, 107, 174, 0.15);
45
+ text-align: center;
46
+ }
45
47
 
46
- .login .login-form form:before {
47
- position: absolute;
48
- content: '';
49
- top: 0px;
50
- left: 0;
51
- display: inline-block;
52
- width: 100%;
53
- height: 2px;
54
- background-color: #2B66CC;
55
- }
48
+ .login .login-form form:before {
49
+ position: absolute;
50
+ content: '';
51
+ top: 0px;
52
+ left: 0;
53
+ display: inline-block;
54
+ width: 100%;
55
+ height: 2px;
56
+ background-color: #2b66cc;
57
+ }
56
58
 
57
- .login .login-form form .error {
58
- display: block;
59
- color: #FF4E00;
60
- padding-bottom: 20px;
61
- }
59
+ .login .login-form form .error {
60
+ display: block;
61
+ color: #ff4e00;
62
+ padding-bottom: 20px;
63
+ }
62
64
 
63
- .login .login-form .sub-title {
64
- margin-top: 35px;
65
- font-size: 1.6rem;
66
- font-weight: 400;
67
- }
65
+ .login .login-form .sub-title {
66
+ margin-top: 35px;
67
+ font-size: 1.6rem;
68
+ font-weight: 400;
69
+ }
68
70
 
69
- .login .login-form .logo{
70
- max-height: 40px;
71
- }
71
+ .login .login-form .logo {
72
+ max-height: 40px;
73
+ }
72
74
 
73
- .login .login-form form label {
74
- display: block;
75
- margin-bottom: 18px;
76
- width: 100%;
77
- text-align: left;
78
- font-weight: 600;
79
- }
75
+ .login .login-form form label {
76
+ display: block;
77
+ margin-bottom: 18px;
78
+ width: 100%;
79
+ text-align: left;
80
+ font-weight: 600;
81
+ }
80
82
 
81
- .login .login-form form input {
82
- outline: none;
83
- width: calc(100% - 30px);
84
- height: 36px;
85
- padding: 0 15px;
86
- border: 1px solid #ECECEC;
87
- border-radius: 2px;
88
- margin-bottom: 20px;
89
- line-height: 36px;
90
- text-align: left;
91
- }
83
+ .login .login-form form input {
84
+ outline: none;
85
+ width: calc(100% - 30px);
86
+ height: 36px;
87
+ padding: 0 15px;
88
+ border: 1px solid #ececec;
89
+ border-radius: 2px;
90
+ margin-bottom: 20px;
91
+ line-height: 36px;
92
+ text-align: left;
93
+ }
92
94
 
93
- .login .login-form form input[type=submit] {
94
- cursor: pointer;
95
- display: inline-block;
96
- width: auto;
97
- margin: 12px auto 0;
98
- padding: 0 75px;
99
- background: transparent;
100
- border-radius: 36px;
101
- border: 1px solid #2B66CC;
102
- color: #2B66CC;
103
- text-transform: uppercase;
104
- font-size: 1.4rem;
105
- font-weight: 700;
106
- transition: all .2s ease-out;
107
- }
95
+ .login .login-form form input[type='submit'] {
96
+ cursor: pointer;
97
+ display: inline-block;
98
+ width: auto;
99
+ margin: 12px auto 0;
100
+ padding: 0 75px;
101
+ background: transparent;
102
+ border-radius: 36px;
103
+ border: 1px solid #2b66cc;
104
+ color: #2b66cc;
105
+ text-transform: uppercase;
106
+ font-size: 1.4rem;
107
+ font-weight: 700;
108
+ transition: all 0.2s ease-out;
109
+ }
108
110
 
109
- .login .login-form form input[type=submit]:hover {
110
- background: #2B66CC;
111
- color: #ffffff;
112
- }
113
- </style>
114
- </head>
115
- <body>
116
- <div class="login">
117
- <section class="login-form">
118
- <div class="container">
119
- <div class="row">
120
- <div class="col-lg-6 col-lg-offset-3 col-md-12">
121
- <img alt="Strapi logo" class="logo" src="https://strapi.io/assets/images/logo_login.png">
122
- <h2 class="sub-title">Enter the password to access the documentation.</h2>
123
- <form method="post" action="<%=actionUrl%>">
124
- <span class="error">Wrong password...</span>
125
- <label>Password</label>
126
- <input type="password" name="password" placeholder="&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;">
127
- <input type="submit" value="Login">
128
- </form>
129
- </div>
111
+ .login .login-form form input[type='submit']:hover {
112
+ background: #2b66cc;
113
+ color: #ffffff;
114
+ }
115
+ </style>
116
+ </head>
117
+ <body>
118
+ <div class="login">
119
+ <section class="login-form">
120
+ <div class="container">
121
+ <div class="row">
122
+ <div class="col-lg-6 col-lg-offset-3 col-md-12">
123
+ <img
124
+ alt="Strapi logo"
125
+ class="logo"
126
+ src="https://strapi.io/assets/images/logo_login.png"
127
+ />
128
+ <h2 class="sub-title">Enter the password to access the documentation.</h2>
129
+ <form method="post" action="<%=actionUrl%>">
130
+ <span class="error">Wrong password...</span>
131
+ <label>Password</label>
132
+ <input
133
+ type="password"
134
+ name="password"
135
+ placeholder="&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;&#x2022;"
136
+ />
137
+ <input type="submit" value="Login" />
138
+ </form>
130
139
  </div>
131
140
  </div>
132
- </section>
133
- </div>
134
-
135
- </body></html>
141
+ </div>
142
+ </section>
143
+ </div>
144
+ </body>
145
+ </html>
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+
2
3
  const restrictAccess = require('../middlewares/restrict-access');
3
4
 
4
5
  module.exports = [
@@ -15,12 +15,13 @@ module.exports = ({ strapi }) => {
15
15
 
16
16
  return {
17
17
  registerDoc(doc) {
18
+ let registeredDoc = doc;
18
19
  // parseYaml
19
20
  if (typeof doc === 'string') {
20
- doc = require('yaml').parse(doc);
21
+ registeredDoc = require('yaml').parse(registeredDoc);
21
22
  }
22
23
  // receive an object we can register it directly
23
- registeredDocs.push(doc);
24
+ registeredDocs.push(registeredDoc);
24
25
  },
25
26
  getDocumentationVersion() {
26
27
  return _.get(config, 'info.version');
@@ -38,7 +39,7 @@ module.exports = ({ strapi }) => {
38
39
  getDocumentationVersions() {
39
40
  return fs
40
41
  .readdirSync(this.getFullDocumentationPath())
41
- .map(version => {
42
+ .map((version) => {
42
43
  try {
43
44
  const doc = JSON.parse(
44
45
  fs.readFileSync(
@@ -52,7 +53,7 @@ module.exports = ({ strapi }) => {
52
53
  return null;
53
54
  }
54
55
  })
55
- .filter(x => x);
56
+ .filter((x) => x);
56
57
  },
57
58
 
58
59
  /**
@@ -99,7 +100,7 @@ module.exports = ({ strapi }) => {
99
100
 
100
101
  getPluginAndApiInfo() {
101
102
  const plugins = _.get(config, 'x-strapi-config.plugins');
102
- const pluginsToDocument = plugins.map(plugin => {
103
+ const pluginsToDocument = plugins.map((plugin) => {
103
104
  return {
104
105
  name: plugin,
105
106
  getter: 'plugin',
@@ -107,7 +108,7 @@ module.exports = ({ strapi }) => {
107
108
  };
108
109
  });
109
110
 
110
- const apisToDocument = Object.keys(strapi.api).map(api => {
111
+ const apisToDocument = Object.keys(strapi.api).map((api) => {
111
112
  return {
112
113
  name: api,
113
114
  getter: 'api',
@@ -186,7 +187,7 @@ module.exports = ({ strapi }) => {
186
187
 
187
188
  const finalDoc = { ...config, paths };
188
189
 
189
- registeredDocs.forEach(doc => {
190
+ registeredDocs.forEach((doc) => {
190
191
  // Add tags
191
192
  finalDoc.tags = finalDoc.tags || [];
192
193
  finalDoc.tags.push(...(doc.tags || []));
@@ -15,12 +15,12 @@ const { hasFindMethod, isLocalizedPath } = require('./utils/routes');
15
15
  * @param {string} routePath - The route's path property
16
16
  * @returns {string}
17
17
  */
18
- const parsePathWithVariables = routePath => {
18
+ const parsePathWithVariables = (routePath) => {
19
19
  return pathToRegexp
20
20
  .parse(routePath)
21
- .map(token => {
21
+ .map((token) => {
22
22
  if (_.isObject(token)) {
23
- return token.prefix + '{' + token.name + '}';
23
+ return `${token.prefix}{${token.name}}`;
24
24
  }
25
25
 
26
26
  return token;
@@ -35,18 +35,18 @@ const parsePathWithVariables = routePath => {
35
35
  *
36
36
  * @returns {object } Swagger path params object
37
37
  */
38
- const getPathParams = routePath => {
38
+ const getPathParams = (routePath) => {
39
39
  return pathToRegexp
40
40
  .parse(routePath)
41
- .filter(token => _.isObject(token))
42
- .map(param => {
41
+ .filter((token) => _.isObject(token))
42
+ .map((param) => {
43
43
  return {
44
44
  name: param.name,
45
45
  in: 'path',
46
46
  description: '',
47
47
  deprecated: false,
48
48
  required: true,
49
- schema: { type: 'string' },
49
+ schema: { type: 'number' },
50
50
  };
51
51
  });
52
52
  };
@@ -83,7 +83,7 @@ const getPathWithPrefix = (prefix, route) => {
83
83
  */
84
84
  const getPaths = ({ routeInfo, uniqueName, contentTypeInfo }) => {
85
85
  // Get the routes for the current content type
86
- const contentTypeRoutes = routeInfo.routes.filter(route => {
86
+ const contentTypeRoutes = routeInfo.routes.filter((route) => {
87
87
  return (
88
88
  route.path.includes(contentTypeInfo.pluralName) ||
89
89
  route.path.includes(contentTypeInfo.singularName)
@@ -152,7 +152,7 @@ const getPaths = ({ routeInfo, uniqueName, contentTypeInfo }) => {
152
152
  *
153
153
  * @returns {object} Open API paths
154
154
  */
155
- const getAllPathsForContentType = apiInfo => {
155
+ const getAllPathsForContentType = (apiInfo) => {
156
156
  let paths = {};
157
157
 
158
158
  const pathsObject = getPaths(apiInfo);
@@ -175,7 +175,7 @@ const getAllPathsForContentType = apiInfo => {
175
175
  *
176
176
  * @returns {object}
177
177
  */
178
- const buildApiEndpointPath = api => {
178
+ const buildApiEndpointPath = (api) => {
179
179
  // A reusable loop for building paths and component schemas
180
180
  // Uses the api param to build a new set of params for each content type
181
181
  // Passes these new params to the function provided
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+
2
3
  const _ = require('lodash');
3
4
 
4
5
  const cleanSchemaAttributes = require('./utils/clean-schema-attributes');
@@ -19,10 +20,24 @@ const { hasFindMethod, isLocalizedPath } = require('./utils/routes');
19
20
  const getAllSchemasForContentType = ({ routeInfo, attributes, uniqueName }) => {
20
21
  // Store response and request schemas in an object
21
22
  let schemas = {};
23
+ let componentSchemas = {};
24
+ // adds a ComponentSchema to the Schemas so it can be used as Ref
25
+ const addComponentSchema = (schemaName, schema) => {
26
+ if (!Object.keys(schema) || !Object.keys(schema.properties)) {
27
+ return false;
28
+ }
29
+ componentSchemas = {
30
+ ...componentSchemas,
31
+ [schemaName]: schema,
32
+ };
33
+ return true;
34
+ };
22
35
  // Get all the route methods
23
- const routeMethods = routeInfo.routes.map(route => route.method);
36
+ const routeMethods = routeInfo.routes.map((route) => route.method);
24
37
  // Check for localized paths
25
- const hasLocalizationPath = routeInfo.routes.filter(route => isLocalizedPath(route.path)).length;
38
+ const hasLocalizationPath = routeInfo.routes.filter((route) =>
39
+ isLocalizedPath(route.path)
40
+ ).length;
26
41
  // When the route methods contain any post or put requests
27
42
  if (routeMethods.includes('POST') || routeMethods.includes('PUT')) {
28
43
  const attributesToOmit = [
@@ -53,7 +68,10 @@ const getAllSchemasForContentType = ({ routeInfo, attributes, uniqueName }) => {
53
68
  [`${pascalCase(uniqueName)}LocalizationRequest`]: {
54
69
  required: [...requiredAttributes, 'locale'],
55
70
  type: 'object',
56
- properties: cleanSchemaAttributes(attributesForRequest, { isRequest: true }),
71
+ properties: cleanSchemaAttributes(attributesForRequest, {
72
+ isRequest: true,
73
+ addComponentSchema,
74
+ }),
57
75
  },
58
76
  };
59
77
  }
@@ -68,7 +86,10 @@ const getAllSchemasForContentType = ({ routeInfo, attributes, uniqueName }) => {
68
86
  data: {
69
87
  required: requiredAttributes,
70
88
  type: 'object',
71
- properties: cleanSchemaAttributes(attributesForRequest, { isRequest: true }),
89
+ properties: cleanSchemaAttributes(attributesForRequest, {
90
+ isRequest: true,
91
+ addComponentSchema,
92
+ }),
72
93
  },
73
94
  },
74
95
  },
@@ -81,30 +102,50 @@ const getAllSchemasForContentType = ({ routeInfo, attributes, uniqueName }) => {
81
102
  [`${pascalCase(uniqueName)}LocalizationResponse`]: {
82
103
  type: 'object',
83
104
  properties: {
84
- id: { type: 'string' },
85
- ...cleanSchemaAttributes(attributes),
105
+ id: { type: 'number' },
106
+ ...cleanSchemaAttributes(attributes, { addComponentSchema }),
86
107
  },
87
108
  },
88
109
  };
89
110
  }
90
111
 
91
112
  // Check for routes that need to return a list
92
- const hasListOfEntities = routeInfo.routes.filter(route => hasFindMethod(route.handler)).length;
113
+ const hasListOfEntities = routeInfo.routes.filter((route) => hasFindMethod(route.handler)).length;
93
114
  if (hasListOfEntities) {
94
115
  // Build the list response schema
95
116
  schemas = {
96
117
  ...schemas,
97
- [`${pascalCase(uniqueName)}ListResponse`]: {
118
+ [`${pascalCase(uniqueName)}ListResponseDataItem`]: {
98
119
  type: 'object',
120
+ properties: {
121
+ id: { type: 'number' },
122
+ attributes: {
123
+ type: 'object',
124
+ properties: cleanSchemaAttributes(attributes, {
125
+ addComponentSchema,
126
+ componentSchemaRefName: `#/components/schemas/${pascalCase(
127
+ uniqueName
128
+ )}ListResponseDataItemLocalized`,
129
+ }),
130
+ },
131
+ },
132
+ },
133
+ [`${pascalCase(uniqueName)}ListResponseDataItemLocalized`]: {
134
+ type: 'object',
135
+ properties: {
136
+ id: { type: 'number' },
137
+ attributes: {
138
+ type: 'object',
139
+ properties: cleanSchemaAttributes(attributes, { addComponentSchema }),
140
+ },
141
+ },
142
+ },
143
+ [`${pascalCase(uniqueName)}ListResponse`]: {
99
144
  properties: {
100
145
  data: {
101
146
  type: 'array',
102
147
  items: {
103
- type: 'object',
104
- properties: {
105
- id: { type: 'string' },
106
- attributes: { type: 'object', properties: cleanSchemaAttributes(attributes) },
107
- },
148
+ $ref: `#/components/schemas/${pascalCase(uniqueName)}ListResponseDataItem`,
108
149
  },
109
150
  },
110
151
  meta: {
@@ -128,25 +169,44 @@ const getAllSchemasForContentType = ({ routeInfo, attributes, uniqueName }) => {
128
169
  // Build the response schema
129
170
  schemas = {
130
171
  ...schemas,
131
- [`${pascalCase(uniqueName)}Response`]: {
172
+ [`${pascalCase(uniqueName)}ResponseDataObject`]: {
132
173
  type: 'object',
133
174
  properties: {
134
- data: {
175
+ id: { type: 'number' },
176
+ attributes: {
135
177
  type: 'object',
136
- properties: {
137
- id: { type: 'string' },
138
- attributes: { type: 'object', properties: cleanSchemaAttributes(attributes) },
139
- },
178
+ properties: cleanSchemaAttributes(attributes, {
179
+ addComponentSchema,
180
+ componentSchemaRefName: `#/components/schemas/${pascalCase(
181
+ uniqueName
182
+ )}ResponseDataObjectLocalized`,
183
+ }),
184
+ },
185
+ },
186
+ },
187
+ [`${pascalCase(uniqueName)}ResponseDataObjectLocalized`]: {
188
+ type: 'object',
189
+ properties: {
190
+ id: { type: 'number' },
191
+ attributes: {
192
+ type: 'object',
193
+ properties: cleanSchemaAttributes(attributes, { addComponentSchema }),
194
+ },
195
+ },
196
+ },
197
+ [`${pascalCase(uniqueName)}Response`]: {
198
+ properties: {
199
+ data: {
200
+ $ref: `#/components/schemas/${pascalCase(uniqueName)}ResponseDataObject`,
140
201
  },
141
202
  meta: { type: 'object' },
142
203
  },
143
204
  },
144
205
  };
145
-
146
- return schemas;
206
+ return { ...schemas, ...componentSchemas };
147
207
  };
148
208
 
149
- const buildComponentSchema = api => {
209
+ const buildComponentSchema = (api) => {
150
210
  // A reusable loop for building paths and component schemas
151
211
  // Uses the api param to build a new set of params for each content type
152
212
  // Passes these new params to the function provided