@strapi/strapi 4.0.0-next.9 → 4.0.3
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 +37 -6
- package/lib/Strapi.js +140 -72
- package/lib/commands/build.js +21 -11
- 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 +24 -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 -34
- package/lib/core/domain/content-type/index.js +3 -7
- package/lib/core/domain/module/index.js +8 -6
- package/lib/core/domain/module/validation.js +1 -4
- package/lib/core/loaders/admin.js +2 -2
- package/lib/core/loaders/apis.js +7 -7
- package/lib/core/loaders/components.js +3 -5
- 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 +2 -16
- package/lib/core/registries/content-types.js +50 -6
- package/lib/core/registries/controllers.d.ts +7 -0
- package/lib/core/registries/controllers.js +74 -3
- 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 +61 -2
- 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 +57 -6
- package/lib/core/registries/services.d.ts +7 -0
- package/lib/core/registries/services.js +71 -15
- package/lib/core-api/controller/collection-type.js +38 -11
- package/lib/core-api/controller/index.d.ts +25 -0
- package/lib/core-api/controller/index.js +30 -11
- package/lib/core-api/controller/single-type.js +26 -7
- package/lib/core-api/controller/transform.js +28 -3
- package/lib/core-api/routes/index.js +71 -0
- package/lib/core-api/service/collection-type.js +22 -27
- package/lib/core-api/service/index.d.ts +21 -0
- package/lib/core-api/service/index.js +9 -19
- package/lib/core-api/service/pagination.js +16 -16
- package/lib/core-api/service/single-type.js +17 -20
- 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 +48 -81
- 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 -93
- package/lib/core/app-configuration/load-functions.js +0 -28
- package/lib/core-api/index.js +0 -39
- 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 -72
- 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 -72
- package/lib/middlewares/router/utils/compose-endpoint.js +0 -169
- package/lib/utils/get-prefixed-dependencies.js +0 -7
|
@@ -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
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { join } = require('path');
|
|
4
|
+
const fse = require('fs-extra');
|
|
5
|
+
const { merge } = require('lodash/fp');
|
|
6
|
+
const loadConfigFile = require('../../app-configuration/load-config-file');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Return user defined plugins' config
|
|
10
|
+
* first load config from `config/plugins.js`
|
|
11
|
+
* and then merge config from `config/env/{env}/plugins.js`
|
|
12
|
+
* @return {Promise<{}>}
|
|
13
|
+
*/
|
|
14
|
+
const getUserPluginsConfig = async () => {
|
|
15
|
+
const globalUserConfigPath = join(strapi.dirs.config, 'plugins.js');
|
|
16
|
+
const currentEnvUserConfigPath = join(
|
|
17
|
+
strapi.dirs.config,
|
|
18
|
+
'env',
|
|
19
|
+
process.env.NODE_ENV,
|
|
20
|
+
'plugins.js'
|
|
21
|
+
);
|
|
22
|
+
let config = {};
|
|
23
|
+
|
|
24
|
+
// assign global user config if exists
|
|
25
|
+
if (await fse.pathExists(globalUserConfigPath)) {
|
|
26
|
+
config = loadConfigFile(globalUserConfigPath);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// and merge user config by environment if exists
|
|
30
|
+
if (await fse.pathExists(currentEnvUserConfigPath)) {
|
|
31
|
+
config = merge(config, loadConfigFile(currentEnvUserConfigPath));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return config;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = getUserPluginsConfig;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { join
|
|
4
|
-
const
|
|
3
|
+
const { join } = require('path');
|
|
4
|
+
const fse = require('fs-extra');
|
|
5
5
|
const { defaultsDeep, getOr, get } = require('lodash/fp');
|
|
6
6
|
const { env } = require('@strapi/utils');
|
|
7
7
|
const loadConfigFile = require('../../app-configuration/load-config-file');
|
|
8
8
|
const loadFiles = require('../../../load/load-files');
|
|
9
9
|
const getEnabledPlugins = require('./get-enabled-plugins');
|
|
10
|
+
const getUserPluginsConfig = require('./get-user-plugins-config');
|
|
10
11
|
|
|
11
12
|
const defaultPlugin = {
|
|
12
|
-
bootstrap
|
|
13
|
-
destroy
|
|
14
|
-
register
|
|
13
|
+
bootstrap() {},
|
|
14
|
+
destroy() {},
|
|
15
|
+
register() {},
|
|
15
16
|
config: {
|
|
16
17
|
default: {},
|
|
17
|
-
validator
|
|
18
|
+
validator() {},
|
|
18
19
|
},
|
|
19
20
|
routes: [],
|
|
20
21
|
controllers: {},
|
|
@@ -25,8 +26,8 @@ const defaultPlugin = {
|
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
const applyUserExtension = async plugins => {
|
|
28
|
-
const extensionsDir =
|
|
29
|
-
if (!
|
|
29
|
+
const extensionsDir = strapi.dirs.extensions;
|
|
30
|
+
if (!(await fse.pathExists(extensionsDir))) {
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -39,7 +40,11 @@ const applyUserExtension = async plugins => {
|
|
|
39
40
|
for (const ctName in plugin.contentTypes) {
|
|
40
41
|
const extendedSchema = get([pluginName, 'content-types', ctName, 'schema'], extendedSchemas);
|
|
41
42
|
if (extendedSchema) {
|
|
42
|
-
plugin.contentTypes[ctName].schema =
|
|
43
|
+
plugin.contentTypes[ctName].schema = Object.assign(
|
|
44
|
+
{},
|
|
45
|
+
plugin.contentTypes[ctName].schema,
|
|
46
|
+
extendedSchema
|
|
47
|
+
);
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
// second: execute strapi-server extension
|
|
@@ -61,11 +66,8 @@ const formatContentTypes = plugins => {
|
|
|
61
66
|
}
|
|
62
67
|
};
|
|
63
68
|
|
|
64
|
-
const applyUserConfig = plugins => {
|
|
65
|
-
const
|
|
66
|
-
const userPluginsConfig = existsSync(userPluginConfigPath)
|
|
67
|
-
? loadConfigFile(userPluginConfigPath)
|
|
68
|
-
: {};
|
|
69
|
+
const applyUserConfig = async plugins => {
|
|
70
|
+
const userPluginsConfig = await getUserPluginsConfig();
|
|
69
71
|
|
|
70
72
|
for (const pluginName in plugins) {
|
|
71
73
|
const plugin = plugins[pluginName];
|
|
@@ -87,15 +89,27 @@ const applyUserConfig = plugins => {
|
|
|
87
89
|
|
|
88
90
|
const loadPlugins = async strapi => {
|
|
89
91
|
const plugins = {};
|
|
92
|
+
|
|
90
93
|
const enabledPlugins = await getEnabledPlugins(strapi);
|
|
91
94
|
|
|
95
|
+
strapi.config.set('enabledPlugins', enabledPlugins);
|
|
96
|
+
|
|
92
97
|
for (const pluginName in enabledPlugins) {
|
|
93
98
|
const enabledPlugin = enabledPlugins[pluginName];
|
|
94
|
-
|
|
99
|
+
|
|
100
|
+
const serverEntrypointPath = join(enabledPlugin.pathToPlugin, 'strapi-server.js');
|
|
101
|
+
|
|
102
|
+
// only load plugins with a server entrypoint
|
|
103
|
+
if (!(await fse.pathExists(serverEntrypointPath))) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const pluginServer = loadConfigFile(serverEntrypointPath);
|
|
95
108
|
plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
|
|
96
109
|
}
|
|
110
|
+
|
|
97
111
|
// TODO: validate plugin format
|
|
98
|
-
applyUserConfig(plugins);
|
|
112
|
+
await applyUserConfig(plugins);
|
|
99
113
|
await applyUserExtension(plugins);
|
|
100
114
|
formatContentTypes(plugins);
|
|
101
115
|
|
|
@@ -5,7 +5,7 @@ const fse = require('fs-extra');
|
|
|
5
5
|
|
|
6
6
|
// TODO:: allow folders with index.js inside for bigger policies
|
|
7
7
|
module.exports = async function loadPolicies(strapi) {
|
|
8
|
-
const dir =
|
|
8
|
+
const dir = strapi.dirs.policies;
|
|
9
9
|
|
|
10
10
|
if (!(await fse.pathExists(dir))) {
|
|
11
11
|
return;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { resolve } = require('path');
|
|
4
|
+
const { statSync, existsSync } = require('fs');
|
|
5
|
+
const { yup } = require('@strapi/utils');
|
|
6
|
+
|
|
7
|
+
const srcSchema = yup
|
|
8
|
+
.object()
|
|
9
|
+
.shape({
|
|
10
|
+
bootstrap: yup.mixed().isFunction(),
|
|
11
|
+
register: yup.mixed().isFunction(),
|
|
12
|
+
destroy: yup.mixed().isFunction(),
|
|
13
|
+
})
|
|
14
|
+
.noUnknown();
|
|
15
|
+
|
|
16
|
+
const validateSrcIndex = srcIndex => {
|
|
17
|
+
return srcSchema.validateSync(srcIndex, { strict: true, abortEarly: false });
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
module.exports = strapi => {
|
|
21
|
+
if (!existsSync(strapi.dirs.src)) {
|
|
22
|
+
throw new Error('Missing src folder. Please create one at `./src`');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const pathToSrcIndex = resolve(strapi.dirs.src, 'index.js');
|
|
26
|
+
if (!existsSync(pathToSrcIndex) || statSync(pathToSrcIndex).isDirectory()) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const srcIndex = require(pathToSrcIndex);
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
validateSrcIndex(srcIndex);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
strapi.stopWithError({ message: `Invalid file \`./src/index.js\`: ${e.message}` });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return srcIndex;
|
|
39
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { has } = require('lodash/fp');
|
|
4
|
-
const { createCoreApi } = require('../../core-api');
|
|
5
4
|
|
|
6
5
|
const apisRegistry = strapi => {
|
|
7
6
|
const apis = {};
|
|
@@ -18,22 +17,9 @@ const apisRegistry = strapi => {
|
|
|
18
17
|
throw new Error(`API ${apiName} has already been registered.`);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
const
|
|
20
|
+
const api = strapi.container.get('modules').add(`api::${apiName}`, apiConfig);
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
const contentType = apiInstance.contentTypes[ctName];
|
|
25
|
-
|
|
26
|
-
const { service, controller } = createCoreApi({
|
|
27
|
-
model: contentType,
|
|
28
|
-
api: apiInstance,
|
|
29
|
-
strapi,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
strapi.container.get('services').set(`api::${apiName}.${ctName}`, service);
|
|
33
|
-
strapi.container.get('controllers').set(`api::${apiName}.${ctName}`, controller);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
apis[apiName] = apiInstance;
|
|
22
|
+
apis[apiName] = api;
|
|
37
23
|
|
|
38
24
|
return apis[apiName];
|
|
39
25
|
},
|
|
@@ -20,32 +20,76 @@ const contentTypesRegistry = () => {
|
|
|
20
20
|
const contentTypes = {};
|
|
21
21
|
|
|
22
22
|
return {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Returns this list of registered contentTypes uids
|
|
25
|
+
* @returns {string[]}
|
|
26
|
+
*/
|
|
27
|
+
keys() {
|
|
28
|
+
return Object.keys(contentTypes);
|
|
25
29
|
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Returns the instance of a contentType. Instantiate the contentType if not already done
|
|
33
|
+
* @param {string} uid
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
get(uid) {
|
|
37
|
+
return contentTypes[uid];
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns a map with all the contentTypes in a namespace
|
|
42
|
+
* @param {string} namespace
|
|
43
|
+
*/
|
|
26
44
|
getAll(namespace) {
|
|
27
45
|
return pickBy((_, uid) => hasNamespace(uid, namespace))(contentTypes);
|
|
28
46
|
},
|
|
29
|
-
add(namespace, rawContentTypes) {
|
|
30
|
-
validateKeySameToSingularName(rawContentTypes);
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Registers a contentType
|
|
50
|
+
* @param {string} uid
|
|
51
|
+
* @param {Object} contentType
|
|
52
|
+
*/
|
|
53
|
+
set(uid, contentType) {
|
|
54
|
+
contentTypes[uid] = contentType;
|
|
55
|
+
return this;
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Registers a map of contentTypes for a specific namespace
|
|
60
|
+
* @param {string} namespace
|
|
61
|
+
* @param {{ [key: string]: Object }} newContentTypes
|
|
62
|
+
*/
|
|
63
|
+
add(namespace, newContentTypes) {
|
|
64
|
+
validateKeySameToSingularName(newContentTypes);
|
|
65
|
+
|
|
66
|
+
for (const rawCtName in newContentTypes) {
|
|
33
67
|
const uid = addNamespace(rawCtName, namespace);
|
|
34
68
|
|
|
35
69
|
if (has(uid, contentTypes)) {
|
|
36
70
|
throw new Error(`Content-type ${uid} has already been registered.`);
|
|
37
71
|
}
|
|
38
72
|
|
|
39
|
-
contentTypes[uid] = createContentType(uid,
|
|
73
|
+
contentTypes[uid] = createContentType(uid, newContentTypes[rawCtName]);
|
|
40
74
|
}
|
|
41
75
|
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Wraps a contentType to extend it
|
|
79
|
+
* @param {string} uid
|
|
80
|
+
* @param {(contentType: Object) => Object} extendFn
|
|
81
|
+
*/
|
|
42
82
|
extend(ctUID, extendFn) {
|
|
43
83
|
const currentContentType = this.get(ctUID);
|
|
84
|
+
|
|
44
85
|
if (!currentContentType) {
|
|
45
86
|
throw new Error(`Content-Type ${ctUID} doesn't exist`);
|
|
46
87
|
}
|
|
88
|
+
|
|
47
89
|
const newContentType = extendFn(currentContentType);
|
|
48
90
|
contentTypes[ctUID] = newContentType;
|
|
91
|
+
|
|
92
|
+
return this;
|
|
49
93
|
},
|
|
50
94
|
};
|
|
51
95
|
};
|