@strapi/strapi 4.0.0-beta.11 → 4.0.0-beta.15
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/lib/Strapi.js +3 -3
- package/lib/commands/new.js +3 -1
- package/lib/core/domain/module/index.js +3 -1
- package/lib/core/domain/module/validation.js +1 -4
- package/lib/core/loaders/plugins/get-enabled-plugins.js +25 -9
- package/lib/core/loaders/plugins/index.js +16 -6
- package/lib/core/registries/apis.js +2 -16
- package/lib/core/registries/controllers.d.ts +7 -0
- package/lib/core/registries/controllers.js +74 -3
- package/lib/core/registries/services.js +15 -6
- package/lib/core-api/controller/collection-type.js +37 -23
- package/lib/core-api/controller/index.d.ts +25 -0
- package/lib/core-api/controller/index.js +15 -10
- package/lib/core-api/controller/single-type.js +23 -16
- package/lib/core-api/routes/index.js +71 -0
- package/lib/core-api/service/collection-type.js +5 -7
- package/lib/core-api/service/index.d.ts +21 -0
- package/lib/core-api/service/index.js +9 -12
- package/lib/core-api/service/single-type.js +6 -4
- package/lib/factories.d.ts +48 -0
- package/lib/factories.js +84 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +5 -1
- package/lib/middlewares/errors.js +1 -1
- package/lib/middlewares/index.d.ts +1 -0
- package/lib/middlewares/security.js +7 -2
- package/lib/services/entity-service/index.d.ts +1 -1
- package/lib/services/entity-service/index.js +8 -7
- package/lib/services/entity-validator/index.js +10 -1
- package/lib/services/errors.js +8 -3
- package/lib/services/server/compose-endpoint.js +21 -7
- package/lib/services/server/policy.js +5 -9
- package/lib/services/server/register-routes.js +1 -3
- package/package.json +13 -13
- package/lib/core-api/index.js +0 -39
package/lib/Strapi.js
CHANGED
|
@@ -366,7 +366,7 @@ class Strapi {
|
|
|
366
366
|
this.telemetry.bootstrap();
|
|
367
367
|
|
|
368
368
|
let oldContentTypes;
|
|
369
|
-
if (await this.db.
|
|
369
|
+
if (await this.db.getSchemaConnection().hasTable(coreStoreModel.collectionName)) {
|
|
370
370
|
oldContentTypes = await this.store.get({
|
|
371
371
|
type: 'strapi',
|
|
372
372
|
name: 'content_types',
|
|
@@ -463,13 +463,13 @@ class Strapi {
|
|
|
463
463
|
await this.container.get('modules')[lifecycleName]();
|
|
464
464
|
|
|
465
465
|
// user
|
|
466
|
-
const userLifecycleFunction = this.app[lifecycleName];
|
|
466
|
+
const userLifecycleFunction = this.app && this.app[lifecycleName];
|
|
467
467
|
if (isFunction(userLifecycleFunction)) {
|
|
468
468
|
await userLifecycleFunction({ strapi: this });
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
// admin
|
|
472
|
-
const adminLifecycleFunction = this.admin[lifecycleName];
|
|
472
|
+
const adminLifecycleFunction = this.admin && this.admin[lifecycleName];
|
|
473
473
|
if (isFunction(adminLifecycleFunction)) {
|
|
474
474
|
await adminLifecycleFunction({ strapi: this });
|
|
475
475
|
}
|
package/lib/commands/new.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { generateNewApp } = require('@strapi/generate-new');
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* `$ strapi new`
|
|
5
7
|
*
|
|
@@ -7,5 +9,5 @@
|
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
module.exports = function(...args) {
|
|
10
|
-
return
|
|
12
|
+
return generateNewApp(...args);
|
|
11
13
|
};
|
|
@@ -61,7 +61,9 @@ const createModule = (namespace, rawModule, strapi) => {
|
|
|
61
61
|
strapi.container.get('controllers').add(namespace, rawModule.controllers);
|
|
62
62
|
strapi.container.get('config').set(uidToPath(namespace), rawModule.config);
|
|
63
63
|
},
|
|
64
|
-
routes
|
|
64
|
+
get routes() {
|
|
65
|
+
return rawModule.routes;
|
|
66
|
+
},
|
|
65
67
|
config(path, defaultValue) {
|
|
66
68
|
return strapi.container.get('config').get(`${uidToPath(namespace)}.${path}`, defaultValue);
|
|
67
69
|
},
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const _ = require('lodash');
|
|
4
3
|
const { yup } = require('@strapi/utils');
|
|
5
4
|
|
|
6
5
|
const strapiServerSchema = yup
|
|
@@ -14,9 +13,7 @@ const strapiServerSchema = yup
|
|
|
14
13
|
if (Array.isArray(value)) {
|
|
15
14
|
return yup.array();
|
|
16
15
|
} else {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return yup.object(shape);
|
|
16
|
+
return yup.object();
|
|
20
17
|
}
|
|
21
18
|
}),
|
|
22
19
|
controllers: yup.object(),
|
|
@@ -51,10 +51,10 @@ const getEnabledPlugins = async strapi => {
|
|
|
51
51
|
const packageInfo = require(packagePath);
|
|
52
52
|
|
|
53
53
|
validatePluginName(packageInfo.strapi.name);
|
|
54
|
-
internalPlugins[packageInfo.strapi.name] =
|
|
55
|
-
enabled: true,
|
|
56
|
-
|
|
57
|
-
}
|
|
54
|
+
internalPlugins[packageInfo.strapi.name] = {
|
|
55
|
+
...toDetailedDeclaration({ enabled: true, resolve: packagePath }),
|
|
56
|
+
info: packageInfo.strapi,
|
|
57
|
+
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const installedPlugins = {};
|
|
@@ -64,10 +64,10 @@ const getEnabledPlugins = async strapi => {
|
|
|
64
64
|
|
|
65
65
|
if (isStrapiPlugin(packageInfo)) {
|
|
66
66
|
validatePluginName(packageInfo.strapi.name);
|
|
67
|
-
installedPlugins[packageInfo.strapi.name] =
|
|
68
|
-
enabled: true,
|
|
69
|
-
|
|
70
|
-
}
|
|
67
|
+
installedPlugins[packageInfo.strapi.name] = {
|
|
68
|
+
...toDetailedDeclaration({ enabled: true, resolve: packagePath }),
|
|
69
|
+
info: packageInfo.strapi,
|
|
70
|
+
};
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -79,7 +79,23 @@ const getEnabledPlugins = async strapi => {
|
|
|
79
79
|
|
|
80
80
|
_.forEach(userPluginsConfig, (declaration, pluginName) => {
|
|
81
81
|
validatePluginName(pluginName);
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
declaredPlugins[pluginName] = {
|
|
84
|
+
...toDetailedDeclaration(declaration),
|
|
85
|
+
info: {},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const { pathToPlugin } = declaredPlugins[pluginName];
|
|
89
|
+
|
|
90
|
+
// for manually resolved plugins
|
|
91
|
+
if (pathToPlugin) {
|
|
92
|
+
const packagePath = join(pathToPlugin, 'package.json');
|
|
93
|
+
const packageInfo = require(packagePath);
|
|
94
|
+
|
|
95
|
+
if (isStrapiPlugin(packageInfo)) {
|
|
96
|
+
declaredPlugins[pluginName].info = packageInfo.strapi || {};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
83
99
|
});
|
|
84
100
|
|
|
85
101
|
const declaredPluginsResolves = map(prop('pathToPlugin'), declaredPlugins);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { join } = require('path');
|
|
4
|
-
const
|
|
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');
|
|
@@ -26,7 +26,7 @@ const defaultPlugin = {
|
|
|
26
26
|
|
|
27
27
|
const applyUserExtension = async plugins => {
|
|
28
28
|
const extensionsDir = strapi.dirs.extensions;
|
|
29
|
-
if (!
|
|
29
|
+
if (!(await fse.pathExists(extensionsDir))) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -61,9 +61,9 @@ const formatContentTypes = plugins => {
|
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
const applyUserConfig = plugins => {
|
|
64
|
+
const applyUserConfig = async plugins => {
|
|
65
65
|
const userPluginConfigPath = join(strapi.dirs.config, 'plugins.js');
|
|
66
|
-
const userPluginsConfig =
|
|
66
|
+
const userPluginsConfig = (await fse.pathExists(userPluginConfigPath))
|
|
67
67
|
? loadConfigFile(userPluginConfigPath)
|
|
68
68
|
: {};
|
|
69
69
|
|
|
@@ -90,14 +90,24 @@ const loadPlugins = async strapi => {
|
|
|
90
90
|
|
|
91
91
|
const enabledPlugins = await getEnabledPlugins(strapi);
|
|
92
92
|
|
|
93
|
+
strapi.config.set('enabledPlugins', enabledPlugins);
|
|
94
|
+
|
|
93
95
|
for (const pluginName in enabledPlugins) {
|
|
94
96
|
const enabledPlugin = enabledPlugins[pluginName];
|
|
95
|
-
|
|
97
|
+
|
|
98
|
+
const serverEntrypointPath = join(enabledPlugin.pathToPlugin, 'strapi-server.js');
|
|
99
|
+
|
|
100
|
+
// only load plugins with a server entrypoint
|
|
101
|
+
if (!(await fse.pathExists(serverEntrypointPath))) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const pluginServer = loadConfigFile(serverEntrypointPath);
|
|
96
106
|
plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
// TODO: validate plugin format
|
|
100
|
-
applyUserConfig(plugins);
|
|
110
|
+
await applyUserConfig(plugins);
|
|
101
111
|
await applyUserExtension(plugins);
|
|
102
112
|
formatContentTypes(plugins);
|
|
103
113
|
|
|
@@ -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
|
},
|
|
@@ -3,20 +3,80 @@
|
|
|
3
3
|
const { pickBy, has } = require('lodash/fp');
|
|
4
4
|
const { addNamespace, hasNamespace } = require('../utils');
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('./controllers').Controller} Controller
|
|
8
|
+
* @typedef {import('./controllers').ControllerFactory} ControllerFactory
|
|
9
|
+
*/
|
|
10
|
+
|
|
6
11
|
const controllersRegistry = () => {
|
|
7
12
|
const controllers = {};
|
|
13
|
+
const instances = {};
|
|
8
14
|
|
|
9
15
|
return {
|
|
16
|
+
/**
|
|
17
|
+
* Returns this list of registered controllers uids
|
|
18
|
+
* @returns {string[]}
|
|
19
|
+
*/
|
|
20
|
+
keys() {
|
|
21
|
+
return Object.keys(controllers);
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns the instance of a controller. Instantiate the controller if not already done
|
|
26
|
+
* @param {string} uid
|
|
27
|
+
* @returns {Controller}
|
|
28
|
+
*/
|
|
10
29
|
get(uid) {
|
|
11
|
-
|
|
30
|
+
if (instances[uid]) {
|
|
31
|
+
return instances[uid];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const controller = controllers[uid];
|
|
35
|
+
|
|
36
|
+
if (controller) {
|
|
37
|
+
instances[uid] = typeof controller === 'function' ? controller({ strapi }) : controller;
|
|
38
|
+
return instances[uid];
|
|
39
|
+
}
|
|
12
40
|
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns a map with all the controller in a namespace
|
|
44
|
+
* @param {string} namespace
|
|
45
|
+
* @returns {{ [key: string]: Controller }}
|
|
46
|
+
*/
|
|
13
47
|
getAll(namespace) {
|
|
14
|
-
|
|
48
|
+
const filteredControllers = pickBy((_, uid) => hasNamespace(uid, namespace))(controllers);
|
|
49
|
+
|
|
50
|
+
const map = {};
|
|
51
|
+
for (const uid in filteredControllers) {
|
|
52
|
+
Object.defineProperty(map, uid, {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: () => {
|
|
55
|
+
return this.get(uid);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return map;
|
|
15
61
|
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Registers a controller
|
|
65
|
+
* @param {string} uid
|
|
66
|
+
* @param {Controller} controller
|
|
67
|
+
*/
|
|
16
68
|
set(uid, value) {
|
|
17
69
|
controllers[uid] = value;
|
|
70
|
+
delete instances[uid];
|
|
18
71
|
return this;
|
|
19
72
|
},
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Registers a map of controllers for a specific namespace
|
|
76
|
+
* @param {string} namespace
|
|
77
|
+
* @param {{ [key: string]: Controller|ControllerFactory }} newControllers
|
|
78
|
+
* @returns
|
|
79
|
+
*/
|
|
20
80
|
add(namespace, newControllers) {
|
|
21
81
|
for (const controllerName in newControllers) {
|
|
22
82
|
const controller = newControllers[controllerName];
|
|
@@ -27,15 +87,26 @@ const controllersRegistry = () => {
|
|
|
27
87
|
}
|
|
28
88
|
controllers[uid] = controller;
|
|
29
89
|
}
|
|
90
|
+
|
|
30
91
|
return this;
|
|
31
92
|
},
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Wraps a controller to extend it
|
|
96
|
+
* @param {string} uid
|
|
97
|
+
* @param {(controller: Controller) => Controller} extendFn
|
|
98
|
+
*/
|
|
32
99
|
extend(controllerUID, extendFn) {
|
|
33
100
|
const currentController = this.get(controllerUID);
|
|
101
|
+
|
|
34
102
|
if (!currentController) {
|
|
35
103
|
throw new Error(`Controller ${controllerUID} doesn't exist`);
|
|
36
104
|
}
|
|
105
|
+
|
|
37
106
|
const newController = extendFn(currentController);
|
|
38
|
-
|
|
107
|
+
instances[controllerUID] = newController;
|
|
108
|
+
|
|
109
|
+
return this;
|
|
39
110
|
},
|
|
40
111
|
};
|
|
41
112
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const _ = require('lodash');
|
|
4
3
|
const { pickBy, has } = require('lodash/fp');
|
|
5
4
|
const { addNamespace, hasNamespace } = require('../utils');
|
|
6
5
|
|
|
@@ -37,8 +36,6 @@ const servicesRegistry = strapi => {
|
|
|
37
36
|
instantiatedServices[uid] = typeof service === 'function' ? service({ strapi }) : service;
|
|
38
37
|
return instantiatedServices[uid];
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
return undefined;
|
|
42
39
|
},
|
|
43
40
|
|
|
44
41
|
/**
|
|
@@ -49,16 +46,28 @@ const servicesRegistry = strapi => {
|
|
|
49
46
|
getAll(namespace) {
|
|
50
47
|
const filteredServices = pickBy((_, uid) => hasNamespace(uid, namespace))(services);
|
|
51
48
|
|
|
52
|
-
|
|
49
|
+
// create lazy accessor to avoid instantiating the services;
|
|
50
|
+
const map = {};
|
|
51
|
+
for (const uid in filteredServices) {
|
|
52
|
+
Object.defineProperty(map, uid, {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: () => {
|
|
55
|
+
return this.get(uid);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return map;
|
|
53
61
|
},
|
|
54
62
|
|
|
55
63
|
/**
|
|
56
64
|
* Registers a service
|
|
57
65
|
* @param {string} uid
|
|
58
|
-
* @param {Service
|
|
66
|
+
* @param {Service} service
|
|
59
67
|
*/
|
|
60
68
|
set(uid, service) {
|
|
61
|
-
|
|
69
|
+
services[uid] = service;
|
|
70
|
+
delete instantiatedServices[uid];
|
|
62
71
|
return this;
|
|
63
72
|
},
|
|
64
73
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isObject } = require('lodash/fp');
|
|
4
|
+
const { ValidationError } = require('@strapi/utils').errors;
|
|
5
|
+
|
|
3
6
|
const { parseBody } = require('./transform');
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
*
|
|
7
10
|
* Returns a collection type controller to handle default core-api actions
|
|
8
11
|
*/
|
|
9
|
-
const createCollectionTypeController = ({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sanitizeOutput,
|
|
13
|
-
transformResponse,
|
|
14
|
-
}) => {
|
|
12
|
+
const createCollectionTypeController = ({ contentType }) => {
|
|
13
|
+
const { uid } = contentType;
|
|
14
|
+
|
|
15
15
|
return {
|
|
16
16
|
/**
|
|
17
17
|
* Retrieve records.
|
|
@@ -21,10 +21,10 @@ const createCollectionTypeController = ({
|
|
|
21
21
|
async find(ctx) {
|
|
22
22
|
const { query } = ctx;
|
|
23
23
|
|
|
24
|
-
const { results, pagination } = await service.find(query);
|
|
25
|
-
const sanitizedResults = await sanitizeOutput(results, ctx);
|
|
24
|
+
const { results, pagination } = await strapi.service(uid).find(query);
|
|
25
|
+
const sanitizedResults = await this.sanitizeOutput(results, ctx);
|
|
26
26
|
|
|
27
|
-
return transformResponse(sanitizedResults, { pagination });
|
|
27
|
+
return this.transformResponse(sanitizedResults, { pagination });
|
|
28
28
|
},
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -36,10 +36,10 @@ const createCollectionTypeController = ({
|
|
|
36
36
|
const { id } = ctx.params;
|
|
37
37
|
const { query } = ctx;
|
|
38
38
|
|
|
39
|
-
const entity = await service.findOne(id, query);
|
|
40
|
-
const sanitizedEntity = await sanitizeOutput(entity, ctx);
|
|
39
|
+
const entity = await strapi.service(uid).findOne(id, query);
|
|
40
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
41
41
|
|
|
42
|
-
return transformResponse(sanitizedEntity);
|
|
42
|
+
return this.transformResponse(sanitizedEntity);
|
|
43
43
|
},
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -51,12 +51,19 @@ const createCollectionTypeController = ({
|
|
|
51
51
|
const { query } = ctx.request;
|
|
52
52
|
|
|
53
53
|
const { data, files } = parseBody(ctx);
|
|
54
|
-
const sanitizedInputData = await sanitizeInput(data, ctx);
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if (!isObject(data)) {
|
|
56
|
+
throw new ValidationError('Missing "data" payload in the request body');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const sanitizedInputData = await this.sanitizeInput(data, ctx);
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
const entity = await strapi
|
|
62
|
+
.service(uid)
|
|
63
|
+
.create({ ...query, data: sanitizedInputData, files });
|
|
64
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
65
|
+
|
|
66
|
+
return this.transformResponse(sanitizedEntity);
|
|
60
67
|
},
|
|
61
68
|
|
|
62
69
|
/**
|
|
@@ -69,12 +76,19 @@ const createCollectionTypeController = ({
|
|
|
69
76
|
const { query } = ctx.request;
|
|
70
77
|
|
|
71
78
|
const { data, files } = parseBody(ctx);
|
|
72
|
-
const sanitizedInputData = await sanitizeInput(data, ctx);
|
|
73
79
|
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
if (!isObject(data)) {
|
|
81
|
+
throw new ValidationError('Missing "data" payload in the request body');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const sanitizedInputData = await this.sanitizeInput(data, ctx);
|
|
85
|
+
|
|
86
|
+
const entity = await strapi
|
|
87
|
+
.service(uid)
|
|
88
|
+
.update(id, { ...query, data: sanitizedInputData, files });
|
|
89
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
76
90
|
|
|
77
|
-
return transformResponse(sanitizedEntity);
|
|
91
|
+
return this.transformResponse(sanitizedEntity);
|
|
78
92
|
},
|
|
79
93
|
|
|
80
94
|
/**
|
|
@@ -86,10 +100,10 @@ const createCollectionTypeController = ({
|
|
|
86
100
|
const { id } = ctx.params;
|
|
87
101
|
const { query } = ctx;
|
|
88
102
|
|
|
89
|
-
const entity = await service.delete(id, query);
|
|
90
|
-
const sanitizedEntity = await sanitizeOutput(entity, ctx);
|
|
103
|
+
const entity = await strapi.service(uid).delete(id, query);
|
|
104
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
91
105
|
|
|
92
|
-
return transformResponse(sanitizedEntity);
|
|
106
|
+
return this.transformResponse(sanitizedEntity);
|
|
93
107
|
},
|
|
94
108
|
};
|
|
95
109
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Context } from 'koa';
|
|
2
|
+
|
|
3
|
+
type Response = object;
|
|
4
|
+
|
|
5
|
+
interface BaseController {
|
|
6
|
+
transformResponse(data: object, meta: object): object;
|
|
7
|
+
sanitizeOutput(data: object, ctx: Context): Promise<object>;
|
|
8
|
+
sanitizeInput(data: object, ctx: Context): Promise<object>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SingleTypeController extends BaseController {
|
|
12
|
+
find(ctx: Context): Promise<Response>;
|
|
13
|
+
update(ctx: Context): Promise<Response>;
|
|
14
|
+
delete(ctx: Context): Promise<Response>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface CollectionTypeController extends BaseController {
|
|
18
|
+
find(ctx: Context): Promise<Response>;
|
|
19
|
+
findOne(ctx: Context): Promise<Response>;
|
|
20
|
+
create(ctx: Context): Promise<Response>;
|
|
21
|
+
update(ctx: Context): Promise<Response>;
|
|
22
|
+
delete(ctx: Context): Promise<Response>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type Controller = SingleTypeController | CollectionTypeController;
|
|
@@ -10,31 +10,36 @@ const createCollectionTypeController = require('./collection-type');
|
|
|
10
10
|
|
|
11
11
|
const getAuthFromKoaContext = getOr({}, 'state.auth');
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
const ctx = {
|
|
15
|
-
model,
|
|
16
|
-
service,
|
|
13
|
+
const createController = ({ contentType }) => {
|
|
14
|
+
const ctx = { contentType };
|
|
17
15
|
|
|
16
|
+
const proto = {
|
|
18
17
|
transformResponse(data, meta) {
|
|
19
|
-
return transformResponse(data, meta, { contentType
|
|
18
|
+
return transformResponse(data, meta, { contentType });
|
|
20
19
|
},
|
|
21
20
|
|
|
22
21
|
sanitizeOutput(data, ctx) {
|
|
23
22
|
const auth = getAuthFromKoaContext(ctx);
|
|
24
23
|
|
|
25
|
-
return sanitize.contentAPI.output(data,
|
|
24
|
+
return sanitize.contentAPI.output(data, contentType, { auth });
|
|
26
25
|
},
|
|
27
26
|
|
|
28
27
|
sanitizeInput(data, ctx) {
|
|
29
28
|
const auth = getAuthFromKoaContext(ctx);
|
|
30
29
|
|
|
31
|
-
return sanitize.contentAPI.input(data,
|
|
30
|
+
return sanitize.contentAPI.input(data, contentType, { auth });
|
|
32
31
|
},
|
|
33
32
|
};
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
let ctrl;
|
|
35
|
+
|
|
36
|
+
if (contentTypes.isSingleType(contentType)) {
|
|
37
|
+
ctrl = createSingleTypeController(ctx);
|
|
38
|
+
} else {
|
|
39
|
+
ctrl = createCollectionTypeController(ctx);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
return
|
|
42
|
+
return Object.assign(Object.create(proto), ctrl);
|
|
40
43
|
};
|
|
44
|
+
|
|
45
|
+
module.exports = { createController };
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isObject } = require('lodash/fp');
|
|
4
|
+
const { ValidationError } = require('@strapi/utils').errors;
|
|
5
|
+
|
|
3
6
|
const { parseBody } = require('./transform');
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Returns a single type controller to handle default core-api actions
|
|
7
10
|
*/
|
|
8
|
-
const createSingleTypeController = ({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
sanitizeOutput,
|
|
12
|
-
transformResponse,
|
|
13
|
-
}) => {
|
|
11
|
+
const createSingleTypeController = ({ contentType }) => {
|
|
12
|
+
const { uid } = contentType;
|
|
13
|
+
|
|
14
14
|
return {
|
|
15
15
|
/**
|
|
16
16
|
* Retrieve single type content
|
|
@@ -20,10 +20,10 @@ const createSingleTypeController = ({
|
|
|
20
20
|
async find(ctx) {
|
|
21
21
|
const { query } = ctx;
|
|
22
22
|
|
|
23
|
-
const entity = await service.find(query);
|
|
24
|
-
const sanitizedEntity = await sanitizeOutput(entity, ctx);
|
|
23
|
+
const entity = await strapi.service(uid).find(query);
|
|
24
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
25
25
|
|
|
26
|
-
return transformResponse(sanitizedEntity);
|
|
26
|
+
return this.transformResponse(sanitizedEntity);
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -34,21 +34,28 @@ const createSingleTypeController = ({
|
|
|
34
34
|
async update(ctx) {
|
|
35
35
|
const { query } = ctx.request;
|
|
36
36
|
const { data, files } = parseBody(ctx);
|
|
37
|
-
const sanitizedInputData = await sanitizeInput(data, ctx);
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
if (!isObject(data)) {
|
|
39
|
+
throw new ValidationError('Missing "data" payload in the request body');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const sanitizedInputData = await this.sanitizeInput(data, ctx);
|
|
43
|
+
|
|
44
|
+
const entity = await strapi
|
|
45
|
+
.service(uid)
|
|
46
|
+
.createOrUpdate({ ...query, data: sanitizedInputData, files });
|
|
47
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
41
48
|
|
|
42
|
-
return transformResponse(sanitizedEntity);
|
|
49
|
+
return this.transformResponse(sanitizedEntity);
|
|
43
50
|
},
|
|
44
51
|
|
|
45
52
|
async delete(ctx) {
|
|
46
53
|
const { query } = ctx;
|
|
47
54
|
|
|
48
|
-
const entity = await service.delete(query);
|
|
49
|
-
const sanitizedEntity = await sanitizeOutput(entity, ctx);
|
|
55
|
+
const entity = await strapi.service(uid).delete(query);
|
|
56
|
+
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
|
|
50
57
|
|
|
51
|
-
return transformResponse(sanitizedEntity);
|
|
58
|
+
return this.transformResponse(sanitizedEntity);
|
|
52
59
|
},
|
|
53
60
|
};
|
|
54
61
|
};
|