@strapi/strapi 4.9.0-beta.2 → 4.9.0

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/.eslintignore ADDED
@@ -0,0 +1,2 @@
1
+ node_modules/
2
+ .eslintrc.js
package/.eslintrc.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ['custom/back'],
4
+ };
package/bin/strapi.js CHANGED
@@ -322,6 +322,11 @@ program
322
322
  }
323
323
  thisCommand.opts().fromToken = answers.fromToken;
324
324
  }
325
+
326
+ await confirmMessage(
327
+ 'The transfer will delete all the local Strapi assets and its database. Are you sure you want to proceed?',
328
+ { failMessage: 'Transfer process aborted' }
329
+ )(thisCommand);
325
330
  }
326
331
  )
327
332
  )
@@ -347,7 +352,7 @@ program
347
352
  }
348
353
 
349
354
  await confirmMessage(
350
- 'The transfer will delete all data in the remote database and media files. Are you sure you want to proceed?',
355
+ 'The transfer will delete all the remote Strapi assets and its database. Are you sure you want to proceed?',
351
356
  { failMessage: 'Transfer process aborted' }
352
357
  )(thisCommand);
353
358
  }
@@ -451,7 +456,7 @@ program
451
456
  .hook(
452
457
  'preAction',
453
458
  confirmMessage(
454
- 'The import will delete all data in your database and media files. Are you sure you want to proceed?',
459
+ 'The import will delete all assets and data in your database. Are you sure you want to proceed?',
455
460
  { failMessage: 'Import process aborted' }
456
461
  )
457
462
  )
package/ee/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { pick } = require('lodash/fp');
3
+ const { pick, isEqual } = require('lodash/fp');
4
4
 
5
5
  const { readLicense, verifyLicense, fetchLicense, LicenseCheckError } = require('./license');
6
6
  const { shiftCronExpression } = require('../lib/utils/cron');
@@ -13,10 +13,31 @@ const ee = {
13
13
  };
14
14
 
15
15
  const disable = (message) => {
16
+ // Prevent emitting ee.disable if it was already disabled
17
+ const shouldEmitEvent = ee.enabled !== false;
18
+
16
19
  ee.logger?.warn(`${message} Switching to CE.`);
17
20
  // Only keep the license key for potential re-enabling during a later check
18
21
  ee.licenseInfo = pick('licenseKey', ee.licenseInfo);
22
+
19
23
  ee.enabled = false;
24
+
25
+ if (shouldEmitEvent) {
26
+ // Notify EE features that they should be disabled
27
+ strapi.eventHub.emit('ee.disable');
28
+ }
29
+ };
30
+
31
+ const enable = () => {
32
+ // Prevent emitting ee.enable if it was already enabled
33
+ const shouldEmitEvent = ee.enabled !== true;
34
+
35
+ ee.enabled = true;
36
+
37
+ if (shouldEmitEvent) {
38
+ // Notify EE features that they should be disabled
39
+ strapi.eventHub.emit('ee.enable');
40
+ }
20
41
  };
21
42
 
22
43
  let initialized = false;
@@ -41,7 +62,7 @@ const init = (licenseDir, logger) => {
41
62
 
42
63
  if (license) {
43
64
  ee.licenseInfo = verifyLicense(license);
44
- ee.enabled = true;
65
+ enable();
45
66
  }
46
67
  } catch (error) {
47
68
  disable(error.message);
@@ -89,8 +110,22 @@ const onlineUpdate = async ({ strapi }) => {
89
110
 
90
111
  if (license) {
91
112
  try {
92
- ee.licenseInfo = verifyLicense(license);
113
+ // Verify license and check if its info changed
114
+ const newLicenseInfo = verifyLicense(license);
115
+ const licenseInfoChanged =
116
+ !isEqual(newLicenseInfo.features, ee.licenseInfo.features) ||
117
+ newLicenseInfo.seats !== ee.licenseInfo.seats ||
118
+ newLicenseInfo.type !== ee.licenseInfo.type;
119
+
120
+ // Store the new license info
121
+ ee.licenseInfo = newLicenseInfo;
122
+ const wasEnabled = ee.enabled;
93
123
  validateInfo();
124
+
125
+ // Notify EE features
126
+ if (licenseInfoChanged && wasEnabled) {
127
+ strapi.eventHub.emit('ee.update');
128
+ }
94
129
  } catch (error) {
95
130
  disable(error.message);
96
131
  }
@@ -125,7 +160,7 @@ const validateInfo = () => {
125
160
  return disable('License expired.');
126
161
  }
127
162
 
128
- ee.enabled = true;
163
+ enable();
129
164
  };
130
165
 
131
166
  const checkLicense = async ({ strapi }) => {
package/ee/license.js CHANGED
@@ -10,7 +10,9 @@ const machineId = require('../lib/utils/machine-id');
10
10
  const DEFAULT_FEATURES = {
11
11
  bronze: [],
12
12
  silver: [],
13
- gold: ['sso', { name: 'audit-logs', options: { retentionDays: 90 } }],
13
+ // Set a null retention duration to allow the user to override it
14
+ // The default of 90 days is set in the audit logs service
15
+ gold: ['sso', { name: 'audit-logs', options: { retentionDays: null } }],
14
16
  };
15
17
 
16
18
  const publicKey = fs.readFileSync(join(__dirname, 'resources/key.pub'));
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { join } = require('path');
4
4
  const fse = require('fs-extra');
5
- const { defaultsDeep, getOr, get } = require('lodash/fp');
5
+ const { defaultsDeep, defaults, getOr, get } = require('lodash/fp');
6
6
  const { env } = require('@strapi/utils');
7
7
  const loadConfigFile = require('../../app-configuration/load-config-file');
8
8
  const loadFiles = require('../../../load/load-files');
@@ -101,7 +101,12 @@ const loadPlugins = async (strapi) => {
101
101
  }
102
102
 
103
103
  const pluginServer = loadConfigFile(serverEntrypointPath);
104
- plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
104
+ plugins[pluginName] = {
105
+ ...defaultPlugin,
106
+ ...pluginServer,
107
+ config: defaults(defaultPlugin.config, pluginServer.config),
108
+ routes: pluginServer.routes ?? defaultPlugin.routes,
109
+ };
105
110
  }
106
111
 
107
112
  // TODO: validate plugin format
@@ -22,7 +22,6 @@ const createCollectionTypeController = ({ contentType }) => {
22
22
  const sanitizedQuery = await this.sanitizeQuery(ctx);
23
23
  const { results, pagination } = await strapi.service(uid).find(sanitizedQuery);
24
24
  const sanitizedResults = await this.sanitizeOutput(results, ctx);
25
-
26
25
  return this.transformResponse(sanitizedResults, { pagination });
27
26
  },
28
27
 
@@ -18,7 +18,7 @@ const createController = ({ contentType }) => {
18
18
  return transformResponse(data, meta, { contentType });
19
19
  },
20
20
 
21
- sanitizeOutput(data, ctx) {
21
+ async sanitizeOutput(data, ctx) {
22
22
  const auth = getAuthFromKoaContext(ctx);
23
23
 
24
24
  return sanitize.contentAPI.output(data, contentType, { auth });
package/lib/factories.js CHANGED
@@ -45,13 +45,12 @@ const createCoreService = (uid, cfg = {}) => {
45
45
  };
46
46
 
47
47
  const createCoreRouter = (uid, cfg = {}) => {
48
- const { prefix, config = {}, only, except } = cfg;
48
+ const { prefix, config = {}, only, except, type } = cfg;
49
49
  let routes;
50
50
 
51
51
  return {
52
- get prefix() {
53
- return prefix;
54
- },
52
+ type,
53
+ prefix,
55
54
  get routes() {
56
55
  if (!routes) {
57
56
  const contentType = strapi.contentType(uid);
@@ -1,21 +1,5 @@
1
1
  'use strict';
2
2
 
3
- /* eslint-disable no-nested-ternary */
4
-
5
- const chalk = require('chalk');
6
-
7
- const codeToColor = (code) => {
8
- return code >= 500
9
- ? chalk.red(code)
10
- : code >= 400
11
- ? chalk.yellow(code)
12
- : code >= 300
13
- ? chalk.cyan(code)
14
- : code >= 200
15
- ? chalk.green(code)
16
- : code;
17
- };
18
-
19
3
  /**
20
4
  * @type {import('./').MiddlewareFactory}
21
5
  */
@@ -25,6 +9,6 @@ module.exports = (_, { strapi }) => {
25
9
  await next();
26
10
  const delta = Math.ceil(Date.now() - start);
27
11
 
28
- strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${codeToColor(ctx.status)}`);
12
+ strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${ctx.status}`);
29
13
  };
30
14
  };
@@ -1,8 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const createError = require('http-errors');
4
- const { NotFoundError, UnauthorizedError, ForbiddenError, PayloadTooLargeError, RateLimitError } =
5
- require('@strapi/utils').errors;
4
+ const {
5
+ NotFoundError,
6
+ UnauthorizedError,
7
+ ForbiddenError,
8
+ PayloadTooLargeError,
9
+ RateLimitError,
10
+ NotImplementedError,
11
+ } = require('@strapi/utils').errors;
6
12
 
7
13
  const mapErrorsAndStatus = [
8
14
  {
@@ -25,6 +31,10 @@ const mapErrorsAndStatus = [
25
31
  classError: RateLimitError,
26
32
  status: 429,
27
33
  },
34
+ {
35
+ classError: NotImplementedError,
36
+ status: 501,
37
+ },
28
38
  ];
29
39
 
30
40
  const formatApplicationError = (error) => {
@@ -35,7 +35,12 @@ module.exports = function createEventHub() {
35
35
  },
36
36
 
37
37
  unsubscribe(subscriber) {
38
- subscribers.splice(subscribers.indexOf(subscriber), 1);
38
+ const subscriberIndex = subscribers.indexOf(subscriber);
39
+
40
+ // Only remove the subscriber if it exists
41
+ if (subscriberIndex >= 0) {
42
+ subscribers.splice(subscriberIndex, 1);
43
+ }
39
44
  },
40
45
 
41
46
  on(eventName, listener) {
@@ -17,6 +17,7 @@ const LIMITED_EVENTS = [
17
17
  'didSaveMediaWithCaption',
18
18
  'didDisableResponsiveDimensions',
19
19
  'didEnableResponsiveDimensions',
20
+ 'didInitializePluginUpload',
20
21
  ];
21
22
 
22
23
  const createTelemetryInstance = (strapi) => {
@@ -69,7 +69,7 @@ const registerPluginRoutes = (strapi) => {
69
69
  } else {
70
70
  _.forEach(plugin.routes, (router) => {
71
71
  router.type = router.type || 'admin';
72
- router.prefix = `/${pluginName}`;
72
+ router.prefix = router.prefix || `/${pluginName}`;
73
73
  router.routes.forEach((route) => {
74
74
  generateRouteScope(route);
75
75
  route.info = { pluginName };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.9.0-beta.2",
3
+ "version": "4.9.0",
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",
@@ -66,9 +66,7 @@
66
66
  ],
67
67
  "main": "./lib",
68
68
  "types": "./lib/index.d.ts",
69
- "bin": {
70
- "strapi": "./bin/strapi.js"
71
- },
69
+ "bin": "./bin/strapi.js",
72
70
  "directories": {
73
71
  "lib": "./lib",
74
72
  "bin": "./bin",
@@ -76,24 +74,26 @@
76
74
  },
77
75
  "scripts": {
78
76
  "postinstall": "node lib/utils/success.js",
79
- "test:unit": "jest --verbose"
77
+ "test:unit": "jest",
78
+ "test:unit:watch": "jest --watch",
79
+ "lint": "eslint ."
80
80
  },
81
81
  "dependencies": {
82
82
  "@koa/cors": "3.4.3",
83
83
  "@koa/router": "10.1.1",
84
- "@strapi/admin": "4.9.0-beta.2",
85
- "@strapi/data-transfer": "4.9.0-beta.2",
86
- "@strapi/database": "4.9.0-beta.2",
87
- "@strapi/generate-new": "4.9.0-beta.2",
88
- "@strapi/generators": "4.9.0-beta.2",
89
- "@strapi/logger": "4.9.0-beta.2",
90
- "@strapi/permissions": "4.9.0-beta.2",
91
- "@strapi/plugin-content-manager": "4.9.0-beta.2",
92
- "@strapi/plugin-content-type-builder": "4.9.0-beta.2",
93
- "@strapi/plugin-email": "4.9.0-beta.2",
94
- "@strapi/plugin-upload": "4.9.0-beta.2",
95
- "@strapi/typescript-utils": "4.9.0-beta.2",
96
- "@strapi/utils": "4.9.0-beta.2",
84
+ "@strapi/admin": "4.9.0",
85
+ "@strapi/data-transfer": "4.9.0",
86
+ "@strapi/database": "4.9.0",
87
+ "@strapi/generate-new": "4.9.0",
88
+ "@strapi/generators": "4.9.0",
89
+ "@strapi/logger": "4.9.0",
90
+ "@strapi/permissions": "4.9.0",
91
+ "@strapi/plugin-content-manager": "4.9.0",
92
+ "@strapi/plugin-content-type-builder": "4.9.0",
93
+ "@strapi/plugin-email": "4.9.0",
94
+ "@strapi/plugin-upload": "4.9.0",
95
+ "@strapi/typescript-utils": "4.9.0",
96
+ "@strapi/utils": "4.9.0",
97
97
  "bcryptjs": "2.4.3",
98
98
  "boxen": "5.1.2",
99
99
  "chalk": "4.1.2",
@@ -128,7 +128,7 @@
128
128
  "open": "8.4.0",
129
129
  "ora": "5.4.1",
130
130
  "package-json": "7.0.0",
131
- "qs": "6.11.0",
131
+ "qs": "6.11.1",
132
132
  "resolve-cwd": "3.0.0",
133
133
  "semver": "7.3.8",
134
134
  "statuses": "2.0.1",
@@ -142,5 +142,5 @@
142
142
  "node": ">=14.19.1 <=18.x.x",
143
143
  "npm": ">=6.0.0"
144
144
  },
145
- "gitHead": "d893ead642592a15a95fefb71c544aaabe4db20b"
145
+ "gitHead": "ffe3f4621ccc968ce56fda9a8317ec30d4bad205"
146
146
  }