@strapi/strapi 4.0.0-next.6 → 4.0.0

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 (166) hide show
  1. package/README.md +12 -12
  2. package/bin/strapi.js +41 -60
  3. package/lib/Strapi.js +234 -114
  4. package/lib/commands/build.js +16 -6
  5. package/lib/commands/console.js +1 -1
  6. package/lib/commands/content-types/list.js +22 -0
  7. package/lib/commands/develop.js +17 -18
  8. package/lib/commands/generate-template.js +4 -5
  9. package/lib/commands/hooks/list.js +22 -0
  10. package/lib/commands/middlewares/list.js +22 -0
  11. package/lib/commands/new.js +3 -1
  12. package/lib/commands/policies/list.js +22 -0
  13. package/lib/commands/routes/list.js +28 -0
  14. package/lib/commands/services/list.js +22 -0
  15. package/lib/commands/watchAdmin.js +18 -8
  16. package/lib/container.js +6 -6
  17. package/lib/core/app-configuration/config-loader.js +1 -37
  18. package/lib/core/app-configuration/index.js +6 -46
  19. package/lib/core/app-configuration/load-config-file.js +43 -0
  20. package/lib/core/bootstrap.js +5 -117
  21. package/lib/core/domain/component/index.js +24 -0
  22. package/lib/core/domain/component/validator.js +29 -0
  23. package/lib/core/domain/content-type/index.js +140 -0
  24. package/lib/core/domain/content-type/validator.js +64 -0
  25. package/lib/core/domain/module/index.js +108 -0
  26. package/lib/core/domain/module/validation.js +33 -0
  27. package/lib/core/loaders/admin.js +16 -0
  28. package/lib/core/loaders/apis.js +159 -0
  29. package/lib/core/{load-components.js → loaders/components.js} +5 -7
  30. package/lib/core/loaders/index.js +11 -0
  31. package/lib/core/loaders/middlewares.js +36 -0
  32. package/lib/core/loaders/plugins/get-enabled-plugins.js +116 -0
  33. package/lib/core/loaders/plugins/index.js +123 -0
  34. package/lib/core/loaders/policies.js +28 -0
  35. package/lib/core/loaders/src-index.js +39 -0
  36. package/lib/core/registries/apis.js +29 -0
  37. package/lib/core/{app-configuration/config-provider.js → registries/config.js} +4 -11
  38. package/lib/core/registries/content-types.js +97 -0
  39. package/lib/core/registries/controllers.d.ts +7 -0
  40. package/lib/core/registries/controllers.js +114 -0
  41. package/lib/core/registries/hooks.d.ts +20 -0
  42. package/lib/core/registries/hooks.js +87 -0
  43. package/lib/core/registries/middlewares.d.ts +5 -0
  44. package/lib/core/registries/middlewares.js +89 -0
  45. package/lib/core/registries/modules.js +44 -0
  46. package/lib/core/registries/plugins.js +28 -0
  47. package/lib/core/registries/policies.d.ts +9 -0
  48. package/lib/core/registries/policies.js +89 -0
  49. package/lib/core/registries/services.d.ts +7 -0
  50. package/lib/core/registries/services.js +114 -0
  51. package/lib/core/utils.js +35 -0
  52. package/lib/core-api/controller/collection-type.js +45 -26
  53. package/lib/core-api/controller/index.d.ts +25 -0
  54. package/lib/core-api/controller/index.js +33 -11
  55. package/lib/core-api/controller/single-type.js +29 -15
  56. package/lib/core-api/controller/transform.js +62 -6
  57. package/lib/core-api/routes/index.js +71 -0
  58. package/lib/core-api/service/collection-type.js +43 -21
  59. package/lib/core-api/service/index.d.ts +21 -0
  60. package/lib/core-api/service/index.js +8 -67
  61. package/lib/core-api/service/pagination.js +130 -0
  62. package/lib/core-api/service/single-type.js +17 -19
  63. package/lib/factories.d.ts +48 -0
  64. package/lib/factories.js +84 -0
  65. package/lib/index.d.ts +10 -31
  66. package/lib/index.js +5 -1
  67. package/lib/middlewares/body.js +33 -0
  68. package/lib/middlewares/compression.js +8 -0
  69. package/lib/middlewares/cors.js +58 -0
  70. package/lib/middlewares/errors.js +40 -0
  71. package/lib/middlewares/favicon.js +19 -0
  72. package/lib/middlewares/index.d.ts +5 -0
  73. package/lib/middlewares/index.js +30 -117
  74. package/lib/middlewares/ip.js +8 -0
  75. package/lib/middlewares/logger.js +27 -0
  76. package/lib/middlewares/powered-by.js +20 -0
  77. package/lib/middlewares/public/index.js +98 -73
  78. package/lib/middlewares/query.js +46 -0
  79. package/lib/middlewares/response-time.js +15 -0
  80. package/lib/middlewares/responses.js +19 -0
  81. package/lib/middlewares/security.js +51 -0
  82. package/lib/middlewares/session/index.js +6 -6
  83. package/lib/migrations/draft-publish.js +57 -0
  84. package/lib/services/auth/index.js +87 -0
  85. package/lib/services/core-store.js +64 -51
  86. package/lib/services/cron.js +54 -0
  87. package/lib/services/entity-service/attributes/index.js +31 -0
  88. package/lib/services/entity-service/attributes/transforms.js +20 -0
  89. package/lib/services/entity-service/components.js +39 -15
  90. package/lib/services/entity-service/index.d.ts +91 -0
  91. package/lib/services/entity-service/index.js +120 -59
  92. package/lib/services/entity-service/params.js +52 -94
  93. package/lib/services/entity-validator/index.js +76 -43
  94. package/lib/services/entity-validator/validators.js +129 -43
  95. package/lib/services/errors.js +77 -0
  96. package/lib/{core → services}/fs.js +10 -2
  97. package/lib/services/metrics/index.js +41 -38
  98. package/lib/services/metrics/sender.js +2 -2
  99. package/lib/services/server/admin-api.js +14 -0
  100. package/lib/services/server/api.js +36 -0
  101. package/lib/services/server/compose-endpoint.js +141 -0
  102. package/lib/services/server/content-api.js +16 -0
  103. package/lib/{server.js → services/server/http-server.js} +0 -0
  104. package/lib/services/server/index.js +127 -0
  105. package/lib/services/server/koa.js +64 -0
  106. package/lib/services/server/middleware.js +122 -0
  107. package/lib/services/server/policy.js +32 -0
  108. package/lib/services/server/register-middlewares.js +110 -0
  109. package/lib/services/server/register-routes.js +106 -0
  110. package/lib/services/server/routing.js +120 -0
  111. package/lib/services/utils/upload-files.js +1 -1
  112. package/lib/services/webhook-runner.js +1 -1
  113. package/lib/utils/ee.js +3 -3
  114. package/lib/utils/get-dirs.js +17 -0
  115. package/lib/utils/index.js +2 -0
  116. package/lib/utils/is-initialized.js +1 -1
  117. package/lib/utils/run-checks.js +0 -15
  118. package/lib/utils/signals.js +24 -0
  119. package/lib/utils/startup-logger.js +2 -2
  120. package/lib/utils/update-notifier/index.js +3 -2
  121. package/package.json +93 -96
  122. package/lib/commands/generate.js +0 -76
  123. package/lib/core/index.js +0 -17
  124. package/lib/core/load-apis.js +0 -20
  125. package/lib/core/load-extensions.js +0 -71
  126. package/lib/core/load-functions.js +0 -21
  127. package/lib/core/load-middlewares.js +0 -130
  128. package/lib/core/load-modules.js +0 -55
  129. package/lib/core/load-plugins.js +0 -68
  130. package/lib/core/load-policies.js +0 -36
  131. package/lib/core/walk.js +0 -27
  132. package/lib/core-api/index.js +0 -39
  133. package/lib/load/check-reserved-filename.js +0 -10
  134. package/lib/load/load-config-files.js +0 -22
  135. package/lib/load/require-file-parse.js +0 -15
  136. package/lib/middlewares/boom/defaults.json +0 -5
  137. package/lib/middlewares/boom/index.js +0 -147
  138. package/lib/middlewares/cors/index.js +0 -66
  139. package/lib/middlewares/cron/defaults.json +0 -5
  140. package/lib/middlewares/cron/index.js +0 -43
  141. package/lib/middlewares/favicon/defaults.json +0 -7
  142. package/lib/middlewares/favicon/index.js +0 -32
  143. package/lib/middlewares/gzip/defaults.json +0 -6
  144. package/lib/middlewares/gzip/index.js +0 -19
  145. package/lib/middlewares/helmet/defaults.json +0 -18
  146. package/lib/middlewares/helmet/index.js +0 -9
  147. package/lib/middlewares/ip/defaults.json +0 -7
  148. package/lib/middlewares/ip/index.js +0 -25
  149. package/lib/middlewares/language/defaults.json +0 -9
  150. package/lib/middlewares/language/index.js +0 -40
  151. package/lib/middlewares/logger/defaults.json +0 -5
  152. package/lib/middlewares/logger/index.js +0 -37
  153. package/lib/middlewares/parser/defaults.json +0 -11
  154. package/lib/middlewares/parser/index.js +0 -71
  155. package/lib/middlewares/poweredBy/defaults.json +0 -5
  156. package/lib/middlewares/poweredBy/index.js +0 -16
  157. package/lib/middlewares/public/defaults.json +0 -8
  158. package/lib/middlewares/responseTime/defaults.json +0 -5
  159. package/lib/middlewares/responseTime/index.js +0 -25
  160. package/lib/middlewares/responses/defaults.json +0 -5
  161. package/lib/middlewares/responses/index.js +0 -18
  162. package/lib/middlewares/router/defaults.json +0 -7
  163. package/lib/middlewares/router/index.js +0 -64
  164. package/lib/middlewares/router/utils/composeEndpoint.js +0 -25
  165. package/lib/middlewares/router/utils/routerChecker.js +0 -92
  166. package/lib/utils/get-prefixed-dependencies.js +0 -7
@@ -0,0 +1,122 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const { propOr, isArray, isNil } = require('lodash/fp');
5
+
6
+ const getMiddlewareConfig = propOr([], 'config.middlewares');
7
+
8
+ const resolveRouteMiddlewares = (route, strapi) => {
9
+ const middlewaresConfig = getMiddlewareConfig(route);
10
+
11
+ if (!isArray(middlewaresConfig)) {
12
+ throw new Error('Route middlewares config must be an array');
13
+ }
14
+
15
+ const middlewares = resolveMiddlewares(middlewaresConfig, strapi);
16
+
17
+ return middlewares.map(({ handler }) => handler);
18
+ };
19
+
20
+ /**
21
+ * Initialize every configured middlewares
22
+ * @param {MiddlewaresConfig} config
23
+ * @param {Strapi} strapi
24
+ * @returns {Middlewares}
25
+ */
26
+ const resolveMiddlewares = (config, strapi) => {
27
+ const middlewares = [];
28
+
29
+ for (const item of config) {
30
+ if (typeof item === 'function') {
31
+ middlewares.push({
32
+ name: null,
33
+ handler: item,
34
+ });
35
+
36
+ continue;
37
+ }
38
+
39
+ if (typeof item === 'string') {
40
+ const middlewareFactory = strapi.middleware(item);
41
+
42
+ if (!middlewareFactory) {
43
+ throw new Error(`Middleware ${item} not found.`);
44
+ }
45
+
46
+ middlewares.push({
47
+ name: item,
48
+ handler: middlewareFactory({}, { strapi }),
49
+ });
50
+
51
+ continue;
52
+ }
53
+
54
+ if (typeof item === 'object' && item !== null) {
55
+ const { name, resolve, config = {} } = item;
56
+
57
+ if (name) {
58
+ const middlewareFactory = strapi.middleware(name);
59
+ middlewares.push({
60
+ name,
61
+ handler: middlewareFactory(config, { strapi }),
62
+ });
63
+
64
+ continue;
65
+ }
66
+
67
+ if (resolve) {
68
+ middlewares.push({
69
+ name: resolve,
70
+ handler: resolveCustomMiddleware(resolve, strapi)(config, { strapi }),
71
+ });
72
+
73
+ continue;
74
+ }
75
+
76
+ throw new Error('Invalid middleware configuration. Missing name or resolve properties.');
77
+ }
78
+
79
+ throw new Error(
80
+ 'Middleware config must either be a string or an object {name?: string, resolve?: string, config: any}.'
81
+ );
82
+ }
83
+
84
+ middlewares.forEach(middleware => {
85
+ // NOTE: we replace null middlewares by a dumb one to avoid having to filter later on
86
+ if (isNil(middleware.handler)) {
87
+ middleware.handler = (_, next) => next();
88
+ }
89
+ });
90
+
91
+ return middlewares;
92
+ };
93
+
94
+ /**
95
+ * Resolve middleware from package name or path
96
+ * @param {string} resolve
97
+ * @param {Strapi} strapi
98
+ */
99
+ const resolveCustomMiddleware = (resolve, strapi) => {
100
+ let modulePath;
101
+
102
+ try {
103
+ modulePath = require.resolve(resolve);
104
+ } catch (error) {
105
+ if (error.code === 'MODULE_NOT_FOUND') {
106
+ modulePath = path.resolve(strapi.dirs.root, resolve);
107
+ } else {
108
+ throw error;
109
+ }
110
+ }
111
+
112
+ try {
113
+ return require(modulePath);
114
+ } catch (err) {
115
+ throw new Error(`Could not load middleware "${modulePath}".`);
116
+ }
117
+ };
118
+
119
+ module.exports = {
120
+ resolveRouteMiddlewares,
121
+ resolveMiddlewares,
122
+ };
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ const { propOr } = require('lodash/fp');
4
+ const { ForbiddenError } = require('@strapi/utils').errors;
5
+ const { policy: policyUtils } = require('@strapi/utils');
6
+
7
+ const getPoliciesConfig = propOr([], 'config.policies');
8
+
9
+ const resolvePolicies = route => {
10
+ const policiesConfig = getPoliciesConfig(route);
11
+ const resolvedPolicies = policyUtils.resolve(policiesConfig, route.info);
12
+
13
+ const policiesMiddleware = async (ctx, next) => {
14
+ const context = policyUtils.createPolicyContext('koa', ctx);
15
+
16
+ for (const { handler, config } of resolvedPolicies) {
17
+ const result = await handler(context, config, { strapi });
18
+
19
+ if (![true, undefined].includes(result)) {
20
+ throw new ForbiddenError('Policies failed.');
21
+ }
22
+ }
23
+
24
+ await next();
25
+ };
26
+
27
+ return [policiesMiddleware];
28
+ };
29
+
30
+ module.exports = {
31
+ resolvePolicies,
32
+ };
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ const { yup } = require('@strapi/utils');
4
+
5
+ const { resolveMiddlewares } = require('./middleware');
6
+
7
+ /**
8
+ * @typedef {import('../../').Strapi} Strapi
9
+ * @typedef {Array<string|{name?: string, resolve?: string, config: any}>} MiddlewaresConfig
10
+ * @typedef {Array<{name: string, hanlder: Function}>} Middlewares
11
+ */
12
+
13
+ const defaultConfig = [
14
+ 'strapi::errors',
15
+ 'strapi::security',
16
+ 'strapi::cors',
17
+ 'strapi::poweredBy',
18
+ 'strapi::logger',
19
+ 'strapi::query',
20
+ 'strapi::body',
21
+ 'strapi::favicon',
22
+ 'strapi::public',
23
+ ];
24
+
25
+ const requiredMiddlewares = [
26
+ 'strapi::errors',
27
+ 'strapi::security',
28
+ 'strapi::cors',
29
+ 'strapi::query',
30
+ 'strapi::body',
31
+ 'strapi::public',
32
+ 'strapi::favicon',
33
+ ];
34
+
35
+ const middlewareConfigSchema = yup.array().of(
36
+ yup.lazy(value => {
37
+ if (typeof value === 'string') {
38
+ return yup.string().required();
39
+ }
40
+
41
+ if (typeof value === 'object') {
42
+ return yup
43
+ .object({
44
+ name: yup.string(),
45
+ resolve: yup.string(),
46
+ config: yup.mixed(),
47
+ })
48
+ .required()
49
+ .noUnknown();
50
+ }
51
+
52
+ return yup.test(() => false);
53
+ })
54
+ );
55
+
56
+ /**
57
+ * Register middlewares in router
58
+ * @param {Strapi} strapi
59
+ */
60
+ const registerApplicationMiddlewares = async strapi => {
61
+ const middlewareConfig = strapi.config.get('middlewares', defaultConfig);
62
+
63
+ await validateMiddlewareConfig(middlewareConfig);
64
+
65
+ const middlewares = await resolveMiddlewares(middlewareConfig, strapi);
66
+
67
+ checkRequiredMiddlewares(middlewares);
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
71
+ for (const middleware of middlewares) {
72
+ strapi.server.use(middleware.handler);
73
+ }
74
+ };
75
+
76
+ /**
77
+ *
78
+ * @param {MiddlewaresConfig} config
79
+ */
80
+ const validateMiddlewareConfig = async config => {
81
+ try {
82
+ await middlewareConfigSchema.validate(config, { strict: true, abortEarly: false });
83
+ } catch (error) {
84
+ throw new Error(
85
+ 'Invalid middleware configuration. Expected Array<string|{name?: string, resolve?: string, config: any}.'
86
+ );
87
+ }
88
+ };
89
+
90
+ /**
91
+ * Check if some required middlewares are missing in configure middlewares
92
+ * @param {Middlewares} middlewares
93
+ */
94
+ const checkRequiredMiddlewares = middlewares => {
95
+ const missingMiddlewares = requiredMiddlewares.filter(name => {
96
+ return middlewares.findIndex(mdl => mdl.name === name) === -1;
97
+ });
98
+
99
+ if (missingMiddlewares.length > 0) {
100
+ throw new Error(
101
+ `Missing required middlewares in configuration. Add the following middlewares: "${missingMiddlewares.join(
102
+ ', '
103
+ )}".`
104
+ );
105
+ }
106
+
107
+ return;
108
+ };
109
+
110
+ module.exports = registerApplicationMiddlewares;
@@ -0,0 +1,106 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ const createRouteScopeGenerator = namespace => route => {
6
+ const prefix = namespace.endsWith('::') ? namespace : `${namespace}.`;
7
+
8
+ if (typeof route.handler === 'string') {
9
+ _.defaultsDeep(route, {
10
+ config: {
11
+ auth: {
12
+ scope: [`${route.handler.startsWith(prefix) ? '' : prefix}${route.handler}`],
13
+ },
14
+ },
15
+ });
16
+ }
17
+ };
18
+
19
+ /**
20
+ * Register all routes
21
+ * @param {import('../../').Strapi} strapi
22
+ */
23
+ module.exports = strapi => {
24
+ registerAdminRoutes(strapi);
25
+ registerAPIRoutes(strapi);
26
+ registerPluginRoutes(strapi);
27
+ };
28
+
29
+ /**
30
+ * Register admin routes
31
+ * @param {import('../../').Strapi} strapi
32
+ */
33
+ const registerAdminRoutes = strapi => {
34
+ const generateRouteScope = createRouteScopeGenerator(`admin::`);
35
+
36
+ strapi.admin.routes.forEach(route => {
37
+ generateRouteScope(route);
38
+ route.info = { pluginName: 'admin' };
39
+ });
40
+
41
+ strapi.server.routes({
42
+ type: 'admin',
43
+ prefix: '/admin',
44
+ routes: strapi.admin.routes,
45
+ });
46
+ };
47
+
48
+ /**
49
+ * Register plugin routes
50
+ * @param {import('../../').Strapi} strapi
51
+ */
52
+ const registerPluginRoutes = strapi => {
53
+ for (const pluginName in strapi.plugins) {
54
+ const plugin = strapi.plugins[pluginName];
55
+
56
+ const generateRouteScope = createRouteScopeGenerator(`plugin::${pluginName}`);
57
+
58
+ if (Array.isArray(plugin.routes)) {
59
+ plugin.routes.forEach(route => {
60
+ generateRouteScope(route);
61
+ route.info = { pluginName };
62
+ });
63
+
64
+ strapi.server.routes({
65
+ type: 'admin',
66
+ prefix: `/${pluginName}`,
67
+ routes: plugin.routes,
68
+ });
69
+ } else {
70
+ _.forEach(plugin.routes, router => {
71
+ router.type = router.type || 'admin';
72
+ router.prefix = `/${pluginName}`;
73
+ router.routes.forEach(route => {
74
+ generateRouteScope(route);
75
+ route.info = { pluginName };
76
+ });
77
+
78
+ strapi.server.routes(router);
79
+ });
80
+ }
81
+ }
82
+ };
83
+
84
+ /**
85
+ * Register api routes
86
+ * @param {import('../../').Strapi} strapi
87
+ */
88
+ const registerAPIRoutes = strapi => {
89
+ for (const apiName in strapi.api) {
90
+ const api = strapi.api[apiName];
91
+
92
+ const generateRouteScope = createRouteScopeGenerator(`api::${apiName}`);
93
+
94
+ _.forEach(api.routes, router => {
95
+ // TODO: remove once auth setup
96
+ // pass meta down to compose endpoint
97
+ router.type = 'content-api';
98
+ router.routes.forEach(route => {
99
+ generateRouteScope(route);
100
+ route.info = { apiName };
101
+ });
102
+
103
+ return strapi.server.routes(router);
104
+ });
105
+ }
106
+ };
@@ -0,0 +1,120 @@
1
+ 'use strict';
2
+
3
+ const Router = require('@koa/router');
4
+ const _ = require('lodash');
5
+ const { has } = require('lodash/fp');
6
+ const { yup } = require('@strapi/utils');
7
+
8
+ const createEndpointComposer = require('./compose-endpoint');
9
+
10
+ const policyOrMiddlewareSchema = yup.lazy(value => {
11
+ if (typeof value === 'string') {
12
+ return yup.string().required();
13
+ }
14
+
15
+ if (typeof value === 'function') {
16
+ return yup.mixed().isFunction();
17
+ }
18
+
19
+ return yup.object({
20
+ name: yup.string().required(),
21
+ options: yup.object().notRequired(), // any options
22
+ });
23
+ });
24
+
25
+ const routeSchema = yup.object({
26
+ method: yup
27
+ .string()
28
+ .oneOf(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'ALL'])
29
+ .required(),
30
+ path: yup.string().required(),
31
+ handler: yup.lazy(value => {
32
+ if (typeof value === 'string') {
33
+ return yup.string().required();
34
+ }
35
+
36
+ if (Array.isArray(value)) {
37
+ return yup.array().required();
38
+ }
39
+
40
+ return yup
41
+ .mixed()
42
+ .isFunction()
43
+ .required();
44
+ }),
45
+ config: yup
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
+ }),
59
+ policies: yup
60
+ .array()
61
+ .of(policyOrMiddlewareSchema)
62
+ .notRequired(),
63
+ middlewares: yup
64
+ .array()
65
+ .of(policyOrMiddlewareSchema)
66
+ .notRequired(),
67
+ })
68
+ .notRequired(),
69
+ });
70
+
71
+ const validateRouteConfig = routeConfig => {
72
+ try {
73
+ return routeSchema.validateSync(routeConfig, {
74
+ strict: true,
75
+ abortEarly: false,
76
+ stripUnknown: true,
77
+ });
78
+ } catch (error) {
79
+ throw new Error('Invalid route config', error.message);
80
+ }
81
+ };
82
+
83
+ const createRouteManager = (strapi, opts = {}) => {
84
+ const { type } = opts;
85
+
86
+ const composeEndpoint = createEndpointComposer(strapi);
87
+
88
+ const createRoute = (route, router) => {
89
+ validateRouteConfig(route);
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
92
+ _.set(route, 'info.type', type || 'admin');
93
+
94
+ composeEndpoint(route, { router });
95
+ };
96
+
97
+ const addRoutes = (routes, router) => {
98
+ if (Array.isArray(routes)) {
99
+ routes.forEach(route => createRoute(route, router));
100
+ } else if (routes.routes) {
101
+ const subRouter = new Router({ prefix: routes.prefix });
102
+
103
+ routes.routes.forEach(route => {
104
+ const hasPrefix = has('prefix', route.config);
105
+ createRoute(route, hasPrefix ? router : subRouter);
106
+ });
107
+
108
+ return router.use(subRouter.routes(), subRouter.allowedMethods());
109
+ }
110
+ };
111
+
112
+ return {
113
+ addRoutes,
114
+ };
115
+ };
116
+
117
+ module.exports = {
118
+ validateRouteConfig,
119
+ createRouteManager,
120
+ };
@@ -16,7 +16,7 @@ module.exports = async (uid, entity, files) => {
16
16
  return;
17
17
  }
18
18
 
19
- const uploadService = strapi.plugins.upload.services.upload;
19
+ const uploadService = strapi.plugin('upload').service('upload');
20
20
 
21
21
  const findModelFromUploadPath = path => {
22
22
  if (path.length === 0) {
@@ -79,7 +79,7 @@ class WebhookRunner {
79
79
  method: 'post',
80
80
  body: JSON.stringify({
81
81
  event,
82
- created_at: new Date(),
82
+ createdAt: new Date(),
83
83
  ...info,
84
84
  }),
85
85
  headers: {
package/lib/utils/ee.js CHANGED
@@ -78,7 +78,7 @@ module.exports = ({ dir, logger = noLog }) => {
78
78
  };
79
79
 
80
80
  Object.defineProperty(module.exports, 'licenseInfo', {
81
- get: () => {
81
+ get() {
82
82
  mustHaveKey('licenseInfo');
83
83
  return internals.licenseInfo;
84
84
  },
@@ -87,7 +87,7 @@ Object.defineProperty(module.exports, 'licenseInfo', {
87
87
  });
88
88
 
89
89
  Object.defineProperty(module.exports, 'isEE', {
90
- get: () => {
90
+ get() {
91
91
  mustHaveKey('isEE');
92
92
  return internals.isEE;
93
93
  },
@@ -96,7 +96,7 @@ Object.defineProperty(module.exports, 'isEE', {
96
96
  });
97
97
 
98
98
  Object.defineProperty(module.exports, 'features', {
99
- get: () => {
99
+ get() {
100
100
  mustHaveKey('licenseInfo');
101
101
 
102
102
  const { type: licenseType } = module.exports.licenseInfo;
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const { join } = require('path');
4
+
5
+ const getDirs = root => ({
6
+ root,
7
+ src: join(root, 'src'),
8
+ api: join(root, 'src', 'api'),
9
+ components: join(root, 'src', 'components'),
10
+ extensions: join(root, 'src', 'extensions'),
11
+ policies: join(root, 'src', 'policies'),
12
+ middlewares: join(root, 'src', 'middlewares'),
13
+ config: join(root, 'config'),
14
+ public: join(root, 'public'),
15
+ });
16
+
17
+ module.exports = getDirs;
@@ -2,8 +2,10 @@
2
2
 
3
3
  const openBrowser = require('./open-browser');
4
4
  const isInitialized = require('./is-initialized');
5
+ const getDirs = require('./get-dirs');
5
6
 
6
7
  module.exports = {
7
8
  isInitialized,
8
9
  openBrowser,
10
+ getDirs,
9
11
  };
@@ -14,7 +14,7 @@ module.exports = async function isInitialized(strapi) {
14
14
  }
15
15
 
16
16
  // test if there is at least one admin
17
- const anyAdministrator = await strapi.query('strapi::user').findOne({ select: ['id'] });
17
+ const anyAdministrator = await strapi.query('admin::user').findOne({ select: ['id'] });
18
18
 
19
19
  return !isNil(anyAdministrator);
20
20
  } catch (err) {
@@ -2,7 +2,6 @@
2
2
 
3
3
  const path = require('path');
4
4
  const fs = require('fs-extra');
5
- const _ = require('lodash');
6
5
 
7
6
  const requiredPaths = ['api', 'extensions', 'plugins', 'config', 'public'];
8
7
  const checkFoldersExist = ({ appPath }) => {
@@ -18,20 +17,6 @@ const checkFoldersExist = ({ appPath }) => {
18
17
  }
19
18
  };
20
19
 
21
- const checkPluginsConflicts = ({ appPath, installedPlugins }) => {
22
- const localPluginNames = fs.readdirSync(path.resolve(appPath, 'plugins'));
23
- const pluginsIntersection = _.intersection(localPluginNames, installedPlugins);
24
-
25
- if (pluginsIntersection.length > 0) {
26
- throw new Error(
27
- `You have some local plugins with the same name as npm installed plugins:\n${pluginsIntersection
28
- .map(p => `- ${p}`)
29
- .join('\n')}`
30
- );
31
- }
32
- };
33
-
34
20
  module.exports = config => {
35
21
  checkFoldersExist(config);
36
- checkPluginsConflicts(config);
37
22
  };
@@ -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
+ };
@@ -72,7 +72,7 @@ module.exports = app => {
72
72
  console.log();
73
73
  },
74
74
 
75
- logStartupMessage(isInitialized) {
75
+ logStartupMessage({ isInitialized } = {}) {
76
76
  // Should the startup message be displayed?
77
77
  const hideStartupMessage = process.env.STRAPI_HIDE_STARTUP_MESSAGE
78
78
  ? process.env.STRAPI_HIDE_STARTUP_MESSAGE === 'true'
@@ -82,7 +82,7 @@ module.exports = app => {
82
82
  if (!isInitialized) {
83
83
  this.logFirstStartupMessage();
84
84
  } else {
85
- this.logStartupMessage();
85
+ this.logDefaultStartupMessage();
86
86
  }
87
87
  }
88
88
  },
@@ -27,7 +27,7 @@ const geUpdatetMessage = (newVersion, currentVersion) => {
27
27
 
28
28
  return `
29
29
  A new version of Strapi is available ${currentVersionLog} → ${newVersionLog}
30
- Check out the new the releases at: ${releaseLink}
30
+ Check out the new releases at: ${releaseLink}
31
31
  `.trim();
32
32
  };
33
33
 
@@ -38,7 +38,7 @@ const createUpdateNotifier = strapi => {
38
38
  config = new Configstore(
39
39
  pkg.name,
40
40
  {},
41
- { configPath: path.join(strapi.dir, '.strapi-updater.json') }
41
+ { configPath: path.join(strapi.dirs.root, '.strapi-updater.json') }
42
42
  );
43
43
  } catch {
44
44
  // we don't have write access to the file system
@@ -67,6 +67,7 @@ const createUpdateNotifier = strapi => {
67
67
  const now = Date.now();
68
68
  const latestVersion = config.get('latest');
69
69
  const lastNotification = config.get('lastNotification') || 0;
70
+
70
71
  if (
71
72
  !process.stdout.isTTY ||
72
73
  lastNotification + notifInterval > now ||