@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 +21 -26
- package/ee/index.js +4 -39
- package/ee/license.js +1 -3
- package/lib/commands/transfer/export.js +5 -18
- package/lib/commands/transfer/import.js +4 -29
- package/lib/commands/transfer/transfer.js +9 -42
- package/lib/commands/transfer/utils.js +4 -37
- package/lib/commands/utils/commander.js +0 -14
- package/lib/core/loaders/plugins/index.js +2 -7
- package/lib/core-api/controller/collection-type.js +1 -0
- package/lib/core-api/controller/index.js +1 -1
- package/lib/factories.js +4 -3
- package/lib/middlewares/logger.js +17 -1
- package/lib/services/event-hub.js +1 -6
- package/lib/services/metrics/index.js +0 -1
- package/lib/services/server/register-routes.js +1 -1
- package/package.json +20 -20
- package/.eslintignore +0 -2
- package/.eslintrc.js +0 -4
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
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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(
|
|
150
|
-
exitWith(0,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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(
|
|
96
|
+
const app = strapi(appContext);
|
|
120
97
|
|
|
121
|
-
app.log.level =
|
|
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,
|
|
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
|
-
|
|
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
|
|
48
|
+
const { prefix, config = {}, only, except } = cfg;
|
|
49
49
|
let routes;
|
|
50
50
|
|
|
51
51
|
return {
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -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 =
|
|
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.
|
|
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":
|
|
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.
|
|
85
|
-
"@strapi/data-transfer": "4.
|
|
86
|
-
"@strapi/database": "4.
|
|
87
|
-
"@strapi/generate-new": "4.
|
|
88
|
-
"@strapi/generators": "4.
|
|
89
|
-
"@strapi/logger": "4.
|
|
90
|
-
"@strapi/permissions": "4.
|
|
91
|
-
"@strapi/plugin-content-manager": "4.
|
|
92
|
-
"@strapi/plugin-content-type-builder": "4.
|
|
93
|
-
"@strapi/plugin-email": "4.
|
|
94
|
-
"@strapi/plugin-upload": "4.
|
|
95
|
-
"@strapi/typescript-utils": "4.
|
|
96
|
-
"@strapi/utils": "4.
|
|
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.
|
|
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": "
|
|
145
|
+
"gitHead": "1519ef0e56d27b738f24fc88223797651ad47aaf"
|
|
146
146
|
}
|
package/.eslintignore
DELETED
package/.eslintrc.js
DELETED