@strapi/strapi 4.3.4 → 4.3.7
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/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 +10 -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 +22 -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 +34 -20
- package/lib/services/entity-service/index.js +73 -52
- 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 +6 -6
- 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 +15 -15
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { isNil, isPlainObject } = require('lodash/fp');
|
|
4
4
|
const { parseMultipartData } = require('@strapi/utils');
|
|
5
5
|
|
|
6
|
-
const parseBody = ctx => {
|
|
6
|
+
const parseBody = (ctx) => {
|
|
7
7
|
if (ctx.is('multipart')) {
|
|
8
8
|
return parseMultipartData(ctx);
|
|
9
9
|
}
|
|
@@ -26,7 +26,7 @@ const transformResponse = (resource, meta = {}, { contentType } = {}) => {
|
|
|
26
26
|
|
|
27
27
|
const transformComponent = (data, component) => {
|
|
28
28
|
if (Array.isArray(data)) {
|
|
29
|
-
return data.map(datum => transformComponent(datum, component));
|
|
29
|
+
return data.map((datum) => transformComponent(datum, component));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const res = transformEntry(data, component);
|
|
@@ -45,7 +45,7 @@ const transformEntry = (entry, type) => {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
if (Array.isArray(entry)) {
|
|
48
|
-
return entry.map(singleEntry => transformEntry(singleEntry, type));
|
|
48
|
+
return entry.map((singleEntry) => transformEntry(singleEntry, type));
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
if (!isPlainObject(entry)) {
|
|
@@ -71,7 +71,7 @@ const transformEntry = (entry, type) => {
|
|
|
71
71
|
attributeValues[key] = property;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
attributeValues[key] = property.map(subProperty => {
|
|
74
|
+
attributeValues[key] = property.map((subProperty) => {
|
|
75
75
|
return transformComponent(subProperty, strapi.components[subProperty.__component]);
|
|
76
76
|
});
|
|
77
77
|
} else if (attribute && attribute.type === 'media') {
|
|
@@ -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
|
+
};
|
|
@@ -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,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 {
|
|
@@ -64,7 +71,7 @@ module.exports = config => {
|
|
|
64
71
|
if (files) {
|
|
65
72
|
if (Array.isArray(files)) {
|
|
66
73
|
// not awaiting to not slow the request
|
|
67
|
-
Promise.all(files.map(file => fse.remove(file.path)));
|
|
74
|
+
Promise.all(files.map((file) => fse.remove(file.path)));
|
|
68
75
|
} else if (files && files.path) {
|
|
69
76
|
// not awaiting to not slow the request
|
|
70
77
|
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,28 @@ 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 specialPaths = ['/documentation'];
|
|
39
|
+
|
|
40
|
+
if (strapi.plugin('graphql')) {
|
|
41
|
+
const { config: gqlConfig } = strapi.plugin('graphql');
|
|
42
|
+
specialPaths.push(gqlConfig('endpoint'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (ctx.method === 'GET' && specialPaths.some((str) => ctx.path.startsWith(str))) {
|
|
46
|
+
helmetConfig = merge(helmetConfig, {
|
|
47
|
+
contentSecurityPolicy: {
|
|
48
|
+
directives: {
|
|
49
|
+
'script-src': ["'self'", "'unsafe-inline'", 'cdn.jsdelivr.net'],
|
|
50
|
+
'img-src': ["'self'", 'data:', 'cdn.jsdelivr.net', 'strapi.io'],
|
|
51
|
+
},
|
|
45
52
|
},
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
};
|
|
56
|
+
return helmet(helmetConfig)(ctx, next);
|
|
57
|
+
};
|
|
@@ -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
|
|
|
@@ -5,10 +5,11 @@ const { has, prop, omit, toString } = require('lodash/fp');
|
|
|
5
5
|
|
|
6
6
|
const { contentTypes: contentTypesUtils } = require('@strapi/utils');
|
|
7
7
|
const { ApplicationError } = require('@strapi/utils').errors;
|
|
8
|
+
const { getComponentAttributes } = require('@strapi/utils').contentTypes;
|
|
8
9
|
|
|
9
10
|
const omitComponentData = (contentType, data) => {
|
|
10
11
|
const { attributes } = contentType;
|
|
11
|
-
const componentAttributes = Object.keys(attributes).filter(attributeName =>
|
|
12
|
+
const componentAttributes = Object.keys(attributes).filter((attributeName) =>
|
|
12
13
|
contentTypesUtils.isComponentAttribute(attributes[attributeName])
|
|
13
14
|
);
|
|
14
15
|
|
|
@@ -43,7 +44,7 @@ const createComponents = async (uid, data) => {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
const components = await Promise.all(
|
|
46
|
-
componentValue.map(value => createComponent(componentUID, value))
|
|
47
|
+
componentValue.map((value) => createComponent(componentUID, value))
|
|
47
48
|
);
|
|
48
49
|
|
|
49
50
|
// TODO: add order
|
|
@@ -100,6 +101,18 @@ const createComponents = async (uid, data) => {
|
|
|
100
101
|
return componentBody;
|
|
101
102
|
};
|
|
102
103
|
|
|
104
|
+
/**
|
|
105
|
+
* @param {str} uid
|
|
106
|
+
* @param {object} entity
|
|
107
|
+
* @return {Promise<{uid: string, entity: object}>}
|
|
108
|
+
*/
|
|
109
|
+
const getComponents = async (uid, entity) => {
|
|
110
|
+
const componentAttributes = getComponentAttributes(strapi.getModel(uid));
|
|
111
|
+
|
|
112
|
+
if (_.isEmpty(componentAttributes)) return {};
|
|
113
|
+
return strapi.query(uid).load(entity, componentAttributes);
|
|
114
|
+
};
|
|
115
|
+
|
|
103
116
|
/*
|
|
104
117
|
delete old components
|
|
105
118
|
create or update
|
|
@@ -129,7 +142,7 @@ const updateComponents = async (uid, entityToUpdate, data) => {
|
|
|
129
142
|
}
|
|
130
143
|
|
|
131
144
|
const components = await Promise.all(
|
|
132
|
-
componentValue.map(value => updateOrCreateComponent(componentUID, value))
|
|
145
|
+
componentValue.map((value) => updateOrCreateComponent(componentUID, value))
|
|
133
146
|
);
|
|
134
147
|
|
|
135
148
|
componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }, idx) => {
|
|
@@ -197,17 +210,11 @@ const deleteOldComponents = async (
|
|
|
197
210
|
) => {
|
|
198
211
|
const previousValue = await strapi.query(uid).load(entityToUpdate, attributeName);
|
|
199
212
|
|
|
200
|
-
const idsToKeep = _.castArray(componentValue)
|
|
201
|
-
.filter(has('id'))
|
|
202
|
-
.map(prop('id'))
|
|
203
|
-
.map(toString);
|
|
213
|
+
const idsToKeep = _.castArray(componentValue).filter(has('id')).map(prop('id')).map(toString);
|
|
204
214
|
|
|
205
|
-
const allIds = _.castArray(previousValue)
|
|
206
|
-
.filter(has('id'))
|
|
207
|
-
.map(prop('id'))
|
|
208
|
-
.map(toString);
|
|
215
|
+
const allIds = _.castArray(previousValue).filter(has('id')).map(prop('id')).map(toString);
|
|
209
216
|
|
|
210
|
-
idsToKeep.forEach(id => {
|
|
217
|
+
idsToKeep.forEach((id) => {
|
|
211
218
|
if (!allIds.includes(id)) {
|
|
212
219
|
throw new ApplicationError(
|
|
213
220
|
`Some of the provided components in ${attributeName} are not related to the entity`
|
|
@@ -242,7 +249,7 @@ const deleteOldDZComponents = async (uid, entityToUpdate, attributeName, dynamic
|
|
|
242
249
|
}));
|
|
243
250
|
|
|
244
251
|
idsToKeep.forEach(({ id, __component }) => {
|
|
245
|
-
if (!allIds.find(el => el.id === id && el.__component === __component)) {
|
|
252
|
+
if (!allIds.find((el) => el.id === id && el.__component === __component)) {
|
|
246
253
|
const err = new Error(
|
|
247
254
|
`Some of the provided components in ${attributeName} are not related to the entity`
|
|
248
255
|
);
|
|
@@ -252,7 +259,7 @@ const deleteOldDZComponents = async (uid, entityToUpdate, attributeName, dynamic
|
|
|
252
259
|
});
|
|
253
260
|
|
|
254
261
|
const idsToDelete = allIds.reduce((acc, { id, __component }) => {
|
|
255
|
-
if (!idsToKeep.find(el => el.id === id && el.__component === __component)) {
|
|
262
|
+
if (!idsToKeep.find((el) => el.id === id && el.__component === __component)) {
|
|
256
263
|
acc.push({ id, __component });
|
|
257
264
|
}
|
|
258
265
|
|
|
@@ -276,14 +283,17 @@ const deleteComponents = async (uid, entityToDelete) => {
|
|
|
276
283
|
if (attribute.type === 'component') {
|
|
277
284
|
const { component: componentUID } = attribute;
|
|
278
285
|
|
|
279
|
-
|
|
286
|
+
// Load attribute value if it's not already loaded
|
|
287
|
+
const value =
|
|
288
|
+
entityToDelete[attributeName] ||
|
|
289
|
+
(await strapi.query(uid).load(entityToDelete, attributeName));
|
|
280
290
|
|
|
281
291
|
if (!value) {
|
|
282
292
|
continue;
|
|
283
293
|
}
|
|
284
294
|
|
|
285
295
|
if (Array.isArray(value)) {
|
|
286
|
-
await Promise.all(value.map(subValue => deleteComponent(componentUID, subValue)));
|
|
296
|
+
await Promise.all(value.map((subValue) => deleteComponent(componentUID, subValue)));
|
|
287
297
|
} else {
|
|
288
298
|
await deleteComponent(componentUID, value);
|
|
289
299
|
}
|
|
@@ -292,14 +302,16 @@ const deleteComponents = async (uid, entityToDelete) => {
|
|
|
292
302
|
}
|
|
293
303
|
|
|
294
304
|
if (attribute.type === 'dynamiczone') {
|
|
295
|
-
const value =
|
|
305
|
+
const value =
|
|
306
|
+
entityToDelete[attributeName] ||
|
|
307
|
+
(await strapi.query(uid).load(entityToDelete, attributeName));
|
|
296
308
|
|
|
297
309
|
if (!value) {
|
|
298
310
|
continue;
|
|
299
311
|
}
|
|
300
312
|
|
|
301
313
|
if (Array.isArray(value)) {
|
|
302
|
-
await Promise.all(value.map(subValue => deleteComponent(subValue.__component, subValue)));
|
|
314
|
+
await Promise.all(value.map((subValue) => deleteComponent(subValue.__component, subValue)));
|
|
303
315
|
}
|
|
304
316
|
|
|
305
317
|
continue;
|
|
@@ -307,9 +319,9 @@ const deleteComponents = async (uid, entityToDelete) => {
|
|
|
307
319
|
}
|
|
308
320
|
};
|
|
309
321
|
|
|
310
|
-
|
|
322
|
+
/** *************************
|
|
311
323
|
Component queries
|
|
312
|
-
|
|
324
|
+
************************** */
|
|
313
325
|
|
|
314
326
|
// components can have nested compos so this must be recursive
|
|
315
327
|
const createComponent = async (uid, data) => {
|
|
@@ -358,7 +370,9 @@ const deleteComponent = async (uid, componentToDelete) => {
|
|
|
358
370
|
|
|
359
371
|
module.exports = {
|
|
360
372
|
omitComponentData,
|
|
373
|
+
getComponents,
|
|
361
374
|
createComponents,
|
|
362
375
|
updateComponents,
|
|
363
376
|
deleteComponents,
|
|
377
|
+
deleteComponent,
|
|
364
378
|
};
|