@strapi/strapi 4.0.0-next.8 → 4.0.2
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/README.md +14 -14
- package/bin/strapi.js +46 -60
- package/lib/Strapi.js +152 -74
- package/lib/commands/build.js +19 -8
- package/lib/commands/console.js +1 -1
- package/lib/commands/content-types/list.js +22 -0
- package/lib/commands/controllers/list.js +22 -0
- package/lib/commands/develop.js +22 -27
- package/lib/commands/generate-template.js +4 -5
- package/lib/commands/hooks/list.js +22 -0
- package/lib/commands/middlewares/list.js +22 -0
- package/lib/commands/new.js +3 -1
- package/lib/commands/policies/list.js +22 -0
- package/lib/commands/routes/list.js +28 -0
- package/lib/commands/services/list.js +22 -0
- package/lib/commands/watchAdmin.js +18 -9
- package/lib/core/app-configuration/index.js +3 -19
- package/lib/core/bootstrap.js +3 -95
- package/lib/core/domain/content-type/index.js +5 -11
- package/lib/core/domain/module/index.js +42 -11
- package/lib/core/domain/module/validation.js +16 -19
- package/lib/core/loaders/admin.js +2 -2
- package/lib/core/loaders/apis.js +148 -9
- package/lib/core/loaders/components.js +4 -6
- package/lib/core/loaders/index.js +1 -0
- package/lib/core/loaders/middlewares.js +23 -123
- package/lib/core/loaders/plugins/get-enabled-plugins.js +55 -19
- package/lib/core/loaders/plugins/get-user-plugins-config.js +37 -0
- package/lib/core/loaders/plugins/index.js +30 -16
- package/lib/core/loaders/policies.js +1 -1
- package/lib/core/loaders/src-index.js +39 -0
- package/lib/core/registries/apis.js +29 -0
- package/lib/core/registries/content-types.js +61 -12
- package/lib/core/registries/controllers.d.ts +7 -0
- package/lib/core/registries/controllers.js +91 -7
- package/lib/core/registries/hooks.d.ts +20 -0
- package/lib/core/registries/hooks.js +87 -0
- package/lib/core/registries/middlewares.d.ts +5 -0
- package/lib/core/registries/middlewares.js +64 -5
- package/lib/core/registries/modules.js +3 -3
- package/lib/core/registries/plugins.js +2 -2
- package/lib/core/registries/policies.d.ts +9 -0
- package/lib/core/registries/policies.js +64 -5
- package/lib/core/registries/services.d.ts +7 -0
- package/lib/core/registries/services.js +86 -17
- package/lib/core/utils.js +22 -0
- package/lib/core-api/controller/collection-type.js +45 -26
- package/lib/core-api/controller/index.d.ts +25 -0
- package/lib/core-api/controller/index.js +33 -11
- package/lib/core-api/controller/single-type.js +29 -15
- package/lib/core-api/controller/transform.js +62 -6
- package/lib/core-api/routes/index.js +71 -0
- package/lib/core-api/service/collection-type.js +43 -21
- package/lib/core-api/service/index.d.ts +21 -0
- package/lib/core-api/service/index.js +8 -67
- package/lib/core-api/service/pagination.js +125 -0
- package/lib/core-api/service/single-type.js +17 -19
- package/lib/factories.d.ts +48 -0
- package/lib/factories.js +84 -0
- package/lib/index.d.ts +10 -31
- package/lib/index.js +5 -1
- package/lib/middlewares/body.js +33 -0
- package/lib/middlewares/compression.js +8 -0
- package/lib/middlewares/cors.js +58 -0
- package/lib/middlewares/errors.js +40 -0
- package/lib/middlewares/favicon.js +19 -0
- package/lib/middlewares/index.d.ts +5 -0
- package/lib/middlewares/index.js +30 -116
- package/lib/middlewares/ip.js +8 -0
- package/lib/middlewares/logger.js +27 -0
- package/lib/middlewares/powered-by.js +20 -0
- package/lib/middlewares/public/index.js +72 -77
- package/lib/middlewares/query.js +46 -0
- package/lib/middlewares/response-time.js +15 -0
- package/lib/middlewares/responses.js +19 -0
- package/lib/middlewares/security.js +51 -0
- package/lib/middlewares/session/index.js +6 -6
- package/lib/migrations/draft-publish.js +57 -0
- package/lib/services/auth/index.js +87 -0
- package/lib/services/core-store.js +64 -49
- package/lib/services/cron.js +54 -0
- package/lib/services/entity-service/attributes/index.js +31 -0
- package/lib/services/entity-service/attributes/transforms.js +20 -0
- package/lib/services/entity-service/components.js +39 -15
- package/lib/services/entity-service/index.d.ts +91 -0
- package/lib/services/entity-service/index.js +118 -60
- package/lib/services/entity-service/params.js +52 -94
- package/lib/services/entity-validator/index.js +76 -43
- package/lib/services/entity-validator/validators.js +131 -43
- package/lib/services/errors.js +77 -0
- package/lib/services/fs.js +1 -1
- package/lib/services/metrics/index.js +38 -36
- package/lib/services/server/admin-api.js +14 -0
- package/lib/services/server/api.js +36 -0
- package/lib/services/server/compose-endpoint.js +141 -0
- package/lib/services/server/content-api.js +16 -0
- package/lib/{server.js → services/server/http-server.js} +0 -0
- package/lib/services/server/index.js +127 -0
- package/lib/services/server/koa.js +64 -0
- package/lib/services/server/middleware.js +122 -0
- package/lib/services/server/policy.js +32 -0
- package/lib/services/server/register-middlewares.js +110 -0
- package/lib/services/server/register-routes.js +106 -0
- package/lib/services/server/routing.js +120 -0
- package/lib/services/webhook-runner.js +1 -1
- package/lib/utils/ee.js +3 -3
- package/lib/utils/get-dirs.js +17 -0
- package/lib/utils/index.js +2 -0
- package/lib/utils/signals.js +24 -0
- package/lib/utils/update-notifier/index.js +2 -1
- package/package.json +94 -97
- package/lib/commands/generate.js +0 -76
- package/lib/core/app-configuration/load-functions.js +0 -28
- package/lib/core-api/index.js +0 -39
- package/lib/load/check-reserved-filename.js +0 -10
- package/lib/load/load-config-files.js +0 -22
- package/lib/load/require-file-parse.js +0 -15
- package/lib/middlewares/boom/defaults.json +0 -5
- package/lib/middlewares/boom/index.js +0 -147
- package/lib/middlewares/cors/index.js +0 -66
- package/lib/middlewares/cron/defaults.json +0 -5
- package/lib/middlewares/cron/index.js +0 -43
- package/lib/middlewares/favicon/defaults.json +0 -7
- package/lib/middlewares/favicon/index.js +0 -32
- package/lib/middlewares/gzip/defaults.json +0 -6
- package/lib/middlewares/gzip/index.js +0 -19
- package/lib/middlewares/helmet/defaults.json +0 -18
- package/lib/middlewares/helmet/index.js +0 -9
- package/lib/middlewares/ip/defaults.json +0 -7
- package/lib/middlewares/ip/index.js +0 -25
- package/lib/middlewares/language/defaults.json +0 -9
- package/lib/middlewares/language/index.js +0 -40
- package/lib/middlewares/logger/defaults.json +0 -5
- package/lib/middlewares/logger/index.js +0 -37
- package/lib/middlewares/parser/defaults.json +0 -11
- package/lib/middlewares/parser/index.js +0 -71
- package/lib/middlewares/poweredBy/defaults.json +0 -5
- package/lib/middlewares/poweredBy/index.js +0 -16
- package/lib/middlewares/public/defaults.json +0 -8
- package/lib/middlewares/responseTime/defaults.json +0 -5
- package/lib/middlewares/responseTime/index.js +0 -25
- package/lib/middlewares/responses/defaults.json +0 -5
- package/lib/middlewares/responses/index.js +0 -18
- package/lib/middlewares/router/defaults.json +0 -7
- package/lib/middlewares/router/index.js +0 -58
- package/lib/middlewares/router/utils/composeEndpoint.js +0 -177
- package/lib/utils/get-prefixed-dependencies.js +0 -7
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const { removeNamespace } = require('../../utils');
|
|
3
5
|
const { validateModule } = require('./validation');
|
|
4
6
|
|
|
7
|
+
const uidToPath = uid => uid.replace('::', '.');
|
|
8
|
+
|
|
9
|
+
// Removes the namespace from a map with keys prefixed with a namespace
|
|
10
|
+
const removeNamespacedKeys = (map, namespace) => {
|
|
11
|
+
return _.mapKeys(map, (value, key) => removeNamespace(key, namespace));
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const defaultModule = {
|
|
15
|
+
config: {},
|
|
16
|
+
routes: [],
|
|
17
|
+
controllers: {},
|
|
18
|
+
services: {},
|
|
19
|
+
contentTypes: {},
|
|
20
|
+
policies: {},
|
|
21
|
+
middlewares: {},
|
|
22
|
+
};
|
|
23
|
+
|
|
5
24
|
const createModule = (namespace, rawModule, strapi) => {
|
|
25
|
+
_.defaults(rawModule, defaultModule);
|
|
26
|
+
|
|
6
27
|
try {
|
|
7
28
|
validateModule(rawModule);
|
|
8
29
|
} catch (e) {
|
|
9
|
-
throw new Error(`strapi-server.js is invalid for
|
|
30
|
+
throw new Error(`strapi-server.js is invalid for '${namespace}'.\n${e.errors.join('\n')}`);
|
|
10
31
|
}
|
|
11
32
|
|
|
12
33
|
const called = {};
|
|
@@ -16,21 +37,21 @@ const createModule = (namespace, rawModule, strapi) => {
|
|
|
16
37
|
throw new Error(`Bootstrap for ${namespace} has already been called`);
|
|
17
38
|
}
|
|
18
39
|
called.bootstrap = true;
|
|
19
|
-
await rawModule.bootstrap(strapi);
|
|
40
|
+
await (rawModule.bootstrap && rawModule.bootstrap({ strapi }));
|
|
20
41
|
},
|
|
21
42
|
async register() {
|
|
22
43
|
if (called.register) {
|
|
23
44
|
throw new Error(`Register for ${namespace} has already been called`);
|
|
24
45
|
}
|
|
25
46
|
called.register = true;
|
|
26
|
-
await rawModule.register(strapi);
|
|
47
|
+
await (rawModule.register && rawModule.register({ strapi }));
|
|
27
48
|
},
|
|
28
49
|
async destroy() {
|
|
29
50
|
if (called.destroy) {
|
|
30
51
|
throw new Error(`Destroy for ${namespace} has already been called`);
|
|
31
52
|
}
|
|
32
53
|
called.destroy = true;
|
|
33
|
-
await rawModule.destroy(strapi);
|
|
54
|
+
await (rawModule.destroy && rawModule.destroy({ strapi }));
|
|
34
55
|
},
|
|
35
56
|
load() {
|
|
36
57
|
strapi.container.get('content-types').add(namespace, rawModule.contentTypes);
|
|
@@ -38,38 +59,48 @@ const createModule = (namespace, rawModule, strapi) => {
|
|
|
38
59
|
strapi.container.get('policies').add(namespace, rawModule.policies);
|
|
39
60
|
strapi.container.get('middlewares').add(namespace, rawModule.middlewares);
|
|
40
61
|
strapi.container.get('controllers').add(namespace, rawModule.controllers);
|
|
41
|
-
strapi.container.get('config').set(namespace
|
|
62
|
+
strapi.container.get('config').set(uidToPath(namespace), rawModule.config);
|
|
63
|
+
},
|
|
64
|
+
get routes() {
|
|
65
|
+
return rawModule.routes;
|
|
66
|
+
},
|
|
67
|
+
config(path, defaultValue) {
|
|
68
|
+
return strapi.container.get('config').get(`${uidToPath(namespace)}.${path}`, defaultValue);
|
|
42
69
|
},
|
|
43
|
-
routes: rawModule.routes, // TODO: to remove v3
|
|
44
70
|
contentType(ctName) {
|
|
45
71
|
return strapi.container.get('content-types').get(`${namespace}.${ctName}`);
|
|
46
72
|
},
|
|
47
73
|
get contentTypes() {
|
|
48
|
-
|
|
74
|
+
const contentTypes = strapi.container.get('content-types').getAll(namespace);
|
|
75
|
+
return removeNamespacedKeys(contentTypes, namespace);
|
|
49
76
|
},
|
|
50
77
|
service(serviceName) {
|
|
51
78
|
return strapi.container.get('services').get(`${namespace}.${serviceName}`);
|
|
52
79
|
},
|
|
53
80
|
get services() {
|
|
54
|
-
|
|
81
|
+
const services = strapi.container.get('services').getAll(namespace);
|
|
82
|
+
return removeNamespacedKeys(services, namespace);
|
|
55
83
|
},
|
|
56
84
|
policy(policyName) {
|
|
57
85
|
return strapi.container.get('policies').get(`${namespace}.${policyName}`);
|
|
58
86
|
},
|
|
59
87
|
get policies() {
|
|
60
|
-
|
|
88
|
+
const policies = strapi.container.get('policies').getAll(namespace);
|
|
89
|
+
return removeNamespacedKeys(policies, namespace);
|
|
61
90
|
},
|
|
62
91
|
middleware(middlewareName) {
|
|
63
92
|
return strapi.container.get('middlewares').get(`${namespace}.${middlewareName}`);
|
|
64
93
|
},
|
|
65
94
|
get middlewares() {
|
|
66
|
-
|
|
95
|
+
const middlewares = strapi.container.get('middlewares').getAll(namespace);
|
|
96
|
+
return removeNamespacedKeys(middlewares, namespace);
|
|
67
97
|
},
|
|
68
98
|
controller(controllerName) {
|
|
69
99
|
return strapi.container.get('controllers').get(`${namespace}.${controllerName}`);
|
|
70
100
|
},
|
|
71
101
|
get controllers() {
|
|
72
|
-
|
|
102
|
+
const controllers = strapi.container.get('controllers').getAll(namespace);
|
|
103
|
+
return removeNamespacedKeys(controllers, namespace);
|
|
73
104
|
},
|
|
74
105
|
};
|
|
75
106
|
};
|
|
@@ -5,25 +5,22 @@ const { yup } = require('@strapi/utils');
|
|
|
5
5
|
const strapiServerSchema = yup
|
|
6
6
|
.object()
|
|
7
7
|
.shape({
|
|
8
|
-
bootstrap: yup
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
policies: yup.object().required(),
|
|
25
|
-
middlewares: yup.object().required(), // may be removed later
|
|
26
|
-
contentTypes: yup.object().required(),
|
|
8
|
+
bootstrap: yup.mixed().isFunction(),
|
|
9
|
+
destroy: yup.mixed().isFunction(),
|
|
10
|
+
register: yup.mixed().isFunction(),
|
|
11
|
+
config: yup.object(),
|
|
12
|
+
routes: yup.lazy(value => {
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return yup.array();
|
|
15
|
+
} else {
|
|
16
|
+
return yup.object();
|
|
17
|
+
}
|
|
18
|
+
}),
|
|
19
|
+
controllers: yup.object(),
|
|
20
|
+
services: yup.object(),
|
|
21
|
+
policies: yup.object(),
|
|
22
|
+
middlewares: yup.object(),
|
|
23
|
+
contentTypes: yup.object(),
|
|
27
24
|
})
|
|
28
25
|
.noUnknown();
|
|
29
26
|
|
|
@@ -11,6 +11,6 @@ module.exports = strapi => {
|
|
|
11
11
|
strapi.container.get('policies').add(`admin::`, strapi.admin.policies);
|
|
12
12
|
strapi.container.get('middlewares').add(`admin::`, strapi.admin.middlewares);
|
|
13
13
|
|
|
14
|
-
const userAdminConfig = strapi.config.get('
|
|
15
|
-
strapi.container.get('config').set('
|
|
14
|
+
const userAdminConfig = strapi.config.get('admin');
|
|
15
|
+
strapi.container.get('config').set('admin', _.merge(strapi.admin.config, userAdminConfig));
|
|
16
16
|
};
|
package/lib/core/loaders/apis.js
CHANGED
|
@@ -1,20 +1,159 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { join } = require('path');
|
|
3
|
+
const { join, extname, basename } = require('path');
|
|
4
4
|
const { existsSync } = require('fs-extra');
|
|
5
5
|
const _ = require('lodash');
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const fse = require('fs-extra');
|
|
7
|
+
const { isKebabCase } = require('@strapi/utils');
|
|
8
|
+
|
|
9
|
+
// to handle names with numbers in it we first check if it is already in kebabCase
|
|
10
|
+
const normalizeName = name => (isKebabCase(name) ? name : _.kebabCase(name));
|
|
11
|
+
|
|
12
|
+
const DEFAULT_CONTENT_TYPE = {
|
|
13
|
+
schema: {},
|
|
14
|
+
actions: {},
|
|
15
|
+
lifecycles: {},
|
|
16
|
+
};
|
|
8
17
|
|
|
9
18
|
module.exports = async strapi => {
|
|
10
|
-
|
|
19
|
+
if (!existsSync(strapi.dirs.api)) {
|
|
20
|
+
throw new Error('Missing api folder. Please create one at `./src/api`');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const apisFDs = await fse.readdir(strapi.dirs.api, { withFileTypes: true });
|
|
24
|
+
const apis = {};
|
|
25
|
+
|
|
26
|
+
// only load folders
|
|
27
|
+
for (const apiFD of apisFDs) {
|
|
28
|
+
if (apiFD.isDirectory()) {
|
|
29
|
+
const apiName = normalizeName(apiFD.name);
|
|
30
|
+
const api = await loadAPI(join(strapi.dirs.api, apiFD.name));
|
|
31
|
+
|
|
32
|
+
apis[apiName] = api;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
validateContentTypesUnicity(apis);
|
|
37
|
+
|
|
38
|
+
for (const apiName in apis) {
|
|
39
|
+
strapi.container.get('apis').add(apiName, apis[apiName]);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const validateContentTypesUnicity = apis => {
|
|
44
|
+
const allApisSchemas = Object.values(apis).flatMap(api => Object.values(api.contentTypes));
|
|
45
|
+
|
|
46
|
+
const names = [];
|
|
47
|
+
allApisSchemas.forEach(({ schema }) => {
|
|
48
|
+
if (schema.info.singularName) {
|
|
49
|
+
const singularName = _.kebabCase(schema.info.singularName);
|
|
50
|
+
if (names.includes(singularName)) {
|
|
51
|
+
throw new Error(`The singular name "${schema.info.singularName}" should be unique`);
|
|
52
|
+
}
|
|
53
|
+
names.push(singularName);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (schema.info.pluralName) {
|
|
57
|
+
const pluralName = _.kebabCase(schema.info.pluralName);
|
|
58
|
+
if (names.includes(pluralName)) {
|
|
59
|
+
throw new Error(`The plural name "${schema.info.pluralName}" should be unique`);
|
|
60
|
+
}
|
|
61
|
+
names.push(pluralName);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const loadAPI = async dir => {
|
|
67
|
+
const [
|
|
68
|
+
index,
|
|
69
|
+
config,
|
|
70
|
+
routes,
|
|
71
|
+
controllers,
|
|
72
|
+
services,
|
|
73
|
+
policies,
|
|
74
|
+
middlewares,
|
|
75
|
+
contentTypes,
|
|
76
|
+
] = await Promise.all([
|
|
77
|
+
loadIndex(dir),
|
|
78
|
+
loadDir(join(dir, 'config')),
|
|
79
|
+
loadDir(join(dir, 'routes')),
|
|
80
|
+
loadDir(join(dir, 'controllers')),
|
|
81
|
+
loadDir(join(dir, 'services')),
|
|
82
|
+
loadDir(join(dir, 'policies')),
|
|
83
|
+
loadDir(join(dir, 'middlewares')),
|
|
84
|
+
loadContentTypes(join(dir, 'content-types')),
|
|
85
|
+
]);
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
...(index || {}),
|
|
89
|
+
config: config || {},
|
|
90
|
+
routes: routes || [],
|
|
91
|
+
controllers: controllers || {},
|
|
92
|
+
services: services || {},
|
|
93
|
+
policies: policies || {},
|
|
94
|
+
middlewares: middlewares || {},
|
|
95
|
+
contentTypes: contentTypes || {},
|
|
96
|
+
};
|
|
97
|
+
};
|
|
11
98
|
|
|
12
|
-
|
|
13
|
-
|
|
99
|
+
const loadIndex = async dir => {
|
|
100
|
+
if (await fse.pathExists(join(dir, 'index.js'))) {
|
|
101
|
+
return loadFile(join(dir, 'index.js'));
|
|
14
102
|
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const loadContentTypes = async dir => {
|
|
106
|
+
if (!(await fse.pathExists(dir))) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const fds = await fse.readdir(dir, { withFileTypes: true });
|
|
111
|
+
const contentTypes = {};
|
|
112
|
+
|
|
113
|
+
// only load folders
|
|
114
|
+
for (const fd of fds) {
|
|
115
|
+
if (fd.isFile()) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
15
118
|
|
|
16
|
-
|
|
17
|
-
|
|
119
|
+
const contentTypeName = normalizeName(fd.name);
|
|
120
|
+
const contentType = await loadDir(join(dir, fd.name));
|
|
18
121
|
|
|
19
|
-
|
|
122
|
+
contentTypes[normalizeName(contentTypeName)] = _.defaults(contentType, DEFAULT_CONTENT_TYPE);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return contentTypes;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const loadDir = async dir => {
|
|
129
|
+
if (!(await fse.pathExists(dir))) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const fds = await fse.readdir(dir, { withFileTypes: true });
|
|
134
|
+
|
|
135
|
+
const root = {};
|
|
136
|
+
for (const fd of fds) {
|
|
137
|
+
if (!fd.isFile()) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const key = basename(fd.name, extname(fd.name));
|
|
142
|
+
root[normalizeName(key)] = await loadFile(join(dir, fd.name));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return root;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const loadFile = file => {
|
|
149
|
+
const ext = extname(file);
|
|
150
|
+
|
|
151
|
+
switch (ext) {
|
|
152
|
+
case '.js':
|
|
153
|
+
return require(file);
|
|
154
|
+
case '.json':
|
|
155
|
+
return fse.readJSON(file);
|
|
156
|
+
default:
|
|
157
|
+
return {};
|
|
158
|
+
}
|
|
20
159
|
};
|
|
@@ -2,23 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
const { join } = require('path');
|
|
4
4
|
const _ = require('lodash');
|
|
5
|
-
const {
|
|
5
|
+
const { pathExists } = require('fs-extra');
|
|
6
6
|
const loadFiles = require('../../load/load-files');
|
|
7
7
|
|
|
8
8
|
module.exports = async strapi => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (!(await exists(componentsDir))) {
|
|
9
|
+
if (!(await pathExists(strapi.dirs.components))) {
|
|
12
10
|
return {};
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
const map = await loadFiles(
|
|
13
|
+
const map = await loadFiles(strapi.dirs.components, '*/*.*(js|json)');
|
|
16
14
|
|
|
17
15
|
return Object.keys(map).reduce((acc, category) => {
|
|
18
16
|
Object.keys(map[category]).forEach(key => {
|
|
19
17
|
const schema = map[category][key];
|
|
20
18
|
|
|
21
|
-
const filePath = join(
|
|
19
|
+
const filePath = join(strapi.dirs.components, category, schema.__filename__);
|
|
22
20
|
|
|
23
21
|
if (!schema.collectionName) {
|
|
24
22
|
return strapi.stopWithError(
|
|
@@ -1,136 +1,36 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const fs = require('fs-extra');
|
|
6
|
-
const _ = require('lodash');
|
|
7
|
-
const glob = require('../../load/glob');
|
|
8
|
-
const findPackagePath = require('../../load/package-path');
|
|
3
|
+
const { join, extname, basename } = require('path');
|
|
4
|
+
const fse = require('fs-extra');
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const installedMiddlewares = strapi.config.get('installedMiddlewares');
|
|
15
|
-
const appPath = strapi.config.get('appPath');
|
|
6
|
+
// TODO:: allow folders with index.js inside for bigger policies
|
|
7
|
+
module.exports = async function loadMiddlewares(strapi) {
|
|
8
|
+
const localMiddlewares = await loadLocalMiddlewares(strapi);
|
|
9
|
+
const internalMiddlewares = require('../../middlewares');
|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const loaders = createLoaders(strapi);
|
|
20
|
-
|
|
21
|
-
await loaders.loadMiddlewareDependencies(installedMiddlewares, middlewares);
|
|
22
|
-
// internal middlewares
|
|
23
|
-
await loaders.loadInternalMiddlewares(middlewares);
|
|
24
|
-
// local middleware
|
|
25
|
-
await loaders.loadLocalMiddlewares(appPath, middlewares);
|
|
26
|
-
// plugins middlewares
|
|
27
|
-
await loaders.loadPluginsMiddlewares(strapi.plugins, middlewares);
|
|
28
|
-
// local plugin middlewares
|
|
29
|
-
await loaders.loadLocalPluginsMiddlewares(appPath, middlewares);
|
|
30
|
-
// load admin middlewares
|
|
31
|
-
await loaders.loadAdminMiddlewares(middlewares);
|
|
32
|
-
|
|
33
|
-
return middlewares;
|
|
11
|
+
strapi.container.get('middlewares').add(`global::`, localMiddlewares);
|
|
12
|
+
strapi.container.get('middlewares').add(`strapi::`, internalMiddlewares);
|
|
34
13
|
};
|
|
35
14
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* @param {*} strapi - strapi instance
|
|
39
|
-
*/
|
|
40
|
-
const createLoaders = strapi => {
|
|
41
|
-
const loadMiddlewaresInDir = async (dir, middlewares) => {
|
|
42
|
-
const files = await glob('*/*(index|defaults).*(js|json)', {
|
|
43
|
-
cwd: dir,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
files.forEach(f => {
|
|
47
|
-
const name = f.split('/')[0];
|
|
48
|
-
mountMiddleware(name, [path.resolve(dir, f)], middlewares);
|
|
49
|
-
});
|
|
50
|
-
};
|
|
15
|
+
const loadLocalMiddlewares = async strapi => {
|
|
16
|
+
const dir = strapi.dirs.middlewares;
|
|
51
17
|
|
|
52
|
-
|
|
53
|
-
|
|
18
|
+
if (!(await fse.pathExists(dir))) {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
54
21
|
|
|
55
|
-
const
|
|
56
|
-
|
|
22
|
+
const middlewares = {};
|
|
23
|
+
const paths = await fse.readdir(dir, { withFileTypes: true });
|
|
57
24
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (const middlewareName in pluginMiddlewares) {
|
|
62
|
-
middlewares[middlewareName] = {
|
|
63
|
-
loaded: false,
|
|
64
|
-
...pluginMiddlewares[middlewareName],
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const loadLocalPluginsMiddlewares = async (appPath, middlewares) => {
|
|
71
|
-
const pluginsDir = path.resolve(appPath, 'plugins');
|
|
72
|
-
if (!fs.existsSync(pluginsDir)) return;
|
|
73
|
-
|
|
74
|
-
const pluginsNames = await fs.readdir(pluginsDir);
|
|
25
|
+
for (const fd of paths) {
|
|
26
|
+
const { name } = fd;
|
|
27
|
+
const fullPath = join(dir, name);
|
|
75
28
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (!stat.isDirectory()) continue;
|
|
80
|
-
|
|
81
|
-
const dir = path.resolve(pluginsDir, pluginFolder, 'middlewares');
|
|
82
|
-
await loadMiddlewaresInDir(dir, middlewares);
|
|
29
|
+
if (fd.isFile() && extname(name) === '.js') {
|
|
30
|
+
const key = basename(name, '.js');
|
|
31
|
+
middlewares[key] = require(fullPath);
|
|
83
32
|
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const loadAdminMiddlewares = async middlewares => {
|
|
87
|
-
const middlewaresDir = 'middlewares';
|
|
88
|
-
const dir = path.resolve(findPackagePath(`@strapi/admin`), middlewaresDir);
|
|
89
|
-
await loadMiddlewaresInDir(dir, middlewares);
|
|
33
|
+
}
|
|
90
34
|
|
|
91
|
-
|
|
92
|
-
if (process.env.STRAPI_DISABLE_EE !== 'true' && strapi.EE) {
|
|
93
|
-
await loadMiddlewaresInDir(`${dir}/../ee/${middlewaresDir}`, middlewares);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const loadMiddlewareDependencies = async (packages, middlewares) => {
|
|
98
|
-
for (let packageName of packages) {
|
|
99
|
-
const baseDir = path.dirname(require.resolve(`@strapi/middleware-${packageName}`));
|
|
100
|
-
const files = await glob('*(index|defaults).*(js|json)', {
|
|
101
|
-
cwd: baseDir,
|
|
102
|
-
absolute: true,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
mountMiddleware(packageName, files, middlewares);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const mountMiddleware = (name, files, middlewares) => {
|
|
110
|
-
files.forEach(file => {
|
|
111
|
-
middlewares[name] = middlewares[name] || { loaded: false };
|
|
112
|
-
|
|
113
|
-
if (_.endsWith(file, 'index.js') && !middlewares[name].load) {
|
|
114
|
-
return Object.defineProperty(middlewares[name], 'load', {
|
|
115
|
-
configurable: false,
|
|
116
|
-
enumerable: true,
|
|
117
|
-
get: () => require(file)(strapi),
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (_.endsWith(file, 'defaults.json')) {
|
|
122
|
-
middlewares[name].defaults = require(file);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
loadInternalMiddlewares,
|
|
130
|
-
loadLocalMiddlewares,
|
|
131
|
-
loadPluginsMiddlewares,
|
|
132
|
-
loadLocalPluginsMiddlewares,
|
|
133
|
-
loadMiddlewareDependencies,
|
|
134
|
-
loadAdminMiddlewares,
|
|
135
|
-
};
|
|
35
|
+
return middlewares;
|
|
136
36
|
};
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { dirname, join } = require('path');
|
|
3
|
+
const { dirname, join, resolve } = require('path');
|
|
4
4
|
const { statSync, existsSync } = require('fs');
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const { get, has, pick, pickBy, defaultsDeep, map, prop, pipe } = require('lodash/fp');
|
|
7
7
|
const { isKebabCase } = require('@strapi/utils');
|
|
8
|
-
const
|
|
8
|
+
const getUserPluginsConfig = require('./get-user-plugins-config');
|
|
9
9
|
|
|
10
10
|
const isStrapiPlugin = info => get('strapi.kind', info) === 'plugin';
|
|
11
|
+
const INTERNAL_PLUGINS = [
|
|
12
|
+
'@strapi/plugin-content-manager',
|
|
13
|
+
'@strapi/plugin-content-type-builder',
|
|
14
|
+
'@strapi/plugin-email',
|
|
15
|
+
'@strapi/plugin-upload',
|
|
16
|
+
];
|
|
11
17
|
|
|
12
18
|
const validatePluginName = pluginName => {
|
|
13
19
|
if (!isKebabCase(pluginName)) {
|
|
@@ -21,17 +27,14 @@ const toDetailedDeclaration = declaration => {
|
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
let detailedDeclaration = pick(['enabled'], declaration);
|
|
24
|
-
if (has('config', declaration)) {
|
|
25
|
-
detailedDeclaration.userConfig = declaration.config;
|
|
26
|
-
}
|
|
27
30
|
if (has('resolve', declaration)) {
|
|
28
31
|
let pathToPlugin = '';
|
|
29
32
|
try {
|
|
30
33
|
pathToPlugin = dirname(require.resolve(declaration.resolve));
|
|
31
34
|
} catch (e) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
pathToPlugin = resolve(strapi.dirs.root, declaration.resolve);
|
|
36
|
+
|
|
37
|
+
if (!existsSync(pathToPlugin) || !statSync(pathToPlugin).isDirectory()) {
|
|
35
38
|
throw new Error(`${declaration.resolve} couldn't be resolved`);
|
|
36
39
|
}
|
|
37
40
|
}
|
|
@@ -42,28 +45,59 @@ const toDetailedDeclaration = declaration => {
|
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
const getEnabledPlugins = async strapi => {
|
|
48
|
+
const internalPlugins = {};
|
|
49
|
+
for (const dep of INTERNAL_PLUGINS) {
|
|
50
|
+
const packagePath = join(dep, 'package.json');
|
|
51
|
+
const packageInfo = require(packagePath);
|
|
52
|
+
|
|
53
|
+
validatePluginName(packageInfo.strapi.name);
|
|
54
|
+
internalPlugins[packageInfo.strapi.name] = {
|
|
55
|
+
...toDetailedDeclaration({ enabled: true, resolve: packagePath }),
|
|
56
|
+
info: packageInfo.strapi,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
45
60
|
const installedPlugins = {};
|
|
46
61
|
for (const dep in strapi.config.get('info.dependencies', {})) {
|
|
47
62
|
const packagePath = join(dep, 'package.json');
|
|
48
|
-
|
|
63
|
+
let packageInfo;
|
|
64
|
+
try {
|
|
65
|
+
packageInfo = require(packagePath);
|
|
66
|
+
} catch {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
49
69
|
|
|
50
70
|
if (isStrapiPlugin(packageInfo)) {
|
|
51
71
|
validatePluginName(packageInfo.strapi.name);
|
|
52
|
-
installedPlugins[packageInfo.strapi.name] =
|
|
53
|
-
enabled: true,
|
|
54
|
-
|
|
55
|
-
}
|
|
72
|
+
installedPlugins[packageInfo.strapi.name] = {
|
|
73
|
+
...toDetailedDeclaration({ enabled: true, resolve: packagePath }),
|
|
74
|
+
info: packageInfo.strapi,
|
|
75
|
+
};
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
const declaredPlugins = {};
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
? loadConfigFile(userPluginConfigPath)
|
|
63
|
-
: {};
|
|
80
|
+
const userPluginsConfig = await getUserPluginsConfig();
|
|
81
|
+
|
|
64
82
|
_.forEach(userPluginsConfig, (declaration, pluginName) => {
|
|
65
83
|
validatePluginName(pluginName);
|
|
66
|
-
|
|
84
|
+
|
|
85
|
+
declaredPlugins[pluginName] = {
|
|
86
|
+
...toDetailedDeclaration(declaration),
|
|
87
|
+
info: {},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const { pathToPlugin } = declaredPlugins[pluginName];
|
|
91
|
+
|
|
92
|
+
// for manually resolved plugins
|
|
93
|
+
if (pathToPlugin) {
|
|
94
|
+
const packagePath = join(pathToPlugin, 'package.json');
|
|
95
|
+
const packageInfo = require(packagePath);
|
|
96
|
+
|
|
97
|
+
if (isStrapiPlugin(packageInfo)) {
|
|
98
|
+
declaredPlugins[pluginName].info = packageInfo.strapi || {};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
67
101
|
});
|
|
68
102
|
|
|
69
103
|
const declaredPluginsResolves = map(prop('pathToPlugin'), declaredPlugins);
|
|
@@ -71,10 +105,12 @@ const getEnabledPlugins = async strapi => {
|
|
|
71
105
|
p => !declaredPluginsResolves.includes(p.pathToPlugin),
|
|
72
106
|
installedPlugins
|
|
73
107
|
);
|
|
108
|
+
|
|
74
109
|
const enabledPlugins = pipe(
|
|
110
|
+
defaultsDeep(declaredPlugins),
|
|
75
111
|
defaultsDeep(installedPluginsNotAlreadyUsed),
|
|
76
112
|
pickBy(p => p.enabled)
|
|
77
|
-
)(
|
|
113
|
+
)(internalPlugins);
|
|
78
114
|
|
|
79
115
|
return enabledPlugins;
|
|
80
116
|
};
|