@strapi/strapi 4.6.0-beta.2 → 4.6.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.
@@ -15,6 +15,7 @@ const {
15
15
  buildTransferTable,
16
16
  createStrapiInstance,
17
17
  DEFAULT_IGNORED_CONTENT_TYPES,
18
+ formatDiagnostic,
18
19
  } = require('./utils');
19
20
 
20
21
  const logger = console;
@@ -109,6 +110,8 @@ module.exports = async (opts) => {
109
110
  },
110
111
  });
111
112
 
113
+ engine.diagnostics.onDiagnostic(formatDiagnostic('transfer'));
114
+
112
115
  try {
113
116
  logger.log(`Starting transfer...`);
114
117
 
@@ -120,8 +123,7 @@ module.exports = async (opts) => {
120
123
  logger.log(`${chalk.bold('Transfer process has been completed successfully!')}`);
121
124
  process.exit(0);
122
125
  } catch (e) {
123
- logger.error('Transfer process failed unexpectedly');
124
- logger.error(e);
126
+ logger.error('Transfer process failed.');
125
127
  process.exit(1);
126
128
  }
127
129
  };
@@ -4,6 +4,11 @@ const chalk = require('chalk');
4
4
  const Table = require('cli-table3');
5
5
  const { Option } = require('commander');
6
6
  const { TransferGroupPresets } = require('@strapi/data-transfer/lib/engine');
7
+
8
+ const {
9
+ configs: { createOutputFileConfiguration },
10
+ createLogger,
11
+ } = require('@strapi/logger');
7
12
  const { readableBytes, exitWith } = require('../utils/helpers');
8
13
  const strapi = require('../../index');
9
14
  const { getParseListWithChoices } = require('../utils/commander');
@@ -77,29 +82,34 @@ const DEFAULT_IGNORED_CONTENT_TYPES = [
77
82
  'admin::role',
78
83
  'admin::api-token',
79
84
  'admin::api-token-permission',
85
+ 'admin::audit-log',
80
86
  ];
81
87
 
82
88
  const createStrapiInstance = async (logLevel = 'error') => {
83
- const appContext = await strapi.compile();
84
- const app = strapi(appContext);
85
-
86
- app.log.level = logLevel;
87
-
88
- return app.load();
89
+ try {
90
+ const appContext = await strapi.compile();
91
+ const app = strapi(appContext);
92
+
93
+ app.log.level = logLevel;
94
+ return await app.load();
95
+ } catch (err) {
96
+ if (err.code === 'ECONNREFUSED') {
97
+ throw new Error('Process failed. Check the database connection with your Strapi project.');
98
+ }
99
+ throw err;
100
+ }
89
101
  };
90
102
 
91
103
  const transferDataTypes = Object.keys(TransferGroupPresets);
92
104
 
93
105
  const excludeOption = new Option(
94
106
  '--exclude <comma-separated data types>',
95
- `Exclude this data. Options used here override --only. Available types: ${transferDataTypes.join(
96
- ','
97
- )}`
107
+ `Exclude data using comma-separated types. Available types: ${transferDataTypes.join(',')}`
98
108
  ).argParser(getParseListWithChoices(transferDataTypes, 'Invalid options for "exclude"'));
99
109
 
100
110
  const onlyOption = new Option(
101
111
  '--only <command-separated data types>',
102
- `Include only this data (plus schemas). Available types: ${transferDataTypes.join(',')}`
112
+ `Include only these types of data (plus schemas). Available types: ${transferDataTypes.join(',')}`
103
113
  ).argParser(getParseListWithChoices(transferDataTypes, 'Invalid options for "only"'));
104
114
 
105
115
  const validateExcludeOnly = (command) => {
@@ -121,6 +131,44 @@ const validateExcludeOnly = (command) => {
121
131
  }
122
132
  };
123
133
 
134
+ const errorColors = {
135
+ fatal: chalk.red,
136
+ error: chalk.red,
137
+ silly: chalk.yellow,
138
+ };
139
+
140
+ const formatDiagnostic =
141
+ (operation) =>
142
+ ({ details, kind }) => {
143
+ const logger = createLogger(
144
+ createOutputFileConfiguration(`${operation}_error_log_${Date.now()}.log`)
145
+ );
146
+ try {
147
+ if (kind === 'error') {
148
+ const { message, severity = 'fatal' } = details;
149
+
150
+ const colorizeError = errorColors[severity];
151
+ const errorMessage = colorizeError(`[${severity.toUpperCase()}] ${message}`);
152
+
153
+ logger.error(errorMessage);
154
+ }
155
+ if (kind === 'info') {
156
+ const { message, params } = details;
157
+
158
+ const msg = `${message}\n${params ? JSON.stringify(params, null, 2) : ''}`;
159
+
160
+ logger.info(msg);
161
+ }
162
+ if (kind === 'warning') {
163
+ const { origin, message } = details;
164
+
165
+ logger.warn(`(${origin ?? 'transfer'}) ${message}`);
166
+ }
167
+ } catch (err) {
168
+ logger.error(err);
169
+ }
170
+ };
171
+
124
172
  module.exports = {
125
173
  buildTransferTable,
126
174
  getDefaultExportName,
@@ -129,4 +177,5 @@ module.exports = {
129
177
  excludeOption,
130
178
  onlyOption,
131
179
  validateExcludeOnly,
180
+ formatDiagnostic,
132
181
  };
@@ -122,7 +122,7 @@ const confirmMessage = (message) => {
122
122
  };
123
123
 
124
124
  const forceOption = new Option(
125
- '-f, --force',
125
+ '--force',
126
126
  `Automatically answer "yes" to all prompts, including potentially destructive requests, and run non-interactively.`
127
127
  );
128
128
 
@@ -85,7 +85,15 @@ const loadPlugins = async (strapi) => {
85
85
  for (const pluginName of Object.keys(enabledPlugins)) {
86
86
  const enabledPlugin = enabledPlugins[pluginName];
87
87
 
88
- const serverEntrypointPath = join(enabledPlugin.pathToPlugin, 'strapi-server.js');
88
+ let serverEntrypointPath;
89
+
90
+ try {
91
+ serverEntrypointPath = join(enabledPlugin.pathToPlugin, 'strapi-server.js');
92
+ } catch (e) {
93
+ throw new Error(
94
+ `Error loading the plugin ${pluginName} because ${pluginName} is not installed. Please either install the plugin or remove it's configuration.`
95
+ );
96
+ }
89
97
 
90
98
  // only load plugins with a server entrypoint
91
99
  if (!(await fse.pathExists(serverEntrypointPath))) {
@@ -43,9 +43,10 @@ const createComponents = async (uid, data) => {
43
43
  throw new Error('Expected an array to create repeatable component');
44
44
  }
45
45
 
46
- const components = await Promise.all(
47
- componentValue.map((value) => createComponent(componentUID, value))
48
- );
46
+ const components = [];
47
+ for (const value of componentValue) {
48
+ components.push(await createComponent(componentUID, value));
49
+ }
49
50
 
50
51
  componentBody[attributeName] = components.map(({ id }) => {
51
52
  return {
@@ -77,18 +78,19 @@ const createComponents = async (uid, data) => {
77
78
  throw new Error('Expected an array to create repeatable component');
78
79
  }
79
80
 
80
- componentBody[attributeName] = await Promise.all(
81
- dynamiczoneValues.map(async (value) => {
82
- const { id } = await createComponent(value.__component, value);
83
- return {
84
- id,
85
- __component: value.__component,
86
- __pivot: {
87
- field: attributeName,
88
- },
89
- };
90
- })
91
- );
81
+ const dynamicZoneData = [];
82
+ for (const value of dynamiczoneValues) {
83
+ const { id } = await createComponent(value.__component, value);
84
+ dynamicZoneData.push({
85
+ id,
86
+ __component: value.__component,
87
+ __pivot: {
88
+ field: attributeName,
89
+ },
90
+ });
91
+ }
92
+
93
+ componentBody[attributeName] = dynamicZoneData;
92
94
 
93
95
  continue;
94
96
  }
@@ -137,9 +139,10 @@ const updateComponents = async (uid, entityToUpdate, data) => {
137
139
  throw new Error('Expected an array to create repeatable component');
138
140
  }
139
141
 
140
- const components = await Promise.all(
141
- componentValue.map((value) => updateOrCreateComponent(componentUID, value))
142
- );
142
+ const components = [];
143
+ for (const value of componentValue) {
144
+ components.push(await updateOrCreateComponent(componentUID, value));
145
+ }
143
146
 
144
147
  componentBody[attributeName] = components.filter(_.negate(_.isNil)).map(({ id }) => {
145
148
  return {
@@ -173,19 +176,19 @@ const updateComponents = async (uid, entityToUpdate, data) => {
173
176
  throw new Error('Expected an array to create repeatable component');
174
177
  }
175
178
 
176
- componentBody[attributeName] = await Promise.all(
177
- dynamiczoneValues.map(async (value) => {
178
- const { id } = await updateOrCreateComponent(value.__component, value);
179
+ const dynamicZoneData = [];
180
+ for (const value of dynamiczoneValues) {
181
+ const { id } = await updateOrCreateComponent(value.__component, value);
182
+ dynamicZoneData.push({
183
+ id,
184
+ __component: value.__component,
185
+ __pivot: {
186
+ field: attributeName,
187
+ },
188
+ });
189
+ }
179
190
 
180
- return {
181
- id,
182
- __component: value.__component,
183
- __pivot: {
184
- field: attributeName,
185
- },
186
- };
187
- })
188
- );
191
+ componentBody[attributeName] = dynamicZoneData;
189
192
 
190
193
  continue;
191
194
  }
@@ -287,14 +290,14 @@ const deleteComponents = async (uid, entityToDelete, { loadComponents = true } =
287
290
 
288
291
  if (attribute.type === 'component') {
289
292
  const { component: componentUID } = attribute;
290
- await Promise.all(
291
- _.castArray(value).map((subValue) => deleteComponent(componentUID, subValue))
292
- );
293
+ for (const subValue of _.castArray(value)) {
294
+ await deleteComponent(componentUID, subValue);
295
+ }
293
296
  } else {
294
297
  // delete dynamic zone components
295
- await Promise.all(
296
- _.castArray(value).map((subValue) => deleteComponent(subValue.__component, subValue))
297
- );
298
+ for (const subValue of _.castArray(value)) {
299
+ await deleteComponent(subValue.__component, subValue);
300
+ }
298
301
  }
299
302
 
300
303
  continue;
@@ -70,6 +70,7 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
70
70
 
71
71
  eventHub.emit(event, {
72
72
  model: model.modelName,
73
+ uid: model.uid,
73
74
  entry: sanitizedEntity,
74
75
  });
75
76
  },
@@ -5,12 +5,8 @@
5
5
  * You can learn more at https://docs.strapi.io/developer-docs/latest/getting-started/usage-information.html
6
6
  */
7
7
 
8
- const crypto = require('crypto');
9
- const fs = require('fs');
10
- const path = require('path');
11
8
  const { scheduleJob } = require('node-schedule');
12
9
 
13
- const ee = require('../../utils/ee');
14
10
  const wrapWithRateLimit = require('./rate-limiter');
15
11
  const createSender = require('./sender');
16
12
  const createMiddleware = require('./middleware');
@@ -46,41 +42,14 @@ const createTelemetryInstance = (strapi) => {
46
42
  strapi.server.use(createMiddleware({ sendEvent }));
47
43
  }
48
44
  },
49
- bootstrap() {
50
- if (strapi.EE === true && ee.isEE === true) {
51
- const pingDisabled =
52
- isTruthy(process.env.STRAPI_LICENSE_PING_DISABLED) && ee.licenseInfo.type === 'gold';
53
45
 
54
- const sendLicenseCheck = () => {
55
- return sendEvent(
56
- 'didCheckLicense',
57
- {
58
- groupProperties: {
59
- licenseInfo: {
60
- ...ee.licenseInfo,
61
- projectHash: hashProject(strapi),
62
- dependencyHash: hashDep(strapi),
63
- },
64
- },
65
- },
66
- {
67
- headers: { 'x-strapi-project': 'enterprise' },
68
- }
69
- );
70
- };
46
+ bootstrap() {},
71
47
 
72
- if (!pingDisabled) {
73
- const licenseCron = scheduleJob('0 0 0 * * 7', () => sendLicenseCheck());
74
- crons.push(licenseCron);
75
-
76
- sendLicenseCheck();
77
- }
78
- }
79
- },
80
48
  destroy() {
81
- // clear open handles
49
+ // Clear open handles
82
50
  crons.forEach((cron) => cron.cancel());
83
51
  },
52
+
84
53
  async send(event, payload) {
85
54
  if (isDisabled) return true;
86
55
  return sendEvent(event, payload);
@@ -88,24 +57,4 @@ const createTelemetryInstance = (strapi) => {
88
57
  };
89
58
  };
90
59
 
91
- const hash = (str) => crypto.createHash('sha256').update(str).digest('hex');
92
-
93
- const hashProject = (strapi) =>
94
- hash(`${strapi.config.get('info.name')}${strapi.config.get('info.description')}`);
95
-
96
- const hashDep = (strapi) => {
97
- const depStr = JSON.stringify(strapi.config.info.dependencies);
98
- const readmePath = path.join(strapi.dirs.app.root, 'README.md');
99
-
100
- try {
101
- if (fs.existsSync(readmePath)) {
102
- return hash(`${depStr}${fs.readFileSync(readmePath)}`);
103
- }
104
- } catch (err) {
105
- return hash(`${depStr}`);
106
- }
107
-
108
- return hash(`${depStr}`);
109
- };
110
-
111
60
  module.exports = createTelemetryInstance;
@@ -8,7 +8,6 @@ const fetch = require('node-fetch');
8
8
  const ciEnv = require('ci-info');
9
9
  const { isUsingTypeScriptSync } = require('@strapi/typescript-utils');
10
10
  const { env } = require('@strapi/utils');
11
- const ee = require('../../utils/ee');
12
11
  const machineID = require('../../utils/machine-id');
13
12
  const { generateAdminUserHash } = require('./admin-user-hash');
14
13
 
@@ -37,7 +36,6 @@ const addPackageJsonStrapiMetadata = (metadata, strapi) => {
37
36
  module.exports = (strapi) => {
38
37
  const { uuid } = strapi.config;
39
38
  const deviceId = machineID();
40
- const isEE = strapi.EE === true && ee.isEE === true;
41
39
 
42
40
  const serverRootPath = strapi.dirs.app.root;
43
41
  const adminRootPath = path.join(strapi.dirs.app.root, 'src', 'admin');
@@ -55,7 +53,6 @@ module.exports = (strapi) => {
55
53
  docker: process.env.DOCKER || isDocker(),
56
54
  isCI: ciEnv.isCI,
57
55
  version: strapi.config.get('info.strapi'),
58
- projectType: isEE ? 'Enterprise' : 'Community',
59
56
  useTypescriptOnServer: isUsingTypeScriptSync(serverRootPath),
60
57
  useTypescriptOnAdmin: isUsingTypeScriptSync(adminRootPath),
61
58
  projectId: uuid,
@@ -77,6 +74,7 @@ module.exports = (strapi) => {
77
74
  userProperties: userId ? { ...anonymousUserProperties, ...payload.userProperties } : {},
78
75
  groupProperties: {
79
76
  ...anonymousGroupProperties,
77
+ projectType: strapi.EE ? 'Enterprise' : 'Community',
80
78
  ...payload.groupProperties,
81
79
  },
82
80
  }),
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const { isEmpty, negate } = require('lodash/fp');
4
+
5
+ const INTEGER_REGEX = /^\d+$/;
6
+ const STEP_REGEX = /^\*\/\d+$/;
7
+ const COMPONENTS = [
8
+ { limit: 60, zeroBasedIndices: true, functionName: 'getSeconds' },
9
+ { limit: 60, zeroBasedIndices: true, functionName: 'getMinutes' },
10
+ { limit: 24, zeroBasedIndices: true, functionName: 'getHours' },
11
+ { limit: 31, zeroBasedIndices: false, functionName: 'getDate' },
12
+ { limit: 12, zeroBasedIndices: false, functionName: 'getMonth' },
13
+ { limit: 7, zeroBasedIndices: true, functionName: 'getDay' },
14
+ ];
15
+
16
+ const shift = (component, index, date) => {
17
+ if (component === '*') {
18
+ return '*';
19
+ }
20
+
21
+ const { limit, zeroBasedIndices, functionName } = COMPONENTS[index];
22
+ const offset = +!zeroBasedIndices;
23
+ const currentValue = date[functionName]();
24
+
25
+ if (INTEGER_REGEX.test(component)) {
26
+ return ((Number.parseInt(component, 10) + currentValue) % limit) + offset;
27
+ }
28
+
29
+ if (STEP_REGEX.test(component)) {
30
+ const [, step] = component.split('/');
31
+ const frequency = Math.floor(limit / step);
32
+ const list = Array.from({ length: frequency }, (_, index) => index * step);
33
+ return list.map((value) => ((value + currentValue) % limit) + offset).sort((a, b) => a - b);
34
+ }
35
+
36
+ // Unsupported syntax
37
+ return component;
38
+ };
39
+
40
+ /**
41
+ * Simulate an interval by shifting a cron expression using the specified date.
42
+ * @param {string} rule A cron expression you want to shift.
43
+ * @param {Date} date The date that's gonna be used as the start of the "interval", it defaults to now.
44
+ * @returns The shifted cron expression.
45
+ */
46
+ const shiftCronExpression = (rule, date = new Date()) => {
47
+ const components = rule.trim().split(' ').filter(negate(isEmpty));
48
+ const secondsIncluded = components.length === 6;
49
+ return components
50
+ .map((component, index) => shift(component, secondsIncluded ? index : index + 1, date))
51
+ .join(' ');
52
+ };
53
+
54
+ module.exports = {
55
+ shiftCronExpression,
56
+ };
package/lib/utils/ee.js CHANGED
@@ -1,123 +1,3 @@
1
1
  'use strict';
2
2
 
3
- const path = require('path');
4
- const fs = require('fs');
5
- const crypto = require('crypto');
6
- const _ = require('lodash');
7
-
8
- const publicKey = fs.readFileSync(path.join(__dirname, '../utils/resources/key.pub'));
9
-
10
- const noop = () => {};
11
-
12
- const noLog = {
13
- warn: noop,
14
- info: noop,
15
- };
16
-
17
- const internals = {};
18
- const features = {
19
- bronze: [],
20
- silver: [],
21
- gold: ['sso', 'audit-logs'],
22
- };
23
-
24
- module.exports = ({ dir, logger = noLog }) => {
25
- if (_.has(internals, 'isEE')) return internals.isEE;
26
-
27
- const warnAndReturn = (msg = 'Invalid license. Starting in CE.') => {
28
- logger.warn(msg);
29
- internals.isEE = false;
30
- return false;
31
- };
32
-
33
- if (process.env.STRAPI_DISABLE_EE === 'true') {
34
- internals.isEE = false;
35
- return false;
36
- }
37
-
38
- const licensePath = path.join(dir, 'license.txt');
39
-
40
- let license;
41
- if (_.has(process.env, 'STRAPI_LICENSE')) {
42
- license = process.env.STRAPI_LICENSE;
43
- } else if (fs.existsSync(licensePath)) {
44
- license = fs.readFileSync(licensePath).toString();
45
- }
46
-
47
- if (_.isNil(license)) {
48
- internals.isEE = false;
49
- return false;
50
- }
51
-
52
- try {
53
- const plainLicense = Buffer.from(license, 'base64').toString();
54
- const [signatureb64, contentb64] = plainLicense.split('\n');
55
-
56
- const signature = Buffer.from(signatureb64, 'base64');
57
- const content = Buffer.from(contentb64, 'base64').toString();
58
-
59
- const verifier = crypto.createVerify('RSA-SHA256');
60
- verifier.update(content);
61
- verifier.end();
62
-
63
- const isValid = verifier.verify(publicKey, signature);
64
- if (!isValid) return warnAndReturn();
65
-
66
- internals.licenseInfo = JSON.parse(content);
67
-
68
- const expirationTime = new Date(internals.licenseInfo.expireAt).getTime();
69
- if (expirationTime < new Date().getTime()) {
70
- return warnAndReturn('License expired. Starting in CE');
71
- }
72
- } catch (err) {
73
- return warnAndReturn();
74
- }
75
-
76
- internals.isEE = true;
77
- return true;
78
- };
79
-
80
- Object.defineProperty(module.exports, 'licenseInfo', {
81
- get() {
82
- mustHaveKey('licenseInfo');
83
- return internals.licenseInfo;
84
- },
85
- configurable: false,
86
- enumerable: false,
87
- });
88
-
89
- Object.defineProperty(module.exports, 'isEE', {
90
- get() {
91
- mustHaveKey('isEE');
92
- return internals.isEE;
93
- },
94
- configurable: false,
95
- enumerable: false,
96
- });
97
-
98
- Object.defineProperty(module.exports, 'features', {
99
- get() {
100
- mustHaveKey('licenseInfo');
101
-
102
- const { type: licenseType } = module.exports.licenseInfo;
103
-
104
- return {
105
- isEnabled(feature) {
106
- return features[licenseType].includes(feature);
107
- },
108
- getEnabled() {
109
- return features[licenseType];
110
- },
111
- };
112
- },
113
- configurable: false,
114
- enumerable: false,
115
- });
116
-
117
- const mustHaveKey = (key) => {
118
- if (!_.has(internals, key)) {
119
- const err = new Error('Tampering with license');
120
- // err.stack = null;
121
- throw err;
122
- }
123
- };
3
+ module.exports = require('../../ee');
@@ -4,7 +4,6 @@ const chalk = require('chalk');
4
4
  const CLITable = require('cli-table3');
5
5
  const _ = require('lodash/fp');
6
6
  const { getAbsoluteAdminUrl, getAbsoluteServerUrl } = require('@strapi/utils');
7
- const ee = require('./ee');
8
7
 
9
8
  module.exports = (app) => {
10
9
  return {
@@ -19,15 +18,14 @@ module.exports = (app) => {
19
18
  chars: { mid: '', 'left-mid': '', 'mid-mid': '', 'right-mid': '' },
20
19
  });
21
20
 
22
- const isEE = app.EE === true && ee.isEE === true;
23
-
24
21
  infoTable.push(
25
22
  [chalk.blue('Time'), `${new Date()}`],
26
23
  [chalk.blue('Launched in'), `${Date.now() - app.config.launchedAt} ms`],
27
24
  [chalk.blue('Environment'), app.config.environment],
28
25
  [chalk.blue('Process PID'), process.pid],
29
26
  [chalk.blue('Version'), `${app.config.info.strapi} (node ${process.version})`],
30
- [chalk.blue('Edition'), isEE ? 'Enterprise' : 'Community']
27
+ [chalk.blue('Edition'), app.EE ? 'Enterprise' : 'Community'],
28
+ [chalk.blue('Database'), app.db.dialect.client]
31
29
  );
32
30
 
33
31
  console.log(infoTable.toString());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.6.0-beta.2",
3
+ "version": "4.6.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",
@@ -71,7 +71,8 @@
71
71
  },
72
72
  "directories": {
73
73
  "lib": "./lib",
74
- "bin": "./bin"
74
+ "bin": "./bin",
75
+ "ee": "./ee"
75
76
  },
76
77
  "scripts": {
77
78
  "postinstall": "node lib/utils/success.js",
@@ -80,26 +81,26 @@
80
81
  "dependencies": {
81
82
  "@koa/cors": "3.4.3",
82
83
  "@koa/router": "10.1.1",
83
- "@strapi/admin": "4.6.0-beta.2",
84
- "@strapi/data-transfer": "4.6.0-beta.2",
85
- "@strapi/database": "4.6.0-beta.2",
86
- "@strapi/generate-new": "4.6.0-beta.2",
87
- "@strapi/generators": "4.6.0-beta.2",
88
- "@strapi/logger": "4.6.0-beta.2",
89
- "@strapi/permissions": "4.6.0-beta.2",
90
- "@strapi/plugin-content-manager": "4.6.0-beta.2",
91
- "@strapi/plugin-content-type-builder": "4.6.0-beta.2",
92
- "@strapi/plugin-email": "4.6.0-beta.2",
93
- "@strapi/plugin-upload": "4.6.0-beta.2",
94
- "@strapi/typescript-utils": "4.6.0-beta.2",
95
- "@strapi/utils": "4.6.0-beta.2",
84
+ "@strapi/admin": "4.6.0",
85
+ "@strapi/data-transfer": "4.6.0",
86
+ "@strapi/database": "4.6.0",
87
+ "@strapi/generate-new": "4.6.0",
88
+ "@strapi/generators": "4.6.0",
89
+ "@strapi/logger": "4.6.0",
90
+ "@strapi/permissions": "4.6.0",
91
+ "@strapi/plugin-content-manager": "4.6.0",
92
+ "@strapi/plugin-content-type-builder": "4.6.0",
93
+ "@strapi/plugin-email": "4.6.0",
94
+ "@strapi/plugin-upload": "4.6.0",
95
+ "@strapi/typescript-utils": "4.6.0",
96
+ "@strapi/utils": "4.6.0",
96
97
  "bcryptjs": "2.4.3",
97
98
  "boxen": "5.1.2",
98
99
  "chalk": "4.1.2",
99
100
  "chokidar": "3.5.2",
100
101
  "ci-info": "3.5.0",
101
102
  "cli-table3": "0.6.2",
102
- "commander": "8.2.0",
103
+ "commander": "8.3.0",
103
104
  "configstore": "5.0.1",
104
105
  "debug": "4.3.4",
105
106
  "delegates": "1.0.0",
@@ -141,5 +142,5 @@
141
142
  "node": ">=14.19.1 <=18.x.x",
142
143
  "npm": ">=6.0.0"
143
144
  },
144
- "gitHead": "b852090f931cd21868c4016f24db2f9fdfc7a7ab"
145
+ "gitHead": "a9e55435c489f3379d88565bf3f729deb29bfb45"
145
146
  }