@strapi/strapi 4.6.0 → 4.6.2
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/bin/strapi.js +7 -0
- package/lib/core/registries/hooks.d.ts +1 -4
- package/lib/core/registries/policies.d.ts +5 -1
- package/lib/global.d.ts +12 -7
- package/lib/index.d.ts +1 -1
- package/lib/middlewares/cors.js +8 -0
- package/lib/middlewares/public/index.js +2 -1
- package/lib/services/entity-service/components.js +50 -33
- package/lib/services/entity-service/index.d.ts +1 -1
- package/lib/services/metrics/sender.js +12 -0
- package/lib/types/core/attributes/common.d.ts +4 -1
- package/lib/types/core/attributes/component.d.ts +4 -7
- package/lib/types/core/attributes/utils.d.ts +4 -5
- package/lib/types/core/index.d.ts +2 -2
- package/lib/types/index.d.ts +2 -2
- package/package.json +19 -19
package/bin/strapi.js
CHANGED
|
@@ -409,6 +409,13 @@ program
|
|
|
409
409
|
} else {
|
|
410
410
|
thisCommand.opts().decompress = false;
|
|
411
411
|
}
|
|
412
|
+
|
|
413
|
+
if (extname(file) !== '.tar') {
|
|
414
|
+
exitWith(
|
|
415
|
+
1,
|
|
416
|
+
`The file '${opts.file}' does not appear to be a valid Strapi data file. It must have an extension ending in .tar[.gz][.enc]`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
412
419
|
})
|
|
413
420
|
.hook(
|
|
414
421
|
'preAction',
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
type Handler = (context: any) => any;
|
|
3
2
|
|
|
4
3
|
type AsyncHook = {
|
|
@@ -8,7 +7,6 @@ type AsyncHook = {
|
|
|
8
7
|
call(): Promise<void>;
|
|
9
8
|
};
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
type SyncHook = {
|
|
13
11
|
get handlers(): Handler[];
|
|
14
12
|
register(handler: Handler): this;
|
|
@@ -16,5 +14,4 @@ type SyncHook = {
|
|
|
16
14
|
call(): void;
|
|
17
15
|
};
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
export type Hook = AsyncHook|SyncHook
|
|
17
|
+
export type Hook = AsyncHook | SyncHook;
|
|
@@ -6,4 +6,8 @@ interface PolicyContext extends BaseContext {
|
|
|
6
6
|
is(name): boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export type Policy<T=unknown> = (
|
|
9
|
+
export type Policy<T = unknown> = (
|
|
10
|
+
ctx: PolicyContext,
|
|
11
|
+
cfg: T,
|
|
12
|
+
{ strapi: Strapi }
|
|
13
|
+
) => boolean | undefined;
|
package/lib/global.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Strapi as StrapiInterface } from './types/core';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
CollectionTypeSchema,
|
|
4
|
+
SingleTypeSchema,
|
|
5
|
+
ComponentSchema,
|
|
6
|
+
ContentTypeSchema,
|
|
7
|
+
} from './types/core/schemas';
|
|
3
8
|
import type { KeysBy } from './types/utils';
|
|
4
9
|
|
|
5
10
|
declare global {
|
|
@@ -7,7 +12,7 @@ declare global {
|
|
|
7
12
|
/**
|
|
8
13
|
* Map of UID / schemas used as a schemas database for other types.
|
|
9
14
|
* It must be extended by the user application or plugins.
|
|
10
|
-
*
|
|
15
|
+
*
|
|
11
16
|
* @example
|
|
12
17
|
* ```ts
|
|
13
18
|
* declare global {
|
|
@@ -39,12 +44,12 @@ declare global {
|
|
|
39
44
|
/**
|
|
40
45
|
* Literal union type of every component registered in Strapi.Schemas
|
|
41
46
|
*/
|
|
42
|
-
|
|
47
|
+
type ComponentUIDs = KeysBy<Schemas, ComponentSchema>;
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Global shorthand to access the `StrapiInterface` type
|
|
51
|
+
*/
|
|
52
|
+
type Strapi = StrapiInterface;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
/**
|
package/lib/index.d.ts
CHANGED
package/lib/middlewares/cors.js
CHANGED
|
@@ -19,6 +19,14 @@ module.exports = (config) => {
|
|
|
19
19
|
const { origin, expose, maxAge, credentials, methods, headers, keepHeadersOnError } =
|
|
20
20
|
defaultsDeep(defaults, config);
|
|
21
21
|
|
|
22
|
+
if (config.enabled !== undefined) {
|
|
23
|
+
strapi.log.warn(
|
|
24
|
+
'The strapi::cors middleware no longer supports the `enabled` option. Using it' +
|
|
25
|
+
' to conditionally enable CORS might cause an insecure default. To disable strapi::cors, remove it from' +
|
|
26
|
+
' the exported array in config/middleware.js'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
return cors({
|
|
23
31
|
async origin(ctx) {
|
|
24
32
|
let originList;
|
|
@@ -77,9 +77,10 @@ module.exports = (config, { strapi }) => {
|
|
|
77
77
|
}),
|
|
78
78
|
config: { auth: false },
|
|
79
79
|
},
|
|
80
|
+
// All other public GET-routes except /uploads/(.*) which is handled in upload middleware
|
|
80
81
|
{
|
|
81
82
|
method: 'GET',
|
|
82
|
-
path: '/(
|
|
83
|
+
path: '/((?!uploads/).+)',
|
|
83
84
|
handler: koaStatic(strapi.dirs.static.public, {
|
|
84
85
|
maxage: maxAge,
|
|
85
86
|
defer: true,
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
const _ = require('lodash');
|
|
4
4
|
const { has, prop, omit, toString, pipe, assign } = require('lodash/fp');
|
|
5
5
|
|
|
6
|
-
const { contentTypes: contentTypesUtils } = require('@strapi/utils');
|
|
6
|
+
const { contentTypes: contentTypesUtils, mapAsync } = require('@strapi/utils');
|
|
7
7
|
const { ApplicationError } = require('@strapi/utils').errors;
|
|
8
8
|
const { getComponentAttributes } = require('@strapi/utils').contentTypes;
|
|
9
9
|
|
|
10
|
+
const isDialectMySQL = () => strapi.db.dialect.client === 'mysql';
|
|
11
|
+
|
|
10
12
|
const omitComponentData = (contentType, data) => {
|
|
11
13
|
const { attributes } = contentType;
|
|
12
14
|
const componentAttributes = Object.keys(attributes).filter((attributeName) =>
|
|
@@ -43,10 +45,12 @@ const createComponents = async (uid, data) => {
|
|
|
43
45
|
throw new Error('Expected an array to create repeatable component');
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
|
49
|
+
const components = await mapAsync(
|
|
50
|
+
componentValue,
|
|
51
|
+
(value) => createComponent(componentUID, value),
|
|
52
|
+
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
|
53
|
+
);
|
|
50
54
|
|
|
51
55
|
componentBody[attributeName] = components.map(({ id }) => {
|
|
52
56
|
return {
|
|
@@ -78,19 +82,23 @@ const createComponents = async (uid, data) => {
|
|
|
78
82
|
throw new Error('Expected an array to create repeatable component');
|
|
79
83
|
}
|
|
80
84
|
|
|
81
|
-
const
|
|
82
|
-
for (const value of dynamiczoneValues) {
|
|
85
|
+
const createDynamicZoneComponents = async (value) => {
|
|
83
86
|
const { id } = await createComponent(value.__component, value);
|
|
84
|
-
|
|
87
|
+
return {
|
|
85
88
|
id,
|
|
86
89
|
__component: value.__component,
|
|
87
90
|
__pivot: {
|
|
88
91
|
field: attributeName,
|
|
89
92
|
},
|
|
90
|
-
}
|
|
91
|
-
}
|
|
93
|
+
};
|
|
94
|
+
};
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
|
97
|
+
componentBody[attributeName] = await mapAsync(
|
|
98
|
+
dynamiczoneValues,
|
|
99
|
+
createDynamicZoneComponents,
|
|
100
|
+
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
|
101
|
+
);
|
|
94
102
|
|
|
95
103
|
continue;
|
|
96
104
|
}
|
|
@@ -139,10 +147,12 @@ const updateComponents = async (uid, entityToUpdate, data) => {
|
|
|
139
147
|
throw new Error('Expected an array to create repeatable component');
|
|
140
148
|
}
|
|
141
149
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
|
151
|
+
const components = await mapAsync(
|
|
152
|
+
componentValue,
|
|
153
|
+
(value) => updateOrCreateComponent(componentUID, value),
|
|
154
|
+
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
|
155
|
+
);
|
|
146
156
|
|
|
147
157
|
componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }) => {
|
|
148
158
|
return {
|
|
@@ -176,19 +186,22 @@ const updateComponents = async (uid, entityToUpdate, data) => {
|
|
|
176
186
|
throw new Error('Expected an array to create repeatable component');
|
|
177
187
|
}
|
|
178
188
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
id,
|
|
184
|
-
__component: value.__component,
|
|
185
|
-
__pivot: {
|
|
186
|
-
field: attributeName,
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
}
|
|
189
|
+
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
|
190
|
+
componentBody[attributeName] = await mapAsync(
|
|
191
|
+
dynamiczoneValues,
|
|
192
|
+
async (value) => {
|
|
193
|
+
const { id } = await updateOrCreateComponent(value.__component, value);
|
|
190
194
|
|
|
191
|
-
|
|
195
|
+
return {
|
|
196
|
+
id,
|
|
197
|
+
__component: value.__component,
|
|
198
|
+
__pivot: {
|
|
199
|
+
field: attributeName,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
|
204
|
+
);
|
|
192
205
|
|
|
193
206
|
continue;
|
|
194
207
|
}
|
|
@@ -290,14 +303,18 @@ const deleteComponents = async (uid, entityToDelete, { loadComponents = true } =
|
|
|
290
303
|
|
|
291
304
|
if (attribute.type === 'component') {
|
|
292
305
|
const { component: componentUID } = attribute;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
306
|
+
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
|
307
|
+
await mapAsync(_.castArray(value), (subValue) => deleteComponent(componentUID, subValue), {
|
|
308
|
+
concurrency: isDialectMySQL() ? 1 : Infinity,
|
|
309
|
+
});
|
|
296
310
|
} else {
|
|
297
311
|
// delete dynamic zone components
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
312
|
+
// MySQL/MariaDB can cause deadlocks here if concurrency higher than 1
|
|
313
|
+
await mapAsync(
|
|
314
|
+
_.castArray(value),
|
|
315
|
+
(subValue) => deleteComponent(subValue.__component, subValue),
|
|
316
|
+
{ concurrency: isDialectMySQL() ? 1 : Infinity }
|
|
317
|
+
);
|
|
301
318
|
}
|
|
302
319
|
|
|
303
320
|
continue;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const _ = require('lodash');
|
|
6
|
+
const { map, values, sumBy, pipe, flatMap, propEq } = require('lodash/fp');
|
|
6
7
|
const isDocker = require('is-docker');
|
|
7
8
|
const fetch = require('node-fetch');
|
|
8
9
|
const ciEnv = require('ci-info');
|
|
@@ -40,6 +41,14 @@ module.exports = (strapi) => {
|
|
|
40
41
|
const serverRootPath = strapi.dirs.app.root;
|
|
41
42
|
const adminRootPath = path.join(strapi.dirs.app.root, 'src', 'admin');
|
|
42
43
|
|
|
44
|
+
const getNumberOfDynamicZones = () => {
|
|
45
|
+
return pipe(
|
|
46
|
+
map('attributes'),
|
|
47
|
+
flatMap(values),
|
|
48
|
+
sumBy(propEq('type', 'dynamiczone'))
|
|
49
|
+
)(strapi.contentTypes);
|
|
50
|
+
};
|
|
51
|
+
|
|
43
52
|
const anonymousUserProperties = {
|
|
44
53
|
environment: strapi.config.environment,
|
|
45
54
|
os: os.type(),
|
|
@@ -57,6 +66,9 @@ module.exports = (strapi) => {
|
|
|
57
66
|
useTypescriptOnAdmin: isUsingTypeScriptSync(adminRootPath),
|
|
58
67
|
projectId: uuid,
|
|
59
68
|
isHostedOnStrapiCloud: env('STRAPI_HOSTING', null) === 'strapi.cloud',
|
|
69
|
+
numberOfAllContentTypes: _.size(strapi.contentTypes), // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.
|
|
70
|
+
numberOfComponents: _.size(strapi.components),
|
|
71
|
+
numberOfDynamicZones: getNumberOfDynamicZones(),
|
|
60
72
|
};
|
|
61
73
|
|
|
62
74
|
addPackageJsonStrapiMetadata(anonymousGroupProperties, strapi);
|
|
@@ -30,7 +30,10 @@ export type ConfigurableAttribute = { configurable: true };
|
|
|
30
30
|
export type NonConfigurableAttribute = { configurable: false };
|
|
31
31
|
|
|
32
32
|
// custom field
|
|
33
|
-
export type CustomField<T extends string, P extends object = undefined> = {
|
|
33
|
+
export type CustomField<T extends string, P extends object = undefined> = {
|
|
34
|
+
customField: T;
|
|
35
|
+
options?: P;
|
|
36
|
+
};
|
|
34
37
|
|
|
35
38
|
// min/max
|
|
36
39
|
export type SetMinMax<T extends MinMaxOption<U>, U = number> = T;
|
|
@@ -25,13 +25,10 @@ export type ComponentAttribute<
|
|
|
25
25
|
PrivateOption &
|
|
26
26
|
RequiredOption;
|
|
27
27
|
|
|
28
|
-
export type ComponentValue<
|
|
29
|
-
T
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
? V[]
|
|
33
|
-
: V
|
|
34
|
-
: never;
|
|
28
|
+
export type ComponentValue<
|
|
29
|
+
T extends Strapi.ComponentUIDs,
|
|
30
|
+
R extends boolean
|
|
31
|
+
> = GetAttributesValues<T> extends infer V ? (R extends true ? V[] : V) : never;
|
|
35
32
|
|
|
36
33
|
export type GetComponentAttributeValue<T extends Attribute> = T extends ComponentAttribute<
|
|
37
34
|
infer U,
|
|
@@ -83,11 +83,10 @@ export type GetAttributeValueByKey<
|
|
|
83
83
|
export type GetAttributesValues<T extends SchemaUID> = {
|
|
84
84
|
// Handle required attributes
|
|
85
85
|
[key in GetAttributesRequiredKeys<T>]-?: GetAttributeValueByKey<T, key>;
|
|
86
|
-
} &
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
86
|
+
} & {
|
|
87
|
+
// Handle optional attributes
|
|
88
|
+
[key in GetAttributesOptionalKeys<T>]?: GetAttributeValueByKey<T, key>;
|
|
89
|
+
};
|
|
91
90
|
|
|
92
91
|
export type GetAttributesRequiredKeys<T extends SchemaUID> = KeysBy<
|
|
93
92
|
GetAttributes<T>,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './attributes';
|
|
2
|
-
export * from
|
|
3
|
-
export * from './strapi'
|
|
2
|
+
export * from './schemas';
|
|
3
|
+
export * from './strapi';
|
package/lib/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/strapi",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.2",
|
|
4
4
|
"description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MySQL, MariaDB, PostgreSQL, SQLite",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -81,19 +81,19 @@
|
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"@koa/cors": "3.4.3",
|
|
83
83
|
"@koa/router": "10.1.1",
|
|
84
|
-
"@strapi/admin": "4.6.
|
|
85
|
-
"@strapi/data-transfer": "4.6.
|
|
86
|
-
"@strapi/database": "4.6.
|
|
87
|
-
"@strapi/generate-new": "4.6.
|
|
88
|
-
"@strapi/generators": "4.6.
|
|
89
|
-
"@strapi/logger": "4.6.
|
|
90
|
-
"@strapi/permissions": "4.6.
|
|
91
|
-
"@strapi/plugin-content-manager": "4.6.
|
|
92
|
-
"@strapi/plugin-content-type-builder": "4.6.
|
|
93
|
-
"@strapi/plugin-email": "4.6.
|
|
94
|
-
"@strapi/plugin-upload": "4.6.
|
|
95
|
-
"@strapi/typescript-utils": "4.6.
|
|
96
|
-
"@strapi/utils": "4.6.
|
|
84
|
+
"@strapi/admin": "4.6.2",
|
|
85
|
+
"@strapi/data-transfer": "4.6.2",
|
|
86
|
+
"@strapi/database": "4.6.2",
|
|
87
|
+
"@strapi/generate-new": "4.6.2",
|
|
88
|
+
"@strapi/generators": "4.6.2",
|
|
89
|
+
"@strapi/logger": "4.6.2",
|
|
90
|
+
"@strapi/permissions": "4.6.2",
|
|
91
|
+
"@strapi/plugin-content-manager": "4.6.2",
|
|
92
|
+
"@strapi/plugin-content-type-builder": "4.6.2",
|
|
93
|
+
"@strapi/plugin-email": "4.6.2",
|
|
94
|
+
"@strapi/plugin-upload": "4.6.2",
|
|
95
|
+
"@strapi/typescript-utils": "4.6.2",
|
|
96
|
+
"@strapi/utils": "4.6.2",
|
|
97
97
|
"bcryptjs": "2.4.3",
|
|
98
98
|
"boxen": "5.1.2",
|
|
99
99
|
"chalk": "4.1.2",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"fs-extra": "10.0.0",
|
|
110
110
|
"glob": "7.2.0",
|
|
111
111
|
"http-errors": "1.8.1",
|
|
112
|
-
"inquirer": "8.2.
|
|
112
|
+
"inquirer": "8.2.5",
|
|
113
113
|
"is-docker": "2.2.1",
|
|
114
114
|
"koa": "2.13.4",
|
|
115
115
|
"koa-body": "4.2.0",
|
|
@@ -118,11 +118,11 @@
|
|
|
118
118
|
"koa-favicon": "2.1.0",
|
|
119
119
|
"koa-helmet": "6.1.0",
|
|
120
120
|
"koa-ip": "^2.1.2",
|
|
121
|
-
"koa-session": "6.
|
|
121
|
+
"koa-session": "6.4.0",
|
|
122
122
|
"koa-static": "5.0.0",
|
|
123
123
|
"lodash": "4.17.21",
|
|
124
124
|
"mime-types": "2.1.35",
|
|
125
|
-
"node-fetch": "2.6.
|
|
125
|
+
"node-fetch": "2.6.9",
|
|
126
126
|
"node-machine-id": "1.1.12",
|
|
127
127
|
"node-schedule": "2.1.0",
|
|
128
128
|
"open": "8.4.0",
|
|
@@ -135,12 +135,12 @@
|
|
|
135
135
|
"uuid": "^8.3.2"
|
|
136
136
|
},
|
|
137
137
|
"devDependencies": {
|
|
138
|
-
"supertest": "6.
|
|
138
|
+
"supertest": "6.3.3",
|
|
139
139
|
"typescript": "4.6.2"
|
|
140
140
|
},
|
|
141
141
|
"engines": {
|
|
142
142
|
"node": ">=14.19.1 <=18.x.x",
|
|
143
143
|
"npm": ">=6.0.0"
|
|
144
144
|
},
|
|
145
|
-
"gitHead": "
|
|
145
|
+
"gitHead": "bae505f44c3a779905f6b8dbc0c497e24d9eabfb"
|
|
146
146
|
}
|