@strapi/strapi 4.0.0-beta.2 → 4.0.0-beta.20

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 (89) hide show
  1. package/README.md +12 -12
  2. package/bin/strapi.js +6 -1
  3. package/lib/Strapi.js +33 -21
  4. package/lib/commands/build.js +1 -1
  5. package/lib/commands/content-types/list.js +3 -5
  6. package/lib/commands/develop.js +8 -10
  7. package/lib/commands/generate-template.js +4 -5
  8. package/lib/commands/hooks/list.js +3 -5
  9. package/lib/commands/middlewares/list.js +3 -5
  10. package/lib/commands/new.js +3 -1
  11. package/lib/commands/policies/list.js +3 -5
  12. package/lib/commands/services/list.js +22 -0
  13. package/lib/commands/watchAdmin.js +4 -4
  14. package/lib/core/app-configuration/index.js +5 -10
  15. package/lib/core/bootstrap.js +2 -2
  16. package/lib/core/domain/module/index.js +3 -1
  17. package/lib/core/domain/module/validation.js +1 -4
  18. package/lib/core/loaders/admin.js +2 -2
  19. package/lib/core/loaders/apis.js +3 -1
  20. package/lib/core/loaders/plugins/get-enabled-plugins.js +25 -9
  21. package/lib/core/loaders/plugins/index.js +21 -7
  22. package/lib/core/loaders/src-index.js +1 -0
  23. package/lib/core/registries/apis.js +2 -16
  24. package/lib/core/registries/content-types.js +50 -6
  25. package/lib/core/registries/controllers.d.ts +7 -0
  26. package/lib/core/registries/controllers.js +74 -3
  27. package/lib/core/registries/hooks.d.ts +20 -0
  28. package/lib/core/registries/hooks.js +57 -7
  29. package/lib/core/registries/middlewares.d.ts +5 -0
  30. package/lib/core/registries/middlewares.js +61 -2
  31. package/lib/core/registries/policies.d.ts +9 -0
  32. package/lib/core/registries/policies.js +57 -6
  33. package/lib/core/registries/services.d.ts +7 -0
  34. package/lib/core/registries/services.js +67 -11
  35. package/lib/core-api/controller/collection-type.js +38 -11
  36. package/lib/core-api/controller/index.d.ts +25 -0
  37. package/lib/core-api/controller/index.js +30 -11
  38. package/lib/core-api/controller/single-type.js +26 -7
  39. package/lib/core-api/routes/index.js +71 -0
  40. package/lib/core-api/service/collection-type.js +8 -12
  41. package/lib/core-api/service/index.d.ts +21 -0
  42. package/lib/core-api/service/index.js +9 -19
  43. package/lib/core-api/service/pagination.js +7 -2
  44. package/lib/core-api/service/single-type.js +12 -11
  45. package/lib/factories.d.ts +48 -0
  46. package/lib/factories.js +84 -0
  47. package/lib/index.d.ts +1 -0
  48. package/lib/index.js +5 -1
  49. package/lib/middlewares/body.js +33 -0
  50. package/lib/middlewares/compression.js +1 -1
  51. package/lib/middlewares/cors.js +3 -2
  52. package/lib/middlewares/errors.js +24 -119
  53. package/lib/middlewares/favicon.js +3 -3
  54. package/lib/middlewares/index.d.ts +2 -1
  55. package/lib/middlewares/index.js +4 -2
  56. package/lib/middlewares/ip.js +1 -1
  57. package/lib/middlewares/logger.js +1 -1
  58. package/lib/middlewares/powered-by.js +4 -2
  59. package/lib/middlewares/public/index.js +4 -7
  60. package/lib/middlewares/query.js +46 -0
  61. package/lib/middlewares/responses.js +2 -2
  62. package/lib/middlewares/security.js +29 -3
  63. package/lib/middlewares/session/index.js +1 -1
  64. package/lib/services/auth/index.js +1 -6
  65. package/lib/services/entity-service/attributes/index.js +31 -0
  66. package/lib/services/entity-service/attributes/transforms.js +20 -0
  67. package/lib/services/entity-service/components.js +2 -3
  68. package/lib/services/entity-service/index.d.ts +1 -1
  69. package/lib/services/entity-service/index.js +83 -27
  70. package/lib/services/entity-service/params.js +37 -87
  71. package/lib/services/entity-validator/index.js +76 -43
  72. package/lib/services/entity-validator/validators.js +129 -43
  73. package/lib/services/errors.js +77 -0
  74. package/lib/services/metrics/index.js +37 -35
  75. package/lib/services/server/compose-endpoint.js +39 -11
  76. package/lib/services/server/content-api.js +1 -1
  77. package/lib/services/server/index.js +4 -9
  78. package/lib/services/server/koa.js +64 -0
  79. package/lib/services/server/middleware.js +8 -1
  80. package/lib/services/server/policy.js +8 -10
  81. package/lib/services/server/register-middlewares.js +7 -2
  82. package/lib/services/server/register-routes.js +1 -3
  83. package/lib/services/server/routing.js +13 -0
  84. package/lib/utils/get-dirs.js +1 -0
  85. package/lib/utils/signals.js +24 -0
  86. package/package.json +22 -17
  87. package/lib/core/app-configuration/load-functions.js +0 -28
  88. package/lib/core-api/index.js +0 -39
  89. package/lib/middlewares/request.js +0 -74
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { yup } = require('@strapi/utils');
4
+
4
5
  const { resolveMiddlewares } = require('./middleware');
5
6
 
6
7
  /**
@@ -15,7 +16,8 @@ const defaultConfig = [
15
16
  'strapi::cors',
16
17
  'strapi::poweredBy',
17
18
  'strapi::logger',
18
- 'strapi::request',
19
+ 'strapi::query',
20
+ 'strapi::body',
19
21
  'strapi::favicon',
20
22
  'strapi::public',
21
23
  ];
@@ -24,7 +26,8 @@ const requiredMiddlewares = [
24
26
  'strapi::errors',
25
27
  'strapi::security',
26
28
  'strapi::cors',
27
- 'strapi::request',
29
+ 'strapi::query',
30
+ 'strapi::body',
28
31
  'strapi::public',
29
32
  'strapi::favicon',
30
33
  ];
@@ -63,6 +66,8 @@ const registerApplicationMiddlewares = async strapi => {
63
66
 
64
67
  checkRequiredMiddlewares(middlewares);
65
68
 
69
+ // NOTE: exclude middlewares that return nothing.
70
+ // this is used for middlewares that only extend the app only need to be added in certain conditions
66
71
  for (const middleware of middlewares) {
67
72
  strapi.server.use(middleware.handler);
68
73
  }
@@ -6,12 +6,10 @@ const createRouteScopeGenerator = namespace => route => {
6
6
  const prefix = namespace.endsWith('::') ? namespace : `${namespace}.`;
7
7
 
8
8
  if (typeof route.handler === 'string') {
9
- const [controller, action] = route.handler.split('.');
10
-
11
9
  _.defaultsDeep(route, {
12
10
  config: {
13
11
  auth: {
14
- scope: `${prefix}${controller}.${action}`,
12
+ scope: [`${route.handler.startsWith(prefix) ? '' : prefix}${route.handler}`],
15
13
  },
16
14
  },
17
15
  });
@@ -44,6 +44,18 @@ const routeSchema = yup.object({
44
44
  }),
45
45
  config: yup
46
46
  .object({
47
+ auth: yup.lazy(value => {
48
+ if (value === false) {
49
+ return yup.boolean().required();
50
+ }
51
+
52
+ return yup.object({
53
+ scope: yup
54
+ .array()
55
+ .of(yup.string())
56
+ .required(),
57
+ });
58
+ }),
47
59
  policies: yup
48
60
  .array()
49
61
  .of(policyOrMiddlewareSchema)
@@ -76,6 +88,7 @@ const createRouteManager = (strapi, opts = {}) => {
76
88
  const createRoute = (route, router) => {
77
89
  validateRouteConfig(route);
78
90
 
91
+ // NOTE: the router type is used to tag controller actions and for authentication / authorization so we need to pass this info down to the route level
79
92
  _.set(route, 'info.type', type || 'admin');
80
93
 
81
94
  composeEndpoint(route, { router });
@@ -11,6 +11,7 @@ const getDirs = root => ({
11
11
  policies: join(root, 'src', 'policies'),
12
12
  middlewares: join(root, 'src', 'middlewares'),
13
13
  config: join(root, 'config'),
14
+ public: join(root, 'public'),
14
15
  });
15
16
 
16
17
  module.exports = getDirs;
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ const destroyOnSignal = strapi => {
4
+ let signalReceived = false;
5
+
6
+ // For unknown reasons, we receive signals 2 times.
7
+ // As a temporary fix, we ignore the signals received after the first one.
8
+
9
+ const terminateStrapi = async () => {
10
+ if (!signalReceived) {
11
+ signalReceived = true;
12
+ await strapi.destroy();
13
+ process.exit();
14
+ }
15
+ };
16
+
17
+ ['SIGTERM', 'SIGINT'].forEach(signal => {
18
+ process.on(signal, terminateStrapi);
19
+ });
20
+ };
21
+
22
+ module.exports = {
23
+ destroyOnSignal,
24
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.0.0-beta.2",
3
+ "version": "4.0.0-beta.20",
4
4
  "description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MySQL, MariaDB, PostgreSQL, SQLite",
5
5
  "keywords": [
6
6
  "strapi",
@@ -53,13 +53,13 @@
53
53
  },
54
54
  "license": "SEE LICENSE IN LICENSE",
55
55
  "author": {
56
- "name": "Strapi team",
56
+ "name": "Strapi Solutions SAS",
57
57
  "email": "hi@strapi.io",
58
58
  "url": "https://strapi.io"
59
59
  },
60
60
  "maintainers": [
61
61
  {
62
- "name": "Strapi team",
62
+ "name": "Strapi Solutions SAS",
63
63
  "email": "hi@strapi.io",
64
64
  "url": "https://strapi.io"
65
65
  }
@@ -77,19 +77,19 @@
77
77
  "postinstall": "node lib/utils/success.js"
78
78
  },
79
79
  "dependencies": {
80
- "@hapi/boom": "9.1.4",
81
80
  "@koa/cors": "3.1.0",
82
81
  "@koa/router": "10.1.1",
83
- "@strapi/admin": "4.0.0-beta.2",
84
- "@strapi/database": "4.0.0-beta.2",
85
- "@strapi/generate-new": "4.0.0-beta.2",
86
- "@strapi/generators": "4.0.0-beta.2",
87
- "@strapi/logger": "4.0.0-beta.2",
88
- "@strapi/plugin-content-manager": "4.0.0-beta.2",
89
- "@strapi/plugin-content-type-builder": "4.0.0-beta.2",
90
- "@strapi/plugin-email": "4.0.0-beta.2",
91
- "@strapi/plugin-upload": "4.0.0-beta.2",
92
- "@strapi/utils": "4.0.0-beta.2",
82
+ "@strapi/admin": "4.0.0-beta.20",
83
+ "@strapi/database": "4.0.0-beta.20",
84
+ "@strapi/generate-new": "4.0.0-beta.20",
85
+ "@strapi/generators": "4.0.0-beta.20",
86
+ "@strapi/logger": "4.0.0-beta.20",
87
+ "@strapi/plugin-content-manager": "4.0.0-beta.20",
88
+ "@strapi/plugin-content-type-builder": "4.0.0-beta.20",
89
+ "@strapi/plugin-email": "4.0.0-beta.20",
90
+ "@strapi/plugin-upload": "4.0.0-beta.20",
91
+ "@strapi/utils": "4.0.0-beta.20",
92
+ "bcryptjs": "2.4.3",
93
93
  "boxen": "5.1.2",
94
94
  "chalk": "4.1.2",
95
95
  "chokidar": "3.5.2",
@@ -103,7 +103,8 @@
103
103
  "execa": "5.1.1",
104
104
  "fs-extra": "10.0.0",
105
105
  "glob": "7.2.0",
106
- "inquirer": "8.1.5",
106
+ "http-errors": "1.8.0",
107
+ "inquirer": "8.2.0",
107
108
  "is-docker": "2.2.1",
108
109
  "koa": "2.13.3",
109
110
  "koa-body": "4.2.0",
@@ -123,11 +124,15 @@
123
124
  "package-json": "7.0.0",
124
125
  "qs": "6.10.1",
125
126
  "resolve-cwd": "3.0.0",
126
- "semver": "7.3.5"
127
+ "semver": "7.3.5",
128
+ "statuses": "2.0.1"
129
+ },
130
+ "devDependencies": {
131
+ "supertest": "^6.1.6"
127
132
  },
128
133
  "engines": {
129
134
  "node": ">=12.x.x <=16.x.x",
130
135
  "npm": ">=6.0.0"
131
136
  },
132
- "gitHead": "020680cbb38b6281b3e16df264b9388a087b2b49"
137
+ "gitHead": "b4993dab9f6dbc583709167f459b6f00e0b4baa6"
133
138
  }
@@ -1,28 +0,0 @@
1
- 'use strict';
2
-
3
- const { join, extname, basename } = require('path');
4
- const fse = require('fs-extra');
5
-
6
- module.exports = function loadFunctions(dir) {
7
- const functions = {};
8
-
9
- if (!fse.pathExistsSync(dir)) {
10
- return functions;
11
- }
12
-
13
- const paths = fse.readdirSync(dir, { withFileTypes: true });
14
-
15
- for (const fd of paths) {
16
- const { name } = fd;
17
- const fullPath = join(dir, name);
18
-
19
- if (fd.isDirectory()) {
20
- functions[name] = loadFunctions(fullPath);
21
- } else if (fd.isFile() && extname(name) === '.js') {
22
- const key = basename(name, '.js');
23
- functions[key] = require(fullPath);
24
- }
25
- }
26
-
27
- return functions;
28
- };
@@ -1,39 +0,0 @@
1
- /**
2
- * Core API
3
- */
4
- 'use strict';
5
-
6
- const _ = require('lodash');
7
-
8
- const createController = require('./controller');
9
- const { createService } = require('./service');
10
-
11
- /**
12
- * Returns a service and a controller built based on the content type passed
13
- *
14
- * @param {object} opts options
15
- * @param {object} opts.api api
16
- * @param {object} opts.model model
17
- * @param {object} opts.strapi strapi
18
- * @returns {object} controller & service
19
- */
20
- function createCoreApi({ api, model, strapi }) {
21
- const { modelName } = model;
22
-
23
- // find corresponding service and controller
24
- const userService = _.get(api, ['services', modelName], {});
25
- const userController = _.get(api, ['controllers', modelName], {});
26
-
27
- const service = Object.assign(createService({ model, strapi }), userService);
28
-
29
- const controller = Object.assign(createController({ service, model }), userController);
30
-
31
- return {
32
- service,
33
- controller,
34
- };
35
- }
36
-
37
- module.exports = {
38
- createCoreApi,
39
- };
@@ -1,74 +0,0 @@
1
- 'use strict';
2
-
3
- const { defaultsDeep } = require('lodash/fp');
4
- const body = require('koa-body');
5
- const qs = require('qs');
6
-
7
- const defaults = {
8
- multipart: true,
9
- queryStringParser: {
10
- strictNullHandling: true,
11
- arrayLimit: 100,
12
- depth: 20,
13
- },
14
- };
15
-
16
- /**
17
- * Body parser hook
18
- */
19
- const addQsParser = (app, settings) => {
20
- Object.defineProperty(app.request, 'query', {
21
- configurable: false,
22
- enumerable: true,
23
- /*
24
- * Get parsed query-string.
25
- */
26
- get() {
27
- const qstr = this.querystring;
28
- const cache = (this._querycache = this._querycache || {});
29
- return cache[qstr] || (cache[qstr] = qs.parse(qstr, settings));
30
- },
31
-
32
- /*
33
- * Set query-string as an object.
34
- */
35
- set(obj) {
36
- this.querystring = qs.stringify(obj);
37
- },
38
- });
39
-
40
- return app;
41
- };
42
-
43
- /**
44
- * @type {import('./').MiddlewareFactory}
45
- */
46
- module.exports = (options, { strapi }) => {
47
- const { queryStringParser, ...bodyOptions } = defaultsDeep(defaults, options);
48
-
49
- addQsParser(strapi.server.app, queryStringParser);
50
-
51
- return async (ctx, next) => {
52
- // TODO: find a better way later
53
- if (ctx.url === '/graphql') {
54
- return next();
55
- }
56
-
57
- try {
58
- return body({ patchKoa: true, ...bodyOptions })(ctx, next);
59
- } catch (e) {
60
- if ((e || {}).message && e.message.includes('maxFileSize exceeded')) {
61
- throw strapi.errors.entityTooLarge('FileTooBig', {
62
- errors: [
63
- {
64
- id: 'parser.file.status.sizeLimit',
65
- message: `file is bigger than the limit size!`,
66
- },
67
- ],
68
- });
69
- }
70
-
71
- throw e;
72
- }
73
- };
74
- };