@strapi/strapi 4.3.4 → 4.3.5
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 +1 -1
- package/bin/strapi.js +29 -26
- package/lib/Strapi.js +9 -9
- package/lib/commands/admin-create.js +2 -5
- package/lib/commands/admin-reset.js +1 -1
- package/lib/commands/build.js +1 -1
- package/lib/commands/builders/admin.js +1 -1
- package/lib/commands/builders/typescript.js +2 -2
- package/lib/commands/configurationDump.js +3 -3
- package/lib/commands/configurationRestore.js +5 -4
- package/lib/commands/console.js +1 -1
- package/lib/commands/content-types/list.js +2 -2
- package/lib/commands/controllers/list.js +2 -2
- package/lib/commands/develop.js +16 -10
- package/lib/commands/hooks/list.js +2 -2
- package/lib/commands/install.js +4 -4
- package/lib/commands/middlewares/list.js +2 -2
- package/lib/commands/new.js +1 -1
- package/lib/commands/opt-in-telemetry.js +12 -13
- package/lib/commands/opt-out-telemetry.js +3 -3
- package/lib/commands/policies/list.js +2 -2
- package/lib/commands/routes/list.js +3 -3
- package/lib/commands/services/list.js +2 -2
- package/lib/commands/start.js +1 -0
- package/lib/commands/ts/generate-types.js +1 -1
- package/lib/commands/uninstall.js +4 -4
- package/lib/commands/watchAdmin.js +1 -1
- package/lib/compile.js +1 -1
- package/lib/container.js +1 -1
- package/lib/core/app-configuration/config-loader.js +2 -2
- package/lib/core/app-configuration/load-config-file.js +3 -3
- package/lib/core/bootstrap.js +1 -1
- package/lib/core/domain/component/validator.js +3 -9
- package/lib/core/domain/content-type/index.js +2 -2
- package/lib/core/domain/content-type/validator.js +9 -23
- package/lib/core/domain/module/index.js +1 -1
- package/lib/core/domain/module/validation.js +3 -4
- package/lib/core/loaders/admin.js +1 -1
- package/lib/core/loaders/apis.js +22 -30
- package/lib/core/loaders/components.js +2 -2
- package/lib/core/loaders/middlewares.js +1 -1
- package/lib/core/loaders/plugins/get-enabled-plugins.js +7 -7
- package/lib/core/loaders/plugins/index.js +7 -8
- package/lib/core/loaders/sanitizers.js +1 -1
- package/lib/core/loaders/src-index.js +2 -2
- package/lib/core/registries/apis.js +1 -1
- package/lib/core/registries/config.js +1 -1
- package/lib/core/registries/content-types.js +1 -1
- package/lib/core/registries/modules.js +1 -1
- package/lib/core/registries/plugins.js +1 -1
- package/lib/core/registries/services.js +1 -1
- package/lib/core/utils.js +3 -6
- package/lib/core-api/controller/transform.js +4 -4
- package/lib/core-api/service/collection-type.js +1 -1
- package/lib/core-api/service/index.d.ts +6 -3
- package/lib/core-api/service/pagination.js +5 -5
- package/lib/factories.js +5 -5
- package/lib/load/filepath-to-prop-path.js +2 -2
- package/lib/load/load-files.js +1 -1
- package/lib/load/package-path.js +1 -1
- package/lib/middlewares/body.js +7 -3
- package/lib/middlewares/compression.js +1 -1
- package/lib/middlewares/cors.js +3 -10
- package/lib/middlewares/ip.js +1 -1
- package/lib/middlewares/logger.js +4 -1
- package/lib/middlewares/powered-by.js +1 -1
- package/lib/middlewares/query.js +8 -2
- package/lib/middlewares/response-time.js +1 -1
- package/lib/middlewares/responses.js +1 -1
- package/lib/middlewares/security.js +21 -16
- package/lib/middlewares/session.js +2 -2
- package/lib/migrations/draft-publish.js +1 -5
- package/lib/services/auth/index.js +1 -3
- package/lib/services/core-store.js +4 -4
- package/lib/services/entity-service/components.js +12 -18
- package/lib/services/entity-service/index.js +65 -51
- package/lib/services/entity-validator/index.js +134 -127
- package/lib/services/entity-validator/validators.js +18 -15
- package/lib/services/errors.js +6 -10
- package/lib/services/event-hub.js +1 -0
- package/lib/services/fs.js +1 -1
- package/lib/services/metrics/index.js +6 -9
- package/lib/services/metrics/is-truthy.js +1 -1
- package/lib/services/metrics/sender.js +4 -4
- package/lib/services/metrics/stringify-deep.js +1 -1
- package/lib/services/server/admin-api.js +1 -1
- package/lib/services/server/compose-endpoint.js +7 -7
- package/lib/services/server/content-api.js +1 -1
- package/lib/services/server/http-server.js +9 -9
- package/lib/services/server/index.js +4 -4
- package/lib/services/server/koa.js +9 -12
- package/lib/services/server/middleware.js +1 -1
- package/lib/services/server/policy.js +1 -1
- package/lib/services/server/register-middlewares.js +6 -8
- package/lib/services/server/register-routes.js +11 -11
- package/lib/services/server/routing.js +11 -26
- package/lib/services/utils/upload-files.js +3 -3
- package/lib/services/webhook-runner.js +8 -7
- package/lib/services/webhook-store.js +3 -2
- package/lib/services/worker-queue.js +1 -0
- package/lib/types/core/strapi/index.d.ts +4 -3
- package/lib/types/factories.d.ts +3 -3
- package/lib/utils/addSlash.js +3 -3
- package/lib/utils/ee.js +1 -1
- package/lib/utils/import-default.js +1 -1
- package/lib/utils/open-browser.js +1 -1
- package/lib/utils/run-checks.js +4 -4
- package/lib/utils/signals.js +2 -2
- package/lib/utils/startup-logger.js +2 -2
- package/lib/utils/success.js +1 -1
- package/lib/utils/update-notifier/index.js +4 -4
- package/package.json +14 -14
|
@@ -21,7 +21,7 @@ const getLimitConfigDefaults = () => ({
|
|
|
21
21
|
const shouldApplyMaxLimit = (limit, maxLimit = null, { isPagedPagination = false } = {}) =>
|
|
22
22
|
(!isPagedPagination && limit === -1) || (maxLimit && limit > maxLimit);
|
|
23
23
|
|
|
24
|
-
const shouldCount = params => {
|
|
24
|
+
const shouldCount = (params) => {
|
|
25
25
|
if (has('pagination.withCount', params)) {
|
|
26
26
|
const { withCount } = params.pagination;
|
|
27
27
|
|
|
@@ -45,10 +45,10 @@ const shouldCount = params => {
|
|
|
45
45
|
return Boolean(strapi.config.get('api.rest.withCount', true));
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const isOffsetPagination = pagination => has('start', pagination) || has('limit', pagination);
|
|
49
|
-
const isPagedPagination = pagination => has('page', pagination) || has('pageSize', pagination);
|
|
48
|
+
const isOffsetPagination = (pagination) => has('start', pagination) || has('limit', pagination);
|
|
49
|
+
const isPagedPagination = (pagination) => has('page', pagination) || has('pageSize', pagination);
|
|
50
50
|
|
|
51
|
-
const getPaginationInfo = params => {
|
|
51
|
+
const getPaginationInfo = (params) => {
|
|
52
52
|
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
|
|
53
53
|
|
|
54
54
|
const { pagination } = params;
|
|
@@ -90,7 +90,7 @@ const getPaginationInfo = params => {
|
|
|
90
90
|
};
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
const convertPagedToStartLimit = pagination => {
|
|
93
|
+
const convertPagedToStartLimit = (pagination) => {
|
|
94
94
|
if (isPagedPagination(pagination)) {
|
|
95
95
|
const { page, pageSize } = pagination;
|
|
96
96
|
return {
|
package/lib/factories.js
CHANGED
|
@@ -12,7 +12,7 @@ const createCoreController = (uid, cfg = {}) => {
|
|
|
12
12
|
contentType: strapi.contentType(uid),
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const userCtrl = typeof cfg === 'function' ? cfg({ strapi }) : cfg;
|
|
16
16
|
|
|
17
17
|
for (const methodName of Object.keys(baseController)) {
|
|
18
18
|
if (userCtrl[methodName] === undefined) {
|
|
@@ -31,7 +31,7 @@ const createCoreService = (uid, cfg = {}) => {
|
|
|
31
31
|
contentType: strapi.contentType(uid),
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const userService = typeof cfg === 'function' ? cfg({ strapi }) : cfg;
|
|
35
35
|
|
|
36
36
|
for (const methodName of Object.keys(baseService)) {
|
|
37
37
|
if (userService[methodName] === undefined) {
|
|
@@ -58,15 +58,15 @@ const createCoreRouter = (uid, cfg = {}) => {
|
|
|
58
58
|
|
|
59
59
|
const defaultRoutes = createRoutes({ contentType });
|
|
60
60
|
|
|
61
|
-
Object.keys(defaultRoutes).forEach(routeName => {
|
|
61
|
+
Object.keys(defaultRoutes).forEach((routeName) => {
|
|
62
62
|
const defaultRoute = defaultRoutes[routeName];
|
|
63
63
|
|
|
64
64
|
Object.assign(defaultRoute.config, config[routeName] || {});
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
const selectedRoutes = pipe(
|
|
68
|
-
routes => (except ? omit(except, routes) : routes),
|
|
69
|
-
routes => (only ? pick(only, routes) : routes)
|
|
68
|
+
(routes) => (except ? omit(except, routes) : routes),
|
|
69
|
+
(routes) => (only ? pick(only, routes) : routes)
|
|
70
70
|
)(defaultRoutes);
|
|
71
71
|
|
|
72
72
|
routes = Object.values(selectedRoutes);
|
|
@@ -8,13 +8,13 @@ const _ = require('lodash');
|
|
|
8
8
|
* @param {boolean} useFileNameAsKey - wethear to skip the last path key
|
|
9
9
|
*/
|
|
10
10
|
module.exports = (filePath, useFileNameAsKey = true) => {
|
|
11
|
-
|
|
11
|
+
const cleanPath = filePath.startsWith('./') ? filePath.slice(2) : filePath;
|
|
12
12
|
|
|
13
13
|
const prop = cleanPath
|
|
14
14
|
.replace(/(\.settings|\.json|\.js)/g, '')
|
|
15
15
|
.toLowerCase()
|
|
16
16
|
.split('/')
|
|
17
|
-
.map(p => _.trimStart(p, '.'))
|
|
17
|
+
.map((p) => _.trimStart(p, '.'))
|
|
18
18
|
.join('.')
|
|
19
19
|
.split('.');
|
|
20
20
|
|
package/lib/load/load-files.js
CHANGED
package/lib/load/package-path.js
CHANGED
|
@@ -6,4 +6,4 @@ const path = require('path');
|
|
|
6
6
|
* Returns the path to a node modules root directory (not the main file path)
|
|
7
7
|
* @param {string} moduleName - name of a node module
|
|
8
8
|
*/
|
|
9
|
-
module.exports = moduleName => path.dirname(require.resolve(`${moduleName}/package.json`));
|
|
9
|
+
module.exports = (moduleName) => path.dirname(require.resolve(`${moduleName}/package.json`));
|
package/lib/middlewares/body.js
CHANGED
|
@@ -23,12 +23,16 @@ 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
|
+
const { config: gqlConfig } = strapi.plugin('graphql');
|
|
31
|
+
const gqlEndpoint = gqlConfig('endpoint');
|
|
32
|
+
|
|
29
33
|
return async (ctx, next) => {
|
|
30
34
|
// TODO: find a better way later
|
|
31
|
-
if (ctx.url ===
|
|
35
|
+
if (ctx.url === gqlEndpoint) {
|
|
32
36
|
await next();
|
|
33
37
|
} else {
|
|
34
38
|
try {
|
|
@@ -64,7 +68,7 @@ module.exports = config => {
|
|
|
64
68
|
if (files) {
|
|
65
69
|
if (Array.isArray(files)) {
|
|
66
70
|
// not awaiting to not slow the request
|
|
67
|
-
Promise.all(files.map(file => fse.remove(file.path)));
|
|
71
|
+
Promise.all(files.map((file) => fse.remove(file.path)));
|
|
68
72
|
} else if (files && files.path) {
|
|
69
73
|
// not awaiting to not slow the request
|
|
70
74
|
fse.remove(files.path);
|
package/lib/middlewares/cors.js
CHANGED
|
@@ -15,16 +15,9 @@ const defaults = {
|
|
|
15
15
|
/**
|
|
16
16
|
* @type {import('./').MiddlewareFactory}
|
|
17
17
|
*/
|
|
18
|
-
module.exports = config => {
|
|
19
|
-
const {
|
|
20
|
-
|
|
21
|
-
expose,
|
|
22
|
-
maxAge,
|
|
23
|
-
credentials,
|
|
24
|
-
methods,
|
|
25
|
-
headers,
|
|
26
|
-
keepHeadersOnError,
|
|
27
|
-
} = defaultsDeep(defaults, config);
|
|
18
|
+
module.exports = (config) => {
|
|
19
|
+
const { origin, expose, maxAge, credentials, methods, headers, keepHeadersOnError } =
|
|
20
|
+
defaultsDeep(defaults, config);
|
|
28
21
|
|
|
29
22
|
return cors({
|
|
30
23
|
async origin(ctx) {
|
package/lib/middlewares/ip.js
CHANGED
package/lib/middlewares/query.js
CHANGED
|
@@ -21,8 +21,14 @@ const addQsParser = (app, settings) => {
|
|
|
21
21
|
*/
|
|
22
22
|
get() {
|
|
23
23
|
const qstr = this.querystring;
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
this._querycache = this._querycache || {};
|
|
25
|
+
const cache = this._querycache;
|
|
26
|
+
|
|
27
|
+
if (!cache[qstr]) {
|
|
28
|
+
cache[qstr] = qs.parse(qstr, settings);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return cache[qstr];
|
|
26
32
|
},
|
|
27
33
|
|
|
28
34
|
/*
|
|
@@ -30,22 +30,27 @@ const defaults = {
|
|
|
30
30
|
/**
|
|
31
31
|
* @type {import('./').MiddlewareFactory}
|
|
32
32
|
*/
|
|
33
|
-
module.exports = config => (ctx, next) => {
|
|
34
|
-
let helmetConfig = defaultsDeep(defaults, config);
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
module.exports =
|
|
35
|
+
(config, { strapi }) =>
|
|
36
|
+
(ctx, next) => {
|
|
37
|
+
let helmetConfig = defaultsDeep(defaults, config);
|
|
38
|
+
const { config: gqlConfig } = strapi.plugin('graphql');
|
|
39
|
+
const gqlEndpoint = gqlConfig('endpoint');
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
ctx.method === 'GET' &&
|
|
43
|
+
[gqlEndpoint, '/documentation'].some((str) => ctx.path.startsWith(str))
|
|
44
|
+
) {
|
|
45
|
+
helmetConfig = merge(helmetConfig, {
|
|
46
|
+
contentSecurityPolicy: {
|
|
47
|
+
directives: {
|
|
48
|
+
'script-src': ["'self'", "'unsafe-inline'", 'cdn.jsdelivr.net'],
|
|
49
|
+
'img-src': ["'self'", 'data:', 'cdn.jsdelivr.net', 'strapi.io'],
|
|
50
|
+
},
|
|
45
51
|
},
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
};
|
|
55
|
+
return helmet(helmetConfig)(ctx, next);
|
|
56
|
+
};
|
|
@@ -12,12 +12,12 @@ const defaultConfig = {
|
|
|
12
12
|
signed: true,
|
|
13
13
|
rolling: false,
|
|
14
14
|
renew: false,
|
|
15
|
-
secure: process.env.NODE_ENV === 'production'
|
|
15
|
+
secure: process.env.NODE_ENV === 'production',
|
|
16
16
|
sameSite: null,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
module.exports = (userConfig, { strapi }) => {
|
|
20
|
-
const keys = strapi.server.app
|
|
20
|
+
const { keys } = strapi.server.app;
|
|
21
21
|
if (!isArray(keys) || isEmpty(keys) || keys.some(isEmpty)) {
|
|
22
22
|
throw new Error(
|
|
23
23
|
`App keys are required. Please set app.keys in config/server.js (ex: keys: ['myKeyA', 'myKeyB'])`
|
|
@@ -42,11 +42,7 @@ const disableDraftAndPublish = async ({ oldContentTypes, contentTypes }) => {
|
|
|
42
42
|
|
|
43
43
|
// if d&p was disabled remove unpublish content before sync
|
|
44
44
|
if (hasDraftAndPublish(oldContentType) && !hasDraftAndPublish(contentType)) {
|
|
45
|
-
await strapi.db
|
|
46
|
-
.queryBuilder(uid)
|
|
47
|
-
.delete()
|
|
48
|
-
.where({ published_at: null })
|
|
49
|
-
.execute();
|
|
45
|
+
await strapi.db.queryBuilder(uid).delete().where({ published_at: null }).execute();
|
|
50
46
|
}
|
|
51
47
|
}
|
|
52
48
|
};
|
|
@@ -8,7 +8,7 @@ const { UnauthorizedError } = require('@strapi/utils').errors;
|
|
|
8
8
|
const INVALID_STRATEGY_MSG =
|
|
9
9
|
'Invalid auth strategy. Expecting an object with properties {name: string, authenticate: function, verify: function}';
|
|
10
10
|
|
|
11
|
-
const validStrategy = strategy => {
|
|
11
|
+
const validStrategy = (strategy) => {
|
|
12
12
|
assert(has('authenticate', strategy), INVALID_STRATEGY_MSG);
|
|
13
13
|
assert(typeof strategy.authenticate === 'function', INVALID_STRATEGY_MSG);
|
|
14
14
|
|
|
@@ -78,8 +78,6 @@ const createAuthentication = () => {
|
|
|
78
78
|
if (typeof auth.strategy.verify === 'function') {
|
|
79
79
|
return auth.strategy.verify(auth, config);
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
return;
|
|
83
81
|
},
|
|
84
82
|
};
|
|
85
83
|
};
|
|
@@ -30,11 +30,11 @@ const createCoreStore = ({ db }) => {
|
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
const store = function(defaultParams = {}) {
|
|
33
|
+
const store = function (defaultParams = {}) {
|
|
34
34
|
return {
|
|
35
|
-
get: params => store.get(mergeParams(defaultParams, params)),
|
|
36
|
-
set: params => store.set(mergeParams(defaultParams, params)),
|
|
37
|
-
delete: params => store.delete(mergeParams(defaultParams, params)),
|
|
35
|
+
get: (params) => store.get(mergeParams(defaultParams, params)),
|
|
36
|
+
set: (params) => store.set(mergeParams(defaultParams, params)),
|
|
37
|
+
delete: (params) => store.delete(mergeParams(defaultParams, params)),
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
|
|
@@ -8,7 +8,7 @@ const { ApplicationError } = require('@strapi/utils').errors;
|
|
|
8
8
|
|
|
9
9
|
const omitComponentData = (contentType, data) => {
|
|
10
10
|
const { attributes } = contentType;
|
|
11
|
-
const componentAttributes = Object.keys(attributes).filter(attributeName =>
|
|
11
|
+
const componentAttributes = Object.keys(attributes).filter((attributeName) =>
|
|
12
12
|
contentTypesUtils.isComponentAttribute(attributes[attributeName])
|
|
13
13
|
);
|
|
14
14
|
|
|
@@ -43,7 +43,7 @@ const createComponents = async (uid, data) => {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
const components = await Promise.all(
|
|
46
|
-
componentValue.map(value => createComponent(componentUID, value))
|
|
46
|
+
componentValue.map((value) => createComponent(componentUID, value))
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
// TODO: add order
|
|
@@ -129,7 +129,7 @@ const updateComponents = async (uid, entityToUpdate, data) => {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
const components = await Promise.all(
|
|
132
|
-
componentValue.map(value => updateOrCreateComponent(componentUID, value))
|
|
132
|
+
componentValue.map((value) => updateOrCreateComponent(componentUID, value))
|
|
133
133
|
);
|
|
134
134
|
|
|
135
135
|
componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }, idx) => {
|
|
@@ -197,17 +197,11 @@ const deleteOldComponents = async (
|
|
|
197
197
|
) => {
|
|
198
198
|
const previousValue = await strapi.query(uid).load(entityToUpdate, attributeName);
|
|
199
199
|
|
|
200
|
-
const idsToKeep = _.castArray(componentValue)
|
|
201
|
-
.filter(has('id'))
|
|
202
|
-
.map(prop('id'))
|
|
203
|
-
.map(toString);
|
|
200
|
+
const idsToKeep = _.castArray(componentValue).filter(has('id')).map(prop('id')).map(toString);
|
|
204
201
|
|
|
205
|
-
const allIds = _.castArray(previousValue)
|
|
206
|
-
.filter(has('id'))
|
|
207
|
-
.map(prop('id'))
|
|
208
|
-
.map(toString);
|
|
202
|
+
const allIds = _.castArray(previousValue).filter(has('id')).map(prop('id')).map(toString);
|
|
209
203
|
|
|
210
|
-
idsToKeep.forEach(id => {
|
|
204
|
+
idsToKeep.forEach((id) => {
|
|
211
205
|
if (!allIds.includes(id)) {
|
|
212
206
|
throw new ApplicationError(
|
|
213
207
|
`Some of the provided components in ${attributeName} are not related to the entity`
|
|
@@ -242,7 +236,7 @@ const deleteOldDZComponents = async (uid, entityToUpdate, attributeName, dynamic
|
|
|
242
236
|
}));
|
|
243
237
|
|
|
244
238
|
idsToKeep.forEach(({ id, __component }) => {
|
|
245
|
-
if (!allIds.find(el => el.id === id && el.__component === __component)) {
|
|
239
|
+
if (!allIds.find((el) => el.id === id && el.__component === __component)) {
|
|
246
240
|
const err = new Error(
|
|
247
241
|
`Some of the provided components in ${attributeName} are not related to the entity`
|
|
248
242
|
);
|
|
@@ -252,7 +246,7 @@ const deleteOldDZComponents = async (uid, entityToUpdate, attributeName, dynamic
|
|
|
252
246
|
});
|
|
253
247
|
|
|
254
248
|
const idsToDelete = allIds.reduce((acc, { id, __component }) => {
|
|
255
|
-
if (!idsToKeep.find(el => el.id === id && el.__component === __component)) {
|
|
249
|
+
if (!idsToKeep.find((el) => el.id === id && el.__component === __component)) {
|
|
256
250
|
acc.push({ id, __component });
|
|
257
251
|
}
|
|
258
252
|
|
|
@@ -283,7 +277,7 @@ const deleteComponents = async (uid, entityToDelete) => {
|
|
|
283
277
|
}
|
|
284
278
|
|
|
285
279
|
if (Array.isArray(value)) {
|
|
286
|
-
await Promise.all(value.map(subValue => deleteComponent(componentUID, subValue)));
|
|
280
|
+
await Promise.all(value.map((subValue) => deleteComponent(componentUID, subValue)));
|
|
287
281
|
} else {
|
|
288
282
|
await deleteComponent(componentUID, value);
|
|
289
283
|
}
|
|
@@ -299,7 +293,7 @@ const deleteComponents = async (uid, entityToDelete) => {
|
|
|
299
293
|
}
|
|
300
294
|
|
|
301
295
|
if (Array.isArray(value)) {
|
|
302
|
-
await Promise.all(value.map(subValue => deleteComponent(subValue.__component, subValue)));
|
|
296
|
+
await Promise.all(value.map((subValue) => deleteComponent(subValue.__component, subValue)));
|
|
303
297
|
}
|
|
304
298
|
|
|
305
299
|
continue;
|
|
@@ -307,9 +301,9 @@ const deleteComponents = async (uid, entityToDelete) => {
|
|
|
307
301
|
}
|
|
308
302
|
};
|
|
309
303
|
|
|
310
|
-
|
|
304
|
+
/** *************************
|
|
311
305
|
Component queries
|
|
312
|
-
|
|
306
|
+
************************** */
|
|
313
307
|
|
|
314
308
|
// components can have nested compos so this must be recursive
|
|
315
309
|
const createComponent = async (uid, data) => {
|
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const _ = require('lodash');
|
|
4
4
|
const delegate = require('delegates');
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
InvalidDateError,
|
|
8
|
-
InvalidDateTimeError,
|
|
9
|
-
} = require('@strapi/database').errors;
|
|
5
|
+
const { InvalidTimeError, InvalidDateError, InvalidDateTimeError } =
|
|
6
|
+
require('@strapi/database').errors;
|
|
10
7
|
const {
|
|
11
8
|
webhook: webhookUtils,
|
|
12
9
|
contentTypes: contentTypesUtils,
|
|
@@ -37,51 +34,6 @@ const updatePipeline = (data, context) => {
|
|
|
37
34
|
return applyTransforms(data, context);
|
|
38
35
|
};
|
|
39
36
|
|
|
40
|
-
module.exports = ctx => {
|
|
41
|
-
const implementation = createDefaultImplementation(ctx);
|
|
42
|
-
|
|
43
|
-
const service = {
|
|
44
|
-
implementation,
|
|
45
|
-
decorate(decorator) {
|
|
46
|
-
if (typeof decorator !== 'function') {
|
|
47
|
-
throw new Error(`Decorator must be a function, received ${typeof decorator}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this.implementation = Object.assign({}, this.implementation, decorator(this.implementation));
|
|
51
|
-
return this;
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const delegator = delegate(service, 'implementation');
|
|
56
|
-
|
|
57
|
-
// delegate every method in implementation
|
|
58
|
-
Object.keys(service.implementation).forEach(key => delegator.method(key));
|
|
59
|
-
|
|
60
|
-
// wrap methods to handle Database Errors
|
|
61
|
-
service.decorate(oldService => {
|
|
62
|
-
const newService = _.mapValues(
|
|
63
|
-
oldService,
|
|
64
|
-
(method, methodName) =>
|
|
65
|
-
async function(...args) {
|
|
66
|
-
try {
|
|
67
|
-
return await oldService[methodName].call(this, ...args);
|
|
68
|
-
} catch (error) {
|
|
69
|
-
if (
|
|
70
|
-
databaseErrorsToTransform.some(errorToTransform => error instanceof errorToTransform)
|
|
71
|
-
) {
|
|
72
|
-
throw new ValidationError(error.message);
|
|
73
|
-
}
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
return newService;
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return service;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
37
|
/**
|
|
86
38
|
* @type {import('.').default}
|
|
87
39
|
*/
|
|
@@ -276,7 +228,19 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
276
228
|
// select / populate
|
|
277
229
|
const query = transformParamsToQuery(uid, wrappedParams);
|
|
278
230
|
|
|
279
|
-
|
|
231
|
+
const entitiesToDelete = await db.query(uid).findMany(query);
|
|
232
|
+
|
|
233
|
+
if (!entitiesToDelete.length) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const deletedEntities = await db.query(uid).deleteMany(query);
|
|
238
|
+
await Promise.all(entitiesToDelete.map((entity) => deleteComponents(uid, entity)));
|
|
239
|
+
|
|
240
|
+
// Trigger webhooks. One for each entity
|
|
241
|
+
await Promise.all(entitiesToDelete.map((entity) => this.emitEvent(uid, ENTRY_DELETE, entity)));
|
|
242
|
+
|
|
243
|
+
return deletedEntities;
|
|
280
244
|
},
|
|
281
245
|
|
|
282
246
|
load(uid, entity, field, params = {}) {
|
|
@@ -303,8 +267,58 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
|
|
303
267
|
Object.assign(loadParams, transformParamsToQuery('plugin::upload.file', params));
|
|
304
268
|
break;
|
|
305
269
|
}
|
|
270
|
+
default: {
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
306
273
|
}
|
|
307
274
|
|
|
308
275
|
return db.query(uid).load(entity, field, loadParams);
|
|
309
276
|
},
|
|
310
277
|
});
|
|
278
|
+
|
|
279
|
+
module.exports = (ctx) => {
|
|
280
|
+
const implementation = createDefaultImplementation(ctx);
|
|
281
|
+
|
|
282
|
+
const service = {
|
|
283
|
+
implementation,
|
|
284
|
+
decorate(decorator) {
|
|
285
|
+
if (typeof decorator !== 'function') {
|
|
286
|
+
throw new Error(`Decorator must be a function, received ${typeof decorator}`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
this.implementation = { ...this.implementation, ...decorator(this.implementation) };
|
|
290
|
+
return this;
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const delegator = delegate(service, 'implementation');
|
|
295
|
+
|
|
296
|
+
// delegate every method in implementation
|
|
297
|
+
Object.keys(service.implementation).forEach((key) => delegator.method(key));
|
|
298
|
+
|
|
299
|
+
// wrap methods to handle Database Errors
|
|
300
|
+
service.decorate((oldService) => {
|
|
301
|
+
const newService = _.mapValues(
|
|
302
|
+
oldService,
|
|
303
|
+
(method, methodName) =>
|
|
304
|
+
async function (...args) {
|
|
305
|
+
try {
|
|
306
|
+
return await oldService[methodName].call(this, ...args);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
if (
|
|
309
|
+
databaseErrorsToTransform.some(
|
|
310
|
+
(errorToTransform) => error instanceof errorToTransform
|
|
311
|
+
)
|
|
312
|
+
) {
|
|
313
|
+
throw new ValidationError(error.message);
|
|
314
|
+
}
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
return newService;
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
return service;
|
|
324
|
+
};
|