@strapi/strapi 0.0.0-e6cac9fe30 → 0.0.0-eb69fb6b1facdfef907143ee63f1642a71eb4606
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 +18 -9
- package/lib/Strapi.js +21 -3
- package/lib/commands/admin-create.js +1 -1
- package/lib/commands/builders/admin.js +1 -0
- package/lib/commands/configurationDump.js +2 -2
- package/lib/core/app-configuration/load-config-file.js +1 -3
- package/lib/core/domain/content-type/index.js +1 -1
- package/lib/core/loaders/apis.js +4 -4
- package/lib/core/loaders/middlewares.js +1 -2
- package/lib/core/loaders/plugins/get-enabled-plugins.js +3 -1
- package/lib/core/loaders/plugins/index.js +5 -5
- package/lib/core/loaders/policies.js +1 -2
- package/lib/core/loaders/src-index.js +1 -3
- package/lib/core/registries/content-types.js +2 -2
- package/lib/core/registries/controllers.js +2 -2
- package/lib/core/registries/custom-fields.js +72 -0
- package/lib/core/registries/hooks.js +1 -1
- package/lib/core/registries/middlewares.js +2 -2
- package/lib/core/registries/policies.js +1 -1
- package/lib/core/registries/services.js +2 -2
- package/lib/core-api/controller/transform.js +1 -1
- package/lib/core-api/service/index.d.ts +6 -3
- package/lib/load/load-files.js +1 -1
- package/lib/middlewares/body.js +9 -2
- package/lib/middlewares/cors.js +1 -1
- package/lib/middlewares/favicon.js +16 -3
- package/lib/middlewares/security.js +22 -16
- package/lib/services/auth/index.js +4 -1
- package/lib/services/content-api/index.js +74 -0
- package/lib/services/content-api/permissions/engine.js +5 -0
- package/lib/services/content-api/permissions/index.js +148 -0
- package/lib/services/content-api/permissions/providers/action.js +19 -0
- package/lib/services/content-api/permissions/providers/condition.js +19 -0
- package/lib/services/content-api/permissions/providers/index.js +9 -0
- package/lib/services/cron.js +1 -1
- package/lib/services/custom-fields.js +11 -0
- package/lib/services/entity-service/components.js +41 -38
- package/lib/services/entity-service/index.js +68 -46
- package/lib/services/entity-service/params.js +1 -87
- package/lib/services/entity-validator/index.js +166 -19
- package/lib/services/metrics/middleware.js +1 -1
- package/lib/services/metrics/sender.js +4 -2
- package/lib/services/request-context.js +17 -0
- package/lib/services/server/index.js +3 -0
- package/lib/services/server/middleware.js +2 -1
- package/lib/services/server/register-routes.js +2 -2
- package/lib/services/utils/upload-files.js +1 -1
- package/lib/services/worker-queue.js +2 -2
- package/lib/types/core/attributes/common.d.ts +3 -0
- package/lib/types/core/strapi/index.d.ts +45 -10
- package/lib/types/factories.d.ts +3 -3
- package/lib/utils/addSlash.js +6 -5
- package/lib/utils/convert-custom-field-type.js +22 -0
- package/lib/utils/index.js +0 -2
- package/package.json +18 -17
- package/lib/utils/import-default.js +0 -10
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<a href="https://strapi.io">
|
|
2
|
+
<a href="https://strapi.io/#gh-light-mode-only">
|
|
3
3
|
<img src="https://strapi.io/assets/strapi-logo-dark.svg" width="318px" alt="Strapi logo" />
|
|
4
4
|
</a>
|
|
5
|
+
<a href="https://strapi.io/#gh-dark-mode-only">
|
|
6
|
+
<img src="https://strapi.io/assets/strapi-logo-light.svg" width="318px" alt="Strapi logo" />
|
|
7
|
+
</a>
|
|
5
8
|
</p>
|
|
9
|
+
|
|
6
10
|
<h3 align="center">API creation made simple, secure and fast.</h3>
|
|
7
11
|
<p align="center">The most advanced open-source headless CMS to build powerful APIs with no effort.</p>
|
|
8
12
|
<p align="center"><a href="https://strapi.io/demo">Try live demo</a></p>
|
|
@@ -13,11 +17,14 @@
|
|
|
13
17
|
<img src="https://img.shields.io/npm/v/@strapi/strapi/latest.svg" alt="NPM Version" />
|
|
14
18
|
</a>
|
|
15
19
|
<a href="https://github.com/strapi/strapi/actions/workflows/tests.yml">
|
|
16
|
-
<img src="https://github.com/strapi/strapi/actions/workflows/tests.yml/badge.svg?branch=
|
|
20
|
+
<img src="https://github.com/strapi/strapi/actions/workflows/tests.yml/badge.svg?branch=main" alt="Tests" />
|
|
17
21
|
</a>
|
|
18
22
|
<a href="https://discord.strapi.io">
|
|
19
23
|
<img src="https://img.shields.io/discord/811989166782021633?label=Discord" alt="Strapi on Discord" />
|
|
20
24
|
</a>
|
|
25
|
+
<a href="https://github.com/strapi/strapi/actions/workflows/nightly.yml">
|
|
26
|
+
<img src="https://github.com/strapi/strapi/actions/workflows/nightly.yml/badge.svg" alt="Strapi Nightly Release Build Status" />
|
|
27
|
+
</a>
|
|
21
28
|
</p>
|
|
22
29
|
|
|
23
30
|
<br>
|
|
@@ -79,15 +86,17 @@ Complete installation requirements can be found in the documentation under <a hr
|
|
|
79
86
|
|
|
80
87
|
**Node:**
|
|
81
88
|
|
|
82
|
-
- NodeJS >=
|
|
89
|
+
- NodeJS >= 14 <= 18
|
|
83
90
|
- NPM >= 6.x
|
|
84
91
|
|
|
85
92
|
**Database:**
|
|
86
93
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
| Database | Minimum | Recommended |
|
|
95
|
+
| ---------- | ------- | ----------- |
|
|
96
|
+
| MySQL | 5.7.8 | 8.0 |
|
|
97
|
+
| MariaDB | 10.3 | 10.6 |
|
|
98
|
+
| PostgreSQL | 11.0 | 14.0 |
|
|
99
|
+
| SQLite | 3 | 3 |
|
|
91
100
|
|
|
92
101
|
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
93
102
|
|
|
@@ -114,7 +123,7 @@ For general help using Strapi, please refer to [the official Strapi documentatio
|
|
|
114
123
|
- [Discord](https://discord.strapi.io) (For live discussion with the Community and Strapi team)
|
|
115
124
|
- [GitHub](https://github.com/strapi/strapi) (Bug reports, Contributions)
|
|
116
125
|
- [Community Forum](https://forum.strapi.io) (Questions and Discussions)
|
|
117
|
-
- [
|
|
126
|
+
- [Feedback section](https://feedback.strapi.io) (Roadmap, Feature requests)
|
|
118
127
|
- [Twitter](https://twitter.com/strapijs) (Get the news fast)
|
|
119
128
|
- [Facebook](https://www.facebook.com/Strapi-616063331867161)
|
|
120
129
|
- [YouTube Channel](https://www.youtube.com/strapi) (Learn from Video Tutorials)
|
|
@@ -125,7 +134,7 @@ Follow our [migration guides](https://docs.strapi.io/developer-docs/latest/updat
|
|
|
125
134
|
|
|
126
135
|
## Roadmap
|
|
127
136
|
|
|
128
|
-
Check out our [roadmap](https://feedback.strapi.io
|
|
137
|
+
Check out our [roadmap](https://feedback.strapi.io) to get informed of the latest features released and the upcoming ones. You may also give us insights and vote for a specific feature.
|
|
129
138
|
|
|
130
139
|
## Documentation
|
|
131
140
|
|
package/lib/Strapi.js
CHANGED
|
@@ -21,7 +21,10 @@ const createEntityService = require('./services/entity-service');
|
|
|
21
21
|
const createCronService = require('./services/cron');
|
|
22
22
|
const entityValidator = require('./services/entity-validator');
|
|
23
23
|
const createTelemetry = require('./services/metrics');
|
|
24
|
+
const requestContext = require('./services/request-context');
|
|
24
25
|
const createAuth = require('./services/auth');
|
|
26
|
+
const createCustomFields = require('./services/custom-fields');
|
|
27
|
+
const createContentAPI = require('./services/content-api');
|
|
25
28
|
const createUpdateNotifier = require('./utils/update-notifier');
|
|
26
29
|
const createStartupLogger = require('./utils/startup-logger');
|
|
27
30
|
const { LIFECYCLES } = require('./utils/lifecycles');
|
|
@@ -34,12 +37,14 @@ const hooksRegistry = require('./core/registries/hooks');
|
|
|
34
37
|
const controllersRegistry = require('./core/registries/controllers');
|
|
35
38
|
const modulesRegistry = require('./core/registries/modules');
|
|
36
39
|
const pluginsRegistry = require('./core/registries/plugins');
|
|
40
|
+
const customFieldsRegistry = require('./core/registries/custom-fields');
|
|
37
41
|
const createConfigProvider = require('./core/registries/config');
|
|
38
42
|
const apisRegistry = require('./core/registries/apis');
|
|
39
43
|
const bootstrap = require('./core/bootstrap');
|
|
40
44
|
const loaders = require('./core/loaders');
|
|
41
45
|
const { destroyOnSignal } = require('./utils/signals');
|
|
42
46
|
const sanitizersRegistry = require('./core/registries/sanitizers');
|
|
47
|
+
const convertCustomFieldType = require('./utils/convert-custom-field-type');
|
|
43
48
|
|
|
44
49
|
// TODO: move somewhere else
|
|
45
50
|
const draftAndPublishSync = require('./migrations/draft-publish');
|
|
@@ -74,7 +79,7 @@ class Strapi {
|
|
|
74
79
|
// Load the app configuration from the dist directory
|
|
75
80
|
const appConfig = loadConfiguration({ appDir: rootDirs.app, distDir: rootDirs.dist }, opts);
|
|
76
81
|
|
|
77
|
-
//
|
|
82
|
+
// Instantiate the Strapi container
|
|
78
83
|
this.container = createContainer(this);
|
|
79
84
|
|
|
80
85
|
// Register every Strapi registry in the container
|
|
@@ -87,8 +92,10 @@ class Strapi {
|
|
|
87
92
|
this.container.register('controllers', controllersRegistry(this));
|
|
88
93
|
this.container.register('modules', modulesRegistry(this));
|
|
89
94
|
this.container.register('plugins', pluginsRegistry(this));
|
|
95
|
+
this.container.register('custom-fields', customFieldsRegistry(this));
|
|
90
96
|
this.container.register('apis', apisRegistry(this));
|
|
91
97
|
this.container.register('auth', createAuth(this));
|
|
98
|
+
this.container.register('content-api', createContentAPI(this));
|
|
92
99
|
this.container.register('sanitizers', sanitizersRegistry(this));
|
|
93
100
|
|
|
94
101
|
// Create a mapping of every useful directory (for the app, dist and static directories)
|
|
@@ -98,7 +105,7 @@ class Strapi {
|
|
|
98
105
|
this.isLoaded = false;
|
|
99
106
|
this.reload = this.reload();
|
|
100
107
|
|
|
101
|
-
//
|
|
108
|
+
// Instantiate the Koa app & the HTTP server
|
|
102
109
|
this.server = createServer(this);
|
|
103
110
|
|
|
104
111
|
// Strapi utils instanciation
|
|
@@ -108,6 +115,9 @@ class Strapi {
|
|
|
108
115
|
this.log = createLogger(this.config.get('logger', {}));
|
|
109
116
|
this.cron = createCronService();
|
|
110
117
|
this.telemetry = createTelemetry(this);
|
|
118
|
+
this.requestContext = requestContext;
|
|
119
|
+
|
|
120
|
+
this.customFields = createCustomFields(this);
|
|
111
121
|
|
|
112
122
|
createUpdateNotifier(this).notify();
|
|
113
123
|
}
|
|
@@ -117,7 +127,7 @@ class Strapi {
|
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
get EE() {
|
|
120
|
-
return ee({ dir: this.dirs.
|
|
130
|
+
return ee({ dir: this.dirs.app.root, logger: this.log });
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
get services() {
|
|
@@ -188,6 +198,10 @@ class Strapi {
|
|
|
188
198
|
return this.container.get('auth');
|
|
189
199
|
}
|
|
190
200
|
|
|
201
|
+
get contentAPI() {
|
|
202
|
+
return this.container.get('content-api');
|
|
203
|
+
}
|
|
204
|
+
|
|
191
205
|
get sanitizers() {
|
|
192
206
|
return this.container.get('sanitizers');
|
|
193
207
|
}
|
|
@@ -377,6 +391,8 @@ class Strapi {
|
|
|
377
391
|
this.telemetry.register();
|
|
378
392
|
|
|
379
393
|
await this.runLifecyclesFunctions(LIFECYCLES.REGISTER);
|
|
394
|
+
// NOTE: Swap type customField for underlying data type
|
|
395
|
+
convertCustomFieldType(this);
|
|
380
396
|
|
|
381
397
|
return this;
|
|
382
398
|
}
|
|
@@ -445,6 +461,8 @@ class Strapi {
|
|
|
445
461
|
await this.server.initMiddlewares();
|
|
446
462
|
await this.server.initRouting();
|
|
447
463
|
|
|
464
|
+
await this.contentAPI.permissions.registerActions();
|
|
465
|
+
|
|
448
466
|
await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP);
|
|
449
467
|
|
|
450
468
|
this.cron.start();
|
|
@@ -17,7 +17,7 @@ const passwordValidator = yup
|
|
|
17
17
|
const adminCreateSchema = yup.object().shape({
|
|
18
18
|
email: emailValidator,
|
|
19
19
|
password: passwordValidator,
|
|
20
|
-
firstname: yup.string().required('First name is required'),
|
|
20
|
+
firstname: yup.string().trim().required('First name is required'),
|
|
21
21
|
lastname: yup.string(),
|
|
22
22
|
});
|
|
23
23
|
|
|
@@ -9,7 +9,7 @@ const CHUNK_SIZE = 100;
|
|
|
9
9
|
* Will dump configurations to a file or stdout
|
|
10
10
|
* @param {string} file filepath to use as output
|
|
11
11
|
*/
|
|
12
|
-
module.exports = async
|
|
12
|
+
module.exports = async ({ file: filePath, pretty }) => {
|
|
13
13
|
const output = filePath ? fs.createWriteStream(filePath) : process.stdout;
|
|
14
14
|
|
|
15
15
|
const appContext = await strapi.compile();
|
|
@@ -21,7 +21,7 @@ module.exports = async function ({ file: filePath, pretty }) {
|
|
|
21
21
|
|
|
22
22
|
const pageCount = Math.ceil(count / CHUNK_SIZE);
|
|
23
23
|
|
|
24
|
-
for (let page = 0; page < pageCount; page
|
|
24
|
+
for (let page = 0; page < pageCount; page += 1) {
|
|
25
25
|
const results = await app
|
|
26
26
|
.query('strapi::core-store')
|
|
27
27
|
.findMany({ limit: CHUNK_SIZE, offset: page * CHUNK_SIZE, orderBy: 'key' });
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const { templateConfiguration, env } = require('@strapi/utils');
|
|
6
|
-
|
|
7
|
-
const importDefault = require('../../utils/import-default');
|
|
5
|
+
const { templateConfiguration, env, importDefault } = require('@strapi/utils');
|
|
8
6
|
|
|
9
7
|
const loadJsFile = (file) => {
|
|
10
8
|
try {
|
|
@@ -54,7 +54,7 @@ const createContentType = (uid, definition) => {
|
|
|
54
54
|
});
|
|
55
55
|
} else {
|
|
56
56
|
throw new Error(
|
|
57
|
-
`Incorrect Content Type UID "${uid}". The UID should start with api::, plugin:: or
|
|
57
|
+
`Incorrect Content Type UID "${uid}". The UID should start with api::, plugin:: or admin::.`
|
|
58
58
|
);
|
|
59
59
|
}
|
|
60
60
|
|
package/lib/core/loaders/apis.js
CHANGED
|
@@ -4,8 +4,7 @@ const { join, extname, basename } = require('path');
|
|
|
4
4
|
const { existsSync } = require('fs-extra');
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const fse = require('fs-extra');
|
|
7
|
-
const { isKebabCase } = require('@strapi/utils');
|
|
8
|
-
const { importDefault } = require('../../utils');
|
|
7
|
+
const { isKebabCase, importDefault } = require('@strapi/utils');
|
|
9
8
|
|
|
10
9
|
const DEFAULT_CONTENT_TYPE = {
|
|
11
10
|
schema: {},
|
|
@@ -40,7 +39,7 @@ module.exports = async (strapi) => {
|
|
|
40
39
|
|
|
41
40
|
validateContentTypesUnicity(apis);
|
|
42
41
|
|
|
43
|
-
for (const apiName
|
|
42
|
+
for (const apiName of Object.keys(apis)) {
|
|
44
43
|
strapi.container.get('apis').add(apiName, apis[apiName]);
|
|
45
44
|
}
|
|
46
45
|
};
|
|
@@ -131,11 +130,12 @@ const loadDir = async (dir) => {
|
|
|
131
130
|
|
|
132
131
|
const root = {};
|
|
133
132
|
for (const fd of fds) {
|
|
134
|
-
if (!fd.isFile()) {
|
|
133
|
+
if (!fd.isFile() || extname(fd.name) === '.map') {
|
|
135
134
|
continue;
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
const key = basename(fd.name, extname(fd.name));
|
|
138
|
+
|
|
139
139
|
root[normalizeName(key)] = await loadFile(join(dir, fd.name));
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { join, extname, basename } = require('path');
|
|
4
4
|
const fse = require('fs-extra');
|
|
5
|
-
|
|
6
|
-
const { importDefault } = require('../../utils');
|
|
5
|
+
const { importDefault } = require('@strapi/utils');
|
|
7
6
|
|
|
8
7
|
// TODO:: allow folders with index.js inside for bigger policies
|
|
9
8
|
module.exports = async function loadMiddlewares(strapi) {
|
|
@@ -59,7 +59,9 @@ const getEnabledPlugins = async (strapi) => {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
const installedPlugins = {};
|
|
62
|
-
|
|
62
|
+
const dependencies = strapi.config.get('info.dependencies', {});
|
|
63
|
+
|
|
64
|
+
for (const dep of Object.keys(dependencies)) {
|
|
63
65
|
const packagePath = join(dep, 'package.json');
|
|
64
66
|
let packageInfo;
|
|
65
67
|
try {
|
|
@@ -34,10 +34,10 @@ const applyUserExtension = async (plugins) => {
|
|
|
34
34
|
const extendedSchemas = await loadFiles(extensionsDir, '**/content-types/**/schema.json');
|
|
35
35
|
const strapiServers = await loadFiles(extensionsDir, '**/strapi-server.js');
|
|
36
36
|
|
|
37
|
-
for (const pluginName
|
|
37
|
+
for (const pluginName of Object.keys(plugins)) {
|
|
38
38
|
const plugin = plugins[pluginName];
|
|
39
39
|
// first: load json schema
|
|
40
|
-
for (const ctName
|
|
40
|
+
for (const ctName of Object.keys(plugin.contentTypes)) {
|
|
41
41
|
const extendedSchema = get([pluginName, 'content-types', ctName, 'schema'], extendedSchemas);
|
|
42
42
|
if (extendedSchema) {
|
|
43
43
|
plugin.contentTypes[ctName].schema = {
|
|
@@ -57,7 +57,7 @@ const applyUserExtension = async (plugins) => {
|
|
|
57
57
|
const applyUserConfig = async (plugins) => {
|
|
58
58
|
const userPluginsConfig = await getUserPluginsConfig();
|
|
59
59
|
|
|
60
|
-
for (const pluginName
|
|
60
|
+
for (const pluginName of Object.keys(plugins)) {
|
|
61
61
|
const plugin = plugins[pluginName];
|
|
62
62
|
const userPluginConfig = getOr({}, `${pluginName}.config`, userPluginsConfig);
|
|
63
63
|
const defaultConfig =
|
|
@@ -82,7 +82,7 @@ const loadPlugins = async (strapi) => {
|
|
|
82
82
|
|
|
83
83
|
strapi.config.set('enabledPlugins', enabledPlugins);
|
|
84
84
|
|
|
85
|
-
for (const pluginName
|
|
85
|
+
for (const pluginName of Object.keys(enabledPlugins)) {
|
|
86
86
|
const enabledPlugin = enabledPlugins[pluginName];
|
|
87
87
|
|
|
88
88
|
const serverEntrypointPath = join(enabledPlugin.pathToPlugin, 'strapi-server.js');
|
|
@@ -100,7 +100,7 @@ const loadPlugins = async (strapi) => {
|
|
|
100
100
|
await applyUserConfig(plugins);
|
|
101
101
|
await applyUserExtension(plugins);
|
|
102
102
|
|
|
103
|
-
for (const pluginName
|
|
103
|
+
for (const pluginName of Object.keys(plugins)) {
|
|
104
104
|
strapi.container.get('plugins').add(pluginName, plugins[pluginName]);
|
|
105
105
|
}
|
|
106
106
|
};
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { join, extname, basename } = require('path');
|
|
4
4
|
const fse = require('fs-extra');
|
|
5
|
-
|
|
6
|
-
const { importDefault } = require('../../utils');
|
|
5
|
+
const { importDefault } = require('@strapi/utils');
|
|
7
6
|
|
|
8
7
|
// TODO:: allow folders with index.js inside for bigger policies
|
|
9
8
|
module.exports = async function loadPolicies(strapi) {
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { resolve } = require('path');
|
|
4
4
|
const { statSync, existsSync } = require('fs');
|
|
5
|
-
const { yup } = require('@strapi/utils');
|
|
6
|
-
|
|
7
|
-
const { importDefault } = require('../../utils');
|
|
5
|
+
const { yup, importDefault } = require('@strapi/utils');
|
|
8
6
|
|
|
9
7
|
const srcSchema = yup
|
|
10
8
|
.object()
|
|
@@ -5,7 +5,7 @@ const { createContentType } = require('../domain/content-type');
|
|
|
5
5
|
const { addNamespace, hasNamespace } = require('../utils');
|
|
6
6
|
|
|
7
7
|
const validateKeySameToSingularName = (contentTypes) => {
|
|
8
|
-
for (const ctName
|
|
8
|
+
for (const ctName of Object.keys(contentTypes)) {
|
|
9
9
|
const contentType = contentTypes[ctName];
|
|
10
10
|
|
|
11
11
|
if (ctName !== contentType.schema.info.singularName) {
|
|
@@ -63,7 +63,7 @@ const contentTypesRegistry = () => {
|
|
|
63
63
|
add(namespace, newContentTypes) {
|
|
64
64
|
validateKeySameToSingularName(newContentTypes);
|
|
65
65
|
|
|
66
|
-
for (const rawCtName
|
|
66
|
+
for (const rawCtName of Object.keys(newContentTypes)) {
|
|
67
67
|
const uid = addNamespace(rawCtName, namespace);
|
|
68
68
|
|
|
69
69
|
if (has(uid, contentTypes)) {
|
|
@@ -48,7 +48,7 @@ const controllersRegistry = () => {
|
|
|
48
48
|
const filteredControllers = pickBy((_, uid) => hasNamespace(uid, namespace))(controllers);
|
|
49
49
|
|
|
50
50
|
const map = {};
|
|
51
|
-
for (const uid
|
|
51
|
+
for (const uid of Object.keys(filteredControllers)) {
|
|
52
52
|
Object.defineProperty(map, uid, {
|
|
53
53
|
enumerable: true,
|
|
54
54
|
get: () => {
|
|
@@ -78,7 +78,7 @@ const controllersRegistry = () => {
|
|
|
78
78
|
* @returns
|
|
79
79
|
*/
|
|
80
80
|
add(namespace, newControllers) {
|
|
81
|
-
for (const controllerName
|
|
81
|
+
for (const controllerName of Object.keys(newControllers)) {
|
|
82
82
|
const controller = newControllers[controllerName];
|
|
83
83
|
const uid = addNamespace(controllerName, namespace);
|
|
84
84
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { has } = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
const ALLOWED_TYPES = [
|
|
6
|
+
'biginteger',
|
|
7
|
+
'boolean',
|
|
8
|
+
'date',
|
|
9
|
+
'datetime',
|
|
10
|
+
'decimal',
|
|
11
|
+
'email',
|
|
12
|
+
'enumeration',
|
|
13
|
+
'float',
|
|
14
|
+
'integer',
|
|
15
|
+
'json',
|
|
16
|
+
'password',
|
|
17
|
+
'richtext',
|
|
18
|
+
'string',
|
|
19
|
+
'text',
|
|
20
|
+
'time',
|
|
21
|
+
'uid',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const customFieldsRegistry = (strapi) => {
|
|
25
|
+
const customFields = {};
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
getAll() {
|
|
29
|
+
return customFields;
|
|
30
|
+
},
|
|
31
|
+
get(customField) {
|
|
32
|
+
const registeredCustomField = customFields[customField];
|
|
33
|
+
if (!registeredCustomField) {
|
|
34
|
+
throw new Error(`Could not find Custom Field: ${customField}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return registeredCustomField;
|
|
38
|
+
},
|
|
39
|
+
add(customField) {
|
|
40
|
+
const customFieldList = Array.isArray(customField) ? customField : [customField];
|
|
41
|
+
|
|
42
|
+
for (const cf of customFieldList) {
|
|
43
|
+
if (!has('name', cf) || !has('type', cf)) {
|
|
44
|
+
throw new Error(`Custom fields require a 'name' and 'type' key`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { name, plugin, type } = cf;
|
|
48
|
+
if (!ALLOWED_TYPES.includes(type)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isValidObjectKey = /^(?![0-9])[a-zA-Z0-9$_-]+$/g;
|
|
55
|
+
if (!isValidObjectKey.test(name)) {
|
|
56
|
+
throw new Error(`Custom field name: '${name}' is not a valid object key`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// When no plugin is specified, or it isn't found in Strapi, default to global
|
|
60
|
+
const uid = strapi.plugin(plugin) ? `plugin::${plugin}.${name}` : `global::${name}`;
|
|
61
|
+
|
|
62
|
+
if (has(uid, customFields)) {
|
|
63
|
+
throw new Error(`Custom field: '${uid}' has already been registered`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
customFields[uid] = cf;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
module.exports = customFieldsRegistry;
|
|
@@ -54,8 +54,8 @@ const middlewaresRegistry = () => {
|
|
|
54
54
|
* @param {{ [key: string]: Middleware }} newMiddlewares
|
|
55
55
|
* @returns
|
|
56
56
|
*/
|
|
57
|
-
add(namespace, rawMiddlewares) {
|
|
58
|
-
for (const middlewareName
|
|
57
|
+
add(namespace, rawMiddlewares = {}) {
|
|
58
|
+
for (const middlewareName of Object.keys(rawMiddlewares)) {
|
|
59
59
|
const middleware = rawMiddlewares[middlewareName];
|
|
60
60
|
const uid = addNamespace(middlewareName, namespace);
|
|
61
61
|
|
|
@@ -55,7 +55,7 @@ const policiesRegistry = () => {
|
|
|
55
55
|
* @returns
|
|
56
56
|
*/
|
|
57
57
|
add(namespace, newPolicies) {
|
|
58
|
-
for (const policyName
|
|
58
|
+
for (const policyName of Object.keys(newPolicies)) {
|
|
59
59
|
const policy = newPolicies[policyName];
|
|
60
60
|
const uid = addNamespace(policyName, namespace);
|
|
61
61
|
|
|
@@ -48,7 +48,7 @@ const servicesRegistry = (strapi) => {
|
|
|
48
48
|
|
|
49
49
|
// create lazy accessor to avoid instantiating the services;
|
|
50
50
|
const map = {};
|
|
51
|
-
for (const uid
|
|
51
|
+
for (const uid of Object.keys(filteredServices)) {
|
|
52
52
|
Object.defineProperty(map, uid, {
|
|
53
53
|
enumerable: true,
|
|
54
54
|
get: () => {
|
|
@@ -78,7 +78,7 @@ const servicesRegistry = (strapi) => {
|
|
|
78
78
|
* @returns
|
|
79
79
|
*/
|
|
80
80
|
add(namespace, newServices) {
|
|
81
|
-
for (const serviceName
|
|
81
|
+
for (const serviceName of Object.keys(newServices)) {
|
|
82
82
|
const service = newServices[serviceName];
|
|
83
83
|
const uid = addNamespace(serviceName, namespace);
|
|
84
84
|
|
|
@@ -12,11 +12,14 @@ export interface SingleTypeService extends BaseService {
|
|
|
12
12
|
|
|
13
13
|
export interface CollectionTypeService extends BaseService {
|
|
14
14
|
find?(params: object): Promise<Entity[]> | Entity;
|
|
15
|
-
findOne?(entityId: string,params: object): Promise<Entity> | Entity;
|
|
15
|
+
findOne?(entityId: string, params: object): Promise<Entity> | Entity;
|
|
16
16
|
create?(params: object): Promise<Entity> | Entity;
|
|
17
|
-
update?(entityId: string,params: object): Promise<Entity> | Entity;
|
|
18
|
-
delete?(entityId: string,params: object): Promise<Entity> | Entity;
|
|
17
|
+
update?(entityId: string, params: object): Promise<Entity> | Entity;
|
|
18
|
+
delete?(entityId: string, params: object): Promise<Entity> | Entity;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export type Service = SingleTypeService | CollectionTypeService;
|
|
22
22
|
|
|
23
|
+
export type GenericService = Partial<Service> & {
|
|
24
|
+
[method: string | number | symbol]: <T = any>(...args: any) => T;
|
|
25
|
+
};
|
package/lib/load/load-files.js
CHANGED
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const _ = require('lodash');
|
|
5
5
|
const fse = require('fs-extra');
|
|
6
6
|
|
|
7
|
-
const { importDefault } = require('
|
|
7
|
+
const { importDefault } = require('@strapi/utils');
|
|
8
8
|
const glob = require('./glob');
|
|
9
9
|
const filePathToPath = require('./filepath-to-prop-path');
|
|
10
10
|
|
package/lib/middlewares/body.js
CHANGED
|
@@ -23,12 +23,19 @@ function getFiles(ctx) {
|
|
|
23
23
|
/**
|
|
24
24
|
* @type {import('./').MiddlewareFactory}
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
module.exports = (config, { strapi }) => {
|
|
27
28
|
const bodyConfig = defaultsDeep(defaults, config);
|
|
28
29
|
|
|
30
|
+
let gqlEndpoint;
|
|
31
|
+
if (strapi.plugin('graphql')) {
|
|
32
|
+
const { config: gqlConfig } = strapi.plugin('graphql');
|
|
33
|
+
gqlEndpoint = gqlConfig('endpoint');
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
return async (ctx, next) => {
|
|
30
37
|
// TODO: find a better way later
|
|
31
|
-
if (ctx.url ===
|
|
38
|
+
if (gqlEndpoint && ctx.url === gqlEndpoint) {
|
|
32
39
|
await next();
|
|
33
40
|
} else {
|
|
34
41
|
try {
|
package/lib/middlewares/cors.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { existsSync } = require('fs');
|
|
3
4
|
const { resolve } = require('path');
|
|
4
5
|
const { defaultsDeep } = require('lodash/fp');
|
|
5
6
|
const favicon = require('koa-favicon');
|
|
6
7
|
|
|
7
8
|
const defaults = {
|
|
8
|
-
path: 'favicon.
|
|
9
|
+
path: 'favicon.png',
|
|
9
10
|
maxAge: 86400000,
|
|
10
11
|
};
|
|
11
12
|
|
|
@@ -13,7 +14,19 @@ const defaults = {
|
|
|
13
14
|
* @type {import('./').MiddlewareFactory}
|
|
14
15
|
*/
|
|
15
16
|
module.exports = (config, { strapi }) => {
|
|
16
|
-
const { maxAge, path:
|
|
17
|
+
const { maxAge, path: faviconDefaultPath } = defaultsDeep(defaults, config);
|
|
18
|
+
const { root: appRoot } = strapi.dirs.app;
|
|
19
|
+
let faviconPath = faviconDefaultPath;
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
/** TODO (v5): Updating the favicon to use a png caused
|
|
22
|
+
* https://github.com/strapi/strapi/issues/14693
|
|
23
|
+
*
|
|
24
|
+
* This check ensures backwards compatibility until
|
|
25
|
+
* the next major version
|
|
26
|
+
*/
|
|
27
|
+
if (!existsSync(resolve(appRoot, faviconPath))) {
|
|
28
|
+
faviconPath = 'favicon.ico';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return favicon(resolve(appRoot, faviconPath), { maxAge });
|
|
19
32
|
};
|