@strapi/strapi 4.9.0 → 4.10.0-beta.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/bin/strapi.js CHANGED
@@ -24,10 +24,13 @@ const { exitWith, ifOptions, assertUrlHasProtocol } = require('../lib/commands/u
24
24
  const {
25
25
  excludeOption,
26
26
  onlyOption,
27
- throttleOption,
28
27
  validateExcludeOnly,
29
28
  } = require('../lib/commands/transfer/utils');
30
29
 
30
+ process.on('SIGINT', () => {
31
+ process.exit();
32
+ });
33
+
31
34
  const checkCwdIsStrapiApp = (name) => {
32
35
  const logErrorAndExit = () => {
33
36
  console.log(
@@ -276,12 +279,13 @@ program
276
279
  .description('Transfer data from one source to another')
277
280
  .allowExcessArguments(false)
278
281
  .addOption(
279
- new Option(
280
- '--from <sourceURL>',
281
- `URL of the remote Strapi instance to get data from`
282
- ).argParser(parseURL)
282
+ new Option('--from <sourceURL>', `URL of the remote Strapi instance to get data from`)
283
+ .argParser(parseURL)
284
+ .hideHelp() // Hidden until pull feature is released
285
+ )
286
+ .addOption(
287
+ new Option('--from-token <token>', `Transfer token for the remote Strapi source`).hideHelp() // Hidden until pull feature is released
283
288
  )
284
- .addOption(new Option('--from-token <token>', `Transfer token for the remote Strapi source`))
285
289
  .addOption(
286
290
  new Option(
287
291
  '--to <destinationURL>',
@@ -292,16 +296,7 @@ program
292
296
  .addOption(forceOption)
293
297
  .addOption(excludeOption)
294
298
  .addOption(onlyOption)
295
- .addOption(throttleOption)
296
299
  .hook('preAction', validateExcludeOnly)
297
- .hook(
298
- 'preAction',
299
- ifOptions(
300
- (opts) => !(opts.from || opts.to) || (opts.from && opts.to),
301
- () =>
302
- exitWith(1, 'Exactly one remote source (from) or destination (to) option must be provided')
303
- )
304
- )
305
300
  // If --from is used, validate the URL and token
306
301
  .hook(
307
302
  'preAction',
@@ -318,15 +313,10 @@ program
318
313
  },
319
314
  ]);
320
315
  if (!answers.fromToken?.length) {
321
- exitWith(1, 'No token provided for remote source, aborting transfer.');
316
+ exitWith(1, 'No token entered, aborting transfer.');
322
317
  }
323
318
  thisCommand.opts().fromToken = answers.fromToken;
324
319
  }
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);
330
320
  }
331
321
  )
332
322
  )
@@ -346,18 +336,25 @@ program
346
336
  },
347
337
  ]);
348
338
  if (!answers.toToken?.length) {
349
- exitWith(1, 'No token provided for remote destination, aborting transfer.');
339
+ exitWith(1, 'No token entered, aborting transfer.');
350
340
  }
351
341
  thisCommand.opts().toToken = answers.toToken;
352
342
  }
353
343
 
354
344
  await confirmMessage(
355
- 'The transfer will delete all the remote Strapi assets and its database. Are you sure you want to proceed?',
345
+ 'The transfer will delete all data in the remote database and media files. Are you sure you want to proceed?',
356
346
  { failMessage: 'Transfer process aborted' }
357
347
  )(thisCommand);
358
348
  }
359
349
  )
360
350
  )
351
+ // .hook(
352
+ // 'preAction',
353
+ // ifOptions(
354
+ // (opts) => !opts.from && !opts.to,
355
+ // () => exitWith(1, 'At least one source (from) or destination (to) option must be provided')
356
+ // )
357
+ // )
361
358
  .action(getLocalScript('transfer/transfer'));
362
359
 
363
360
  // `$ strapi export`
@@ -378,7 +375,6 @@ program
378
375
  .addOption(new Option('-f, --file <file>', 'name to use for exported file (without extensions)'))
379
376
  .addOption(excludeOption)
380
377
  .addOption(onlyOption)
381
- .addOption(throttleOption)
382
378
  .hook('preAction', validateExcludeOnly)
383
379
  .hook('preAction', promptEncryptionKey)
384
380
  .action(getLocalScript('transfer/export'));
@@ -401,7 +397,6 @@ program
401
397
  .addOption(forceOption)
402
398
  .addOption(excludeOption)
403
399
  .addOption(onlyOption)
404
- .addOption(throttleOption)
405
400
  .hook('preAction', validateExcludeOnly)
406
401
  .hook('preAction', async (thisCommand) => {
407
402
  const opts = thisCommand.opts();
@@ -456,7 +451,7 @@ program
456
451
  .hook(
457
452
  'preAction',
458
453
  confirmMessage(
459
- 'The import will delete all assets and data in your database. Are you sure you want to proceed?',
454
+ 'The import will delete all data in your database and media files. Are you sure you want to proceed?',
460
455
  { failMessage: 'Import process aborted' }
461
456
  )
462
457
  )
package/ee/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { pick, isEqual } = require('lodash/fp');
3
+ const { pick } = require('lodash/fp');
4
4
 
5
5
  const { readLicense, verifyLicense, fetchLicense, LicenseCheckError } = require('./license');
6
6
  const { shiftCronExpression } = require('../lib/utils/cron');
@@ -13,31 +13,10 @@ 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
-
19
16
  ee.logger?.warn(`${message} Switching to CE.`);
20
17
  // Only keep the license key for potential re-enabling during a later check
21
18
  ee.licenseInfo = pick('licenseKey', ee.licenseInfo);
22
-
23
19
  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
- }
41
20
  };
42
21
 
43
22
  let initialized = false;
@@ -62,7 +41,7 @@ const init = (licenseDir, logger) => {
62
41
 
63
42
  if (license) {
64
43
  ee.licenseInfo = verifyLicense(license);
65
- enable();
44
+ ee.enabled = true;
66
45
  }
67
46
  } catch (error) {
68
47
  disable(error.message);
@@ -110,22 +89,8 @@ const onlineUpdate = async ({ strapi }) => {
110
89
 
111
90
  if (license) {
112
91
  try {
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;
92
+ ee.licenseInfo = verifyLicense(license);
123
93
  validateInfo();
124
-
125
- // Notify EE features
126
- if (licenseInfoChanged && wasEnabled) {
127
- strapi.eventHub.emit('ee.update');
128
- }
129
94
  } catch (error) {
130
95
  disable(error.message);
131
96
  }
@@ -160,7 +125,7 @@ const validateInfo = () => {
160
125
  return disable('License expired.');
161
126
  }
162
127
 
163
- enable();
128
+ ee.enabled = true;
164
129
  };
165
130
 
166
131
  const checkLicense = async ({ strapi }) => {
package/ee/license.js CHANGED
@@ -10,9 +10,7 @@ const machineId = require('../lib/utils/machine-id');
10
10
  const DEFAULT_FEATURES = {
11
11
  bronze: [],
12
12
  silver: [],
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 } }],
13
+ gold: ['sso', { name: 'audit-logs', options: { retentionDays: 90 } }, 'review-workflows'],
16
14
  };
17
15
 
18
16
  const publicKey = fs.readFileSync(join(__dirname, 'resources/key.pub'));
@@ -22,20 +22,15 @@ const {
22
22
  createStrapiInstance,
23
23
  formatDiagnostic,
24
24
  loadersFactory,
25
- exitMessageText,
26
- abortTransfer,
27
25
  } = require('./utils');
28
26
  const { exitWith } = require('../utils/helpers');
29
27
  /**
30
28
  * @typedef ExportCommandOptions Options given to the CLI import command
31
29
  *
32
- * @property {string} [file] The file path to export to
30
+ * @property {string} [file] The file path to import
33
31
  * @property {boolean} [encrypt] Used to encrypt the final archive
34
- * @property {string} [key] Encryption key, used only when encryption is enabled
32
+ * @property {string} [key] Encryption key, only useful when encryption is enabled
35
33
  * @property {boolean} [compress] Used to compress the final archive
36
- * @property {(keyof import('@strapi/data-transfer/src/engine').TransferGroupFilter)[]} [only] If present, only include these filtered groups of data
37
- * @property {(keyof import('@strapi/data-transfer/src/engine').TransferGroupFilter)[]} [exclude] If present, exclude these filtered groups of data
38
- * @property {number|undefined} [throttle] Delay in ms after each record
39
34
  */
40
35
 
41
36
  const BYTES_IN_MB = 1024 * 1024;
@@ -63,7 +58,6 @@ module.exports = async (opts) => {
63
58
  schemaStrategy: 'ignore', // for an export to file, schemaStrategy will always be skipped
64
59
  exclude: opts.exclude,
65
60
  only: opts.only,
66
- throttle: opts.throttle,
67
61
  transforms: {
68
62
  links: [
69
63
  {
@@ -114,19 +108,12 @@ module.exports = async (opts) => {
114
108
 
115
109
  progress.on('transfer::start', async () => {
116
110
  console.log(`Starting export...`);
117
-
118
111
  await strapi.telemetry.send('didDEITSProcessStart', getTelemetryPayload());
119
112
  });
120
113
 
121
114
  let results;
122
115
  let outFile;
123
116
  try {
124
- // Abort transfer if user interrupts process
125
- ['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
126
- process.removeAllListeners(signal);
127
- process.on(signal, () => abortTransfer({ engine, strapi }));
128
- });
129
-
130
117
  results = await engine.transfer();
131
118
  outFile = results.destination.file.path;
132
119
  const outFileExists = await fs.pathExists(outFile);
@@ -135,7 +122,7 @@ module.exports = async (opts) => {
135
122
  }
136
123
  } catch {
137
124
  await strapi.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
138
- exitWith(1, exitMessageText('export', true));
125
+ exitWith(1, 'Export process failed.');
139
126
  }
140
127
 
141
128
  await strapi.telemetry.send('didDEITSProcessFinish', getTelemetryPayload());
@@ -146,8 +133,8 @@ module.exports = async (opts) => {
146
133
  console.error('There was an error displaying the results of the transfer.');
147
134
  }
148
135
 
149
- console.log(`Export archive is in ${chalk.green(outFile)}`);
150
- exitWith(0, exitMessageText('export'));
136
+ console.log(`${chalk.bold('Export process has been completed successfully!')}`);
137
+ exitWith(0, `Export archive is in ${chalk.green(outFile)}`);
151
138
  };
152
139
 
153
140
  /**
@@ -18,32 +18,13 @@ const {
18
18
  createStrapiInstance,
19
19
  formatDiagnostic,
20
20
  loadersFactory,
21
- exitMessageText,
22
- abortTransfer,
23
21
  } = require('./utils');
24
22
  const { exitWith } = require('../utils/helpers');
25
23
 
26
24
  /**
27
- * @typedef {import('@strapi/data-transfer/src/file/providers').ILocalFileSourceProviderOptions} ILocalFileSourceProviderOptions
25
+ * @typedef {import('@strapi/data-transfer').ILocalFileSourceProviderOptions} ILocalFileSourceProviderOptions
28
26
  */
29
27
 
30
- /**
31
- * @typedef ImportCommandOptions Options given to the CLI import command
32
- *
33
- * @property {string} [file] The file path to import
34
- * @property {string} [key] Encryption key, used when encryption is enabled
35
- * @property {(keyof import('@strapi/data-transfer/src/engine').TransferGroupFilter)[]} [only] If present, only include these filtered groups of data
36
- * @property {(keyof import('@strapi/data-transfer/src/engine').TransferGroupFilter)[]} [exclude] If present, exclude these filtered groups of data
37
- * @property {number|undefined} [throttle] Delay in ms after each record
38
- */
39
-
40
- /**
41
- * Import command.
42
- *
43
- * It transfers data from a file to a local Strapi instance
44
- *
45
- * @param {ImportCommandOptions} opts
46
- */
47
28
  module.exports = async (opts) => {
48
29
  // validate inputs from Commander
49
30
  if (!isObject(opts)) {
@@ -82,7 +63,6 @@ module.exports = async (opts) => {
82
63
  schemaStrategy: opts.schemaStrategy || DEFAULT_SCHEMA_STRATEGY,
83
64
  exclude: opts.exclude,
84
65
  only: opts.only,
85
- throttle: opts.throttle,
86
66
  rules: {
87
67
  links: [
88
68
  {
@@ -138,16 +118,11 @@ module.exports = async (opts) => {
138
118
 
139
119
  let results;
140
120
  try {
141
- // Abort transfer if user interrupts process
142
- ['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
143
- process.removeAllListeners(signal);
144
- process.on(signal, () => abortTransfer({ engine, strapi }));
145
- });
146
-
147
121
  results = await engine.transfer();
148
122
  } catch (e) {
149
123
  await strapiInstance.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
150
- exitWith(1, exitMessageText('import', true));
124
+ console.error('Import process failed.');
125
+ process.exit(1);
151
126
  }
152
127
 
153
128
  try {
@@ -160,7 +135,7 @@ module.exports = async (opts) => {
160
135
  await strapiInstance.telemetry.send('didDEITSProcessFinish', getTelemetryPayload());
161
136
  await strapiInstance.destroy();
162
137
 
163
- exitWith(0, exitMessageText('import'));
138
+ exitWith(0, 'Import process has been completed successfully!');
164
139
  };
165
140
 
166
141
  /**
@@ -7,11 +7,11 @@ const {
7
7
  createRemoteStrapiDestinationProvider,
8
8
  createLocalStrapiSourceProvider,
9
9
  createLocalStrapiDestinationProvider,
10
- createRemoteStrapiSourceProvider,
11
10
  },
12
11
  },
13
12
  } = require('@strapi/data-transfer');
14
13
  const { isObject } = require('lodash/fp');
14
+ const chalk = require('chalk');
15
15
 
16
16
  const {
17
17
  buildTransferTable,
@@ -19,8 +19,6 @@ const {
19
19
  DEFAULT_IGNORED_CONTENT_TYPES,
20
20
  formatDiagnostic,
21
21
  loadersFactory,
22
- exitMessageText,
23
- abortTransfer,
24
22
  } = require('./utils');
25
23
  const { exitWith } = require('../utils/helpers');
26
24
 
@@ -31,9 +29,6 @@ const { exitWith } = require('../utils/helpers');
31
29
  * @property {URL|undefined} [from] The url of a remote Strapi to use as remote source
32
30
  * @property {string|undefined} [toToken] The transfer token for the remote Strapi destination
33
31
  * @property {string|undefined} [fromToken] The transfer token for the remote Strapi source
34
- * @property {(keyof import('@strapi/data-transfer/src/engine').TransferGroupFilter)[]} [only] If present, only include these filtered groups of data
35
- * @property {(keyof import('@strapi/data-transfer/src/engine').TransferGroupFilter)[]} [exclude] If present, exclude these filtered groups of data
36
- * @property {number|undefined} [throttle] Delay in ms after each record
37
32
  */
38
33
 
39
34
  /**
@@ -49,14 +44,15 @@ module.exports = async (opts) => {
49
44
  exitWith(1, 'Could not parse command arguments');
50
45
  }
51
46
 
52
- if (!(opts.from || opts.to) || (opts.from && opts.to)) {
53
- exitWith(1, 'Exactly one source (from) or destination (to) option must be provided');
54
- }
55
-
56
47
  const strapi = await createStrapiInstance();
48
+
57
49
  let source;
58
50
  let destination;
59
51
 
52
+ if (!opts.from && !opts.to) {
53
+ exitWith(1, 'At least one source (from) or destination (to) option must be provided');
54
+ }
55
+
60
56
  // if no URL provided, use local Strapi
61
57
  if (!opts.from) {
62
58
  source = createLocalStrapiSourceProvider({
@@ -65,28 +61,13 @@ module.exports = async (opts) => {
65
61
  }
66
62
  // if URL provided, set up a remote source provider
67
63
  else {
68
- if (!opts.fromToken) {
69
- exitWith(1, 'Missing token for remote destination');
70
- }
71
-
72
- source = createRemoteStrapiSourceProvider({
73
- getStrapi: () => strapi,
74
- url: opts.from,
75
- auth: {
76
- type: 'token',
77
- token: opts.fromToken,
78
- },
79
- });
64
+ exitWith(1, `Remote Strapi source provider not yet implemented`);
80
65
  }
81
66
 
82
67
  // if no URL provided, use local Strapi
83
68
  if (!opts.to) {
84
69
  destination = createLocalStrapiDestinationProvider({
85
70
  getStrapi: () => strapi,
86
- strategy: 'restore',
87
- restore: {
88
- entities: { exclude: DEFAULT_IGNORED_CONTENT_TYPES },
89
- },
90
71
  });
91
72
  }
92
73
  // if URL provided, set up a remote destination provider
@@ -115,9 +96,6 @@ module.exports = async (opts) => {
115
96
  const engine = createTransferEngine(source, destination, {
116
97
  versionStrategy: 'exact',
117
98
  schemaStrategy: 'strict',
118
- exclude: opts.exclude,
119
- only: opts.only,
120
- throttle: opts.throttle,
121
99
  transforms: {
122
100
  links: [
123
101
  {
@@ -157,26 +135,15 @@ module.exports = async (opts) => {
157
135
  updateLoader(stage, data);
158
136
  });
159
137
 
160
- progress.on('stage::error', ({ stage, data }) => {
161
- updateLoader(stage, data).fail();
162
- });
163
-
164
138
  let results;
165
139
  try {
166
140
  console.log(`Starting transfer...`);
167
-
168
- // Abort transfer if user interrupts process
169
- ['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
170
- process.removeAllListeners(signal);
171
- process.on(signal, () => abortTransfer({ engine, strapi }));
172
- });
173
-
174
141
  results = await engine.transfer();
175
142
  } catch (e) {
176
- exitWith(1, exitMessageText('transfer', true));
143
+ exitWith(1, 'Transfer process failed.');
177
144
  }
178
145
 
179
146
  const table = buildTransferTable(results.engine);
180
147
  console.log(table.toString());
181
- exitWith(0, exitMessageText('transfer'));
148
+ exitWith(0, `${chalk.bold('Transfer process has been completed successfully!')}`);
182
149
  };
@@ -14,19 +14,7 @@ const {
14
14
  const ora = require('ora');
15
15
  const { readableBytes, exitWith } = require('../utils/helpers');
16
16
  const strapi = require('../../index');
17
- const { getParseListWithChoices, parseInteger } = require('../utils/commander');
18
-
19
- const exitMessageText = (process, error = false) => {
20
- const processCapitalized = process[0].toUpperCase() + process.slice(1);
21
-
22
- if (!error) {
23
- return chalk.bold(
24
- chalk.green(`${processCapitalized} process has been completed successfully!`)
25
- );
26
- }
27
-
28
- return chalk.bold(chalk.red(`${processCapitalized} process failed.`));
29
- };
17
+ const { getParseListWithChoices } = require('../utils/commander');
30
18
 
31
19
  const pad = (n) => {
32
20
  return (n < 10 ? '0' : '') + String(n);
@@ -102,23 +90,12 @@ const DEFAULT_IGNORED_CONTENT_TYPES = [
102
90
  'admin::audit-log',
103
91
  ];
104
92
 
105
- const abortTransfer = async ({ engine, strapi }) => {
106
- try {
107
- await engine.abortTransfer();
108
- await strapi.destroy();
109
- } catch (e) {
110
- // ignore because there's not much else we can do
111
- return false;
112
- }
113
- return true;
114
- };
115
-
116
- const createStrapiInstance = async (opts = {}) => {
93
+ const createStrapiInstance = async (logLevel = 'error') => {
117
94
  try {
118
95
  const appContext = await strapi.compile();
119
- const app = strapi({ ...opts, ...appContext });
96
+ const app = strapi(appContext);
120
97
 
121
- app.log.level = opts.logLevel || 'error';
98
+ app.log.level = logLevel;
122
99
  return await app.load();
123
100
  } catch (err) {
124
101
  if (err.code === 'ECONNREFUSED') {
@@ -130,13 +107,6 @@ const createStrapiInstance = async (opts = {}) => {
130
107
 
131
108
  const transferDataTypes = Object.keys(TransferGroupPresets);
132
109
 
133
- const throttleOption = new Option(
134
- '--throttle <delay after each entity>',
135
- `Add a delay in milliseconds between each transferred entity`
136
- )
137
- .argParser(parseInteger)
138
- .hideHelp(); // This option is not publicly documented
139
-
140
110
  const excludeOption = new Option(
141
111
  '--exclude <comma-separated data types>',
142
112
  `Exclude data using comma-separated types. Available types: ${transferDataTypes.join(',')}`
@@ -249,10 +219,7 @@ module.exports = {
249
219
  DEFAULT_IGNORED_CONTENT_TYPES,
250
220
  createStrapiInstance,
251
221
  excludeOption,
252
- exitMessageText,
253
222
  onlyOption,
254
- throttleOption,
255
223
  validateExcludeOnly,
256
224
  formatDiagnostic,
257
- abortTransfer,
258
225
  };
@@ -7,7 +7,6 @@
7
7
  const inquirer = require('inquirer');
8
8
  const { InvalidOptionArgumentError, Option } = require('commander');
9
9
  const { bold, green, cyan } = require('chalk');
10
- const { isNaN } = require('lodash/fp');
11
10
  const { exitWith } = require('./helpers');
12
11
 
13
12
  /**
@@ -41,18 +40,6 @@ const getParseListWithChoices = (choices, errorMessage = 'Invalid options:') =>
41
40
  };
42
41
  };
43
42
 
44
- /**
45
- * argParser: Parse a string as an integer
46
- */
47
- const parseInteger = (value) => {
48
- // parseInt takes a string and a radix
49
- const parsedValue = parseInt(value, 10);
50
- if (isNaN(parsedValue)) {
51
- throw new InvalidOptionArgumentError(`Not an integer: ${value}`);
52
- }
53
- return parsedValue;
54
- };
55
-
56
43
  /**
57
44
  * argParser: Parse a string as a URL object
58
45
  */
@@ -144,7 +131,6 @@ module.exports = {
144
131
  getParseListWithChoices,
145
132
  parseList,
146
133
  parseURL,
147
- parseInteger,
148
134
  promptEncryptionKey,
149
135
  confirmMessage,
150
136
  forceOption,
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { join } = require('path');
4
4
  const fse = require('fs-extra');
5
- const { defaultsDeep, defaults, getOr, get } = require('lodash/fp');
5
+ const { defaultsDeep, 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,12 +101,7 @@ const loadPlugins = async (strapi) => {
101
101
  }
102
102
 
103
103
  const pluginServer = loadConfigFile(serverEntrypointPath);
104
- plugins[pluginName] = {
105
- ...defaultPlugin,
106
- ...pluginServer,
107
- config: defaults(defaultPlugin.config, pluginServer.config),
108
- routes: pluginServer.routes ?? defaultPlugin.routes,
109
- };
104
+ plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
110
105
  }
111
106
 
112
107
  // TODO: validate plugin format
@@ -22,6 +22,7 @@ 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
+
25
26
  return this.transformResponse(sanitizedResults, { pagination });
26
27
  },
27
28
 
@@ -18,7 +18,7 @@ const createController = ({ contentType }) => {
18
18
  return transformResponse(data, meta, { contentType });
19
19
  },
20
20
 
21
- async sanitizeOutput(data, ctx) {
21
+ 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,12 +45,13 @@ const createCoreService = (uid, cfg = {}) => {
45
45
  };
46
46
 
47
47
  const createCoreRouter = (uid, cfg = {}) => {
48
- const { prefix, config = {}, only, except, type } = cfg;
48
+ const { prefix, config = {}, only, except } = cfg;
49
49
  let routes;
50
50
 
51
51
  return {
52
- type,
53
- prefix,
52
+ get prefix() {
53
+ return prefix;
54
+ },
54
55
  get routes() {
55
56
  if (!routes) {
56
57
  const contentType = strapi.contentType(uid);
@@ -1,5 +1,21 @@
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
+
3
19
  /**
4
20
  * @type {import('./').MiddlewareFactory}
5
21
  */
@@ -9,6 +25,6 @@ module.exports = (_, { strapi }) => {
9
25
  await next();
10
26
  const delta = Math.ceil(Date.now() - start);
11
27
 
12
- strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${ctx.status}`);
28
+ strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${codeToColor(ctx.status)}`);
13
29
  };
14
30
  };
@@ -35,12 +35,7 @@ module.exports = function createEventHub() {
35
35
  },
36
36
 
37
37
  unsubscribe(subscriber) {
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
- }
38
+ subscribers.splice(subscribers.indexOf(subscriber), 1);
44
39
  },
45
40
 
46
41
  on(eventName, listener) {
@@ -17,7 +17,6 @@ const LIMITED_EVENTS = [
17
17
  'didSaveMediaWithCaption',
18
18
  'didDisableResponsiveDimensions',
19
19
  'didEnableResponsiveDimensions',
20
- 'didInitializePluginUpload',
21
20
  ];
22
21
 
23
22
  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 = router.prefix || `/${pluginName}`;
72
+ 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",
3
+ "version": "4.10.0-beta.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,7 +66,9 @@
66
66
  ],
67
67
  "main": "./lib",
68
68
  "types": "./lib/index.d.ts",
69
- "bin": "./bin/strapi.js",
69
+ "bin": {
70
+ "strapi": "./bin/strapi.js"
71
+ },
70
72
  "directories": {
71
73
  "lib": "./lib",
72
74
  "bin": "./bin",
@@ -74,26 +76,24 @@
74
76
  },
75
77
  "scripts": {
76
78
  "postinstall": "node lib/utils/success.js",
77
- "test:unit": "jest",
78
- "test:unit:watch": "jest --watch",
79
- "lint": "eslint ."
79
+ "test:unit": "jest --verbose"
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",
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",
84
+ "@strapi/admin": "4.10.0-beta.0",
85
+ "@strapi/data-transfer": "4.10.0-beta.0",
86
+ "@strapi/database": "4.10.0-beta.0",
87
+ "@strapi/generate-new": "4.10.0-beta.0",
88
+ "@strapi/generators": "4.10.0-beta.0",
89
+ "@strapi/logger": "4.10.0-beta.0",
90
+ "@strapi/permissions": "4.10.0-beta.0",
91
+ "@strapi/plugin-content-manager": "4.10.0-beta.0",
92
+ "@strapi/plugin-content-type-builder": "4.10.0-beta.0",
93
+ "@strapi/plugin-email": "4.10.0-beta.0",
94
+ "@strapi/plugin-upload": "4.10.0-beta.0",
95
+ "@strapi/typescript-utils": "4.10.0-beta.0",
96
+ "@strapi/utils": "4.10.0-beta.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.1",
131
+ "qs": "6.11.0",
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": "ffe3f4621ccc968ce56fda9a8317ec30d4bad205"
145
+ "gitHead": "1519ef0e56d27b738f24fc88223797651ad47aaf"
146
146
  }
package/.eslintignore DELETED
@@ -1,2 +0,0 @@
1
- node_modules/
2
- .eslintrc.js
package/.eslintrc.js DELETED
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- extends: ['custom/back'],
4
- };