@strapi/strapi 4.9.0-alpha.0 → 4.9.0-beta.1
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 +92 -60
- package/ee/index.js +6 -3
- package/ee/license.js +1 -1
- package/lib/Strapi.js +0 -4
- package/lib/commands/transfer/export.js +57 -28
- package/lib/commands/transfer/import.js +63 -23
- package/lib/commands/transfer/transfer.js +86 -33
- package/lib/commands/transfer/utils.js +82 -5
- package/lib/commands/utils/commander.js +17 -2
- package/lib/commands/utils/helpers.js +14 -7
- package/lib/core/registries/hooks.d.ts +1 -4
- package/lib/core/registries/policies.d.ts +5 -1
- package/lib/core-api/controller/collection-type.js +2 -3
- package/lib/core-api/controller/index.js +6 -0
- package/lib/core-api/controller/single-type.js +2 -2
- package/lib/global.d.ts +12 -7
- package/lib/index.d.ts +1 -1
- package/lib/services/auth/index.js +22 -1
- package/lib/services/cron.js +14 -1
- package/lib/services/entity-service/index.d.ts +1 -1
- package/lib/types/core/attributes/component.d.ts +4 -7
- package/lib/types/core/attributes/utils.d.ts +4 -5
- package/lib/types/core/index.d.ts +2 -2
- package/lib/types/index.d.ts +2 -2
- package/package.json +17 -17
- package/ee/ee-store.js +0 -18
package/bin/strapi.js
CHANGED
|
@@ -18,18 +18,16 @@ const {
|
|
|
18
18
|
promptEncryptionKey,
|
|
19
19
|
confirmMessage,
|
|
20
20
|
forceOption,
|
|
21
|
+
parseURL,
|
|
21
22
|
} = require('../lib/commands/utils/commander');
|
|
22
|
-
const { exitWith } = require('../lib/commands/utils/helpers');
|
|
23
|
+
const { exitWith, ifOptions, assertUrlHasProtocol } = require('../lib/commands/utils/helpers');
|
|
23
24
|
const {
|
|
24
25
|
excludeOption,
|
|
25
26
|
onlyOption,
|
|
27
|
+
throttleOption,
|
|
26
28
|
validateExcludeOnly,
|
|
27
29
|
} = require('../lib/commands/transfer/utils');
|
|
28
30
|
|
|
29
|
-
process.on('SIGINT', () => {
|
|
30
|
-
process.exit();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
31
|
const checkCwdIsStrapiApp = (name) => {
|
|
34
32
|
const logErrorAndExit = () => {
|
|
35
33
|
console.log(
|
|
@@ -272,59 +270,90 @@ program
|
|
|
272
270
|
.option('-s, --silent', `Run the generation silently, without any output`, false)
|
|
273
271
|
.action(getLocalScript('ts/generate-types'));
|
|
274
272
|
|
|
275
|
-
//
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
//
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
273
|
+
// `$ strapi transfer`
|
|
274
|
+
program
|
|
275
|
+
.command('transfer')
|
|
276
|
+
.description('Transfer data from one source to another')
|
|
277
|
+
.allowExcessArguments(false)
|
|
278
|
+
.addOption(
|
|
279
|
+
new Option(
|
|
280
|
+
'--from <sourceURL>',
|
|
281
|
+
`URL of the remote Strapi instance to get data from`
|
|
282
|
+
).argParser(parseURL)
|
|
283
|
+
)
|
|
284
|
+
.addOption(new Option('--from-token <token>', `Transfer token for the remote Strapi source`))
|
|
285
|
+
.addOption(
|
|
286
|
+
new Option(
|
|
287
|
+
'--to <destinationURL>',
|
|
288
|
+
`URL of the remote Strapi instance to send data to`
|
|
289
|
+
).argParser(parseURL)
|
|
290
|
+
)
|
|
291
|
+
.addOption(new Option('--to-token <token>', `Transfer token for the remote Strapi destination`))
|
|
292
|
+
.addOption(forceOption)
|
|
293
|
+
.addOption(excludeOption)
|
|
294
|
+
.addOption(onlyOption)
|
|
295
|
+
.addOption(throttleOption)
|
|
296
|
+
.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
|
+
// If --from is used, validate the URL and token
|
|
306
|
+
.hook(
|
|
307
|
+
'preAction',
|
|
308
|
+
ifOptions(
|
|
309
|
+
(opts) => opts.from,
|
|
310
|
+
async (thisCommand) => {
|
|
311
|
+
assertUrlHasProtocol(thisCommand.opts().from, ['https:', 'http:']);
|
|
312
|
+
if (!thisCommand.opts().fromToken) {
|
|
313
|
+
const answers = await inquirer.prompt([
|
|
314
|
+
{
|
|
315
|
+
type: 'password',
|
|
316
|
+
message: 'Please enter your transfer token for the remote Strapi source',
|
|
317
|
+
name: 'fromToken',
|
|
318
|
+
},
|
|
319
|
+
]);
|
|
320
|
+
if (!answers.fromToken?.length) {
|
|
321
|
+
exitWith(1, 'No token provided for remote source, aborting transfer.');
|
|
322
|
+
}
|
|
323
|
+
thisCommand.opts().fromToken = answers.fromToken;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
// If --to is used, validate the URL, token, and confirm restore
|
|
329
|
+
.hook(
|
|
330
|
+
'preAction',
|
|
331
|
+
ifOptions(
|
|
332
|
+
(opts) => opts.to,
|
|
333
|
+
async (thisCommand) => {
|
|
334
|
+
assertUrlHasProtocol(thisCommand.opts().to, ['https:', 'http:']);
|
|
335
|
+
if (!thisCommand.opts().toToken) {
|
|
336
|
+
const answers = await inquirer.prompt([
|
|
337
|
+
{
|
|
338
|
+
type: 'password',
|
|
339
|
+
message: 'Please enter your transfer token for the remote Strapi destination',
|
|
340
|
+
name: 'toToken',
|
|
341
|
+
},
|
|
342
|
+
]);
|
|
343
|
+
if (!answers.toToken?.length) {
|
|
344
|
+
exitWith(1, 'No token provided for remote destination, aborting transfer.');
|
|
345
|
+
}
|
|
346
|
+
thisCommand.opts().toToken = answers.toToken;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
await confirmMessage(
|
|
350
|
+
'The transfer will delete all data in the remote database and media files. Are you sure you want to proceed?',
|
|
351
|
+
{ failMessage: 'Transfer process aborted' }
|
|
352
|
+
)(thisCommand);
|
|
353
|
+
}
|
|
354
|
+
)
|
|
355
|
+
)
|
|
356
|
+
.action(getLocalScript('transfer/transfer'));
|
|
328
357
|
|
|
329
358
|
// `$ strapi export`
|
|
330
359
|
program
|
|
@@ -344,6 +373,7 @@ program
|
|
|
344
373
|
.addOption(new Option('-f, --file <file>', 'name to use for exported file (without extensions)'))
|
|
345
374
|
.addOption(excludeOption)
|
|
346
375
|
.addOption(onlyOption)
|
|
376
|
+
.addOption(throttleOption)
|
|
347
377
|
.hook('preAction', validateExcludeOnly)
|
|
348
378
|
.hook('preAction', promptEncryptionKey)
|
|
349
379
|
.action(getLocalScript('transfer/export'));
|
|
@@ -366,6 +396,7 @@ program
|
|
|
366
396
|
.addOption(forceOption)
|
|
367
397
|
.addOption(excludeOption)
|
|
368
398
|
.addOption(onlyOption)
|
|
399
|
+
.addOption(throttleOption)
|
|
369
400
|
.hook('preAction', validateExcludeOnly)
|
|
370
401
|
.hook('preAction', async (thisCommand) => {
|
|
371
402
|
const opts = thisCommand.opts();
|
|
@@ -382,7 +413,7 @@ program
|
|
|
382
413
|
},
|
|
383
414
|
]);
|
|
384
415
|
if (!answers.key?.length) {
|
|
385
|
-
exitWith(
|
|
416
|
+
exitWith(1, 'No key entered, aborting import.');
|
|
386
417
|
}
|
|
387
418
|
opts.key = answers.key;
|
|
388
419
|
}
|
|
@@ -420,7 +451,8 @@ program
|
|
|
420
451
|
.hook(
|
|
421
452
|
'preAction',
|
|
422
453
|
confirmMessage(
|
|
423
|
-
'The import will delete all 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?',
|
|
455
|
+
{ failMessage: 'Import process aborted' }
|
|
424
456
|
)
|
|
425
457
|
)
|
|
426
458
|
.action(getLocalScript('transfer/import'));
|
package/ee/index.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { pick } = require('lodash/fp');
|
|
4
4
|
|
|
5
5
|
const { readLicense, verifyLicense, fetchLicense, LicenseCheckError } = require('./license');
|
|
6
|
-
const { eeStoreModel } = require('./ee-store');
|
|
7
6
|
const { shiftCronExpression } = require('../lib/utils/cron');
|
|
8
7
|
|
|
9
8
|
const ONE_MINUTE = 1000 * 60;
|
|
@@ -60,7 +59,7 @@ const onlineUpdate = async ({ strapi }) => {
|
|
|
60
59
|
|
|
61
60
|
try {
|
|
62
61
|
const storedInfo = await strapi.db
|
|
63
|
-
.queryBuilder(
|
|
62
|
+
.queryBuilder('strapi::core-store')
|
|
64
63
|
.where({ key: 'ee_information' })
|
|
65
64
|
.select('value')
|
|
66
65
|
.first()
|
|
@@ -101,7 +100,7 @@ const onlineUpdate = async ({ strapi }) => {
|
|
|
101
100
|
|
|
102
101
|
if (shouldContactRegistry) {
|
|
103
102
|
result.license = license ?? null;
|
|
104
|
-
const query = strapi.db.queryBuilder(
|
|
103
|
+
const query = strapi.db.queryBuilder('strapi::core-store').transacting(transaction);
|
|
105
104
|
|
|
106
105
|
if (!storedInfo) {
|
|
107
106
|
query.insert({ key: 'ee_information', value: JSON.stringify(result) });
|
|
@@ -165,6 +164,10 @@ module.exports = Object.freeze({
|
|
|
165
164
|
return ee.enabled;
|
|
166
165
|
},
|
|
167
166
|
|
|
167
|
+
get seats() {
|
|
168
|
+
return ee.licenseInfo.seats;
|
|
169
|
+
},
|
|
170
|
+
|
|
168
171
|
features: Object.freeze({
|
|
169
172
|
list,
|
|
170
173
|
get,
|
package/ee/license.js
CHANGED
|
@@ -10,7 +10,7 @@ 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
|
+
gold: ['sso', { name: 'audit-logs', options: { retentionDays: 90 } }],
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
const publicKey = fs.readFileSync(join(__dirname, 'resources/key.pub'));
|
package/lib/Strapi.js
CHANGED
|
@@ -17,7 +17,6 @@ const { createServer } = require('./services/server');
|
|
|
17
17
|
const createWebhookRunner = require('./services/webhook-runner');
|
|
18
18
|
const { webhookModel, createWebhookStore } = require('./services/webhook-store');
|
|
19
19
|
const { createCoreStore, coreStoreModel } = require('./services/core-store');
|
|
20
|
-
const { eeStoreModel } = require('../ee/ee-store');
|
|
21
20
|
const createEntityService = require('./services/entity-service');
|
|
22
21
|
const createCronService = require('./services/cron');
|
|
23
22
|
const entityValidator = require('./services/entity-validator');
|
|
@@ -117,7 +116,6 @@ class Strapi {
|
|
|
117
116
|
this.cron = createCronService();
|
|
118
117
|
this.telemetry = createTelemetry(this);
|
|
119
118
|
this.requestContext = requestContext;
|
|
120
|
-
|
|
121
119
|
this.customFields = createCustomFields(this);
|
|
122
120
|
|
|
123
121
|
createUpdateNotifier(this).notify();
|
|
@@ -227,7 +225,6 @@ class Strapi {
|
|
|
227
225
|
|
|
228
226
|
async destroy() {
|
|
229
227
|
await this.server.destroy();
|
|
230
|
-
|
|
231
228
|
await this.runLifecyclesFunctions(LIFECYCLES.DESTROY);
|
|
232
229
|
|
|
233
230
|
this.eventHub.destroy();
|
|
@@ -409,7 +406,6 @@ class Strapi {
|
|
|
409
406
|
const contentTypes = [
|
|
410
407
|
coreStoreModel,
|
|
411
408
|
webhookModel,
|
|
412
|
-
eeStoreModel,
|
|
413
409
|
...Object.values(strapi.contentTypes),
|
|
414
410
|
...Object.values(strapi.components),
|
|
415
411
|
];
|
|
@@ -1,36 +1,43 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
file: {
|
|
5
|
+
providers: { createLocalFileDestinationProvider },
|
|
6
|
+
},
|
|
7
|
+
strapi: {
|
|
8
|
+
providers: { createLocalStrapiSourceProvider },
|
|
9
|
+
},
|
|
10
|
+
engine: { createTransferEngine },
|
|
11
|
+
} = require('@strapi/data-transfer');
|
|
12
|
+
|
|
10
13
|
const { isObject, isString, isFinite, toNumber } = require('lodash/fp');
|
|
11
14
|
const fs = require('fs-extra');
|
|
12
15
|
const chalk = require('chalk');
|
|
13
16
|
|
|
14
|
-
const { TransferEngineTransferError } = require('@strapi/data-transfer
|
|
17
|
+
const { TransferEngineTransferError } = require('@strapi/data-transfer').engine.errors;
|
|
15
18
|
const {
|
|
16
19
|
getDefaultExportName,
|
|
17
20
|
buildTransferTable,
|
|
18
21
|
DEFAULT_IGNORED_CONTENT_TYPES,
|
|
19
22
|
createStrapiInstance,
|
|
20
23
|
formatDiagnostic,
|
|
24
|
+
loadersFactory,
|
|
25
|
+
exitMessageText,
|
|
26
|
+
abortTransfer,
|
|
21
27
|
} = require('./utils');
|
|
22
|
-
|
|
28
|
+
const { exitWith } = require('../utils/helpers');
|
|
23
29
|
/**
|
|
24
30
|
* @typedef ExportCommandOptions Options given to the CLI import command
|
|
25
31
|
*
|
|
26
|
-
* @property {string} [file] The file path to
|
|
32
|
+
* @property {string} [file] The file path to export to
|
|
27
33
|
* @property {boolean} [encrypt] Used to encrypt the final archive
|
|
28
|
-
* @property {string} [key] Encryption key, only
|
|
34
|
+
* @property {string} [key] Encryption key, used only when encryption is enabled
|
|
29
35
|
* @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
|
|
30
39
|
*/
|
|
31
40
|
|
|
32
|
-
const logger = console;
|
|
33
|
-
|
|
34
41
|
const BYTES_IN_MB = 1024 * 1024;
|
|
35
42
|
|
|
36
43
|
/**
|
|
@@ -43,8 +50,7 @@ const BYTES_IN_MB = 1024 * 1024;
|
|
|
43
50
|
module.exports = async (opts) => {
|
|
44
51
|
// Validate inputs from Commander
|
|
45
52
|
if (!isObject(opts)) {
|
|
46
|
-
|
|
47
|
-
process.exit(1);
|
|
53
|
+
exitWith(1, 'Could not parse command arguments');
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
const strapi = await createStrapiInstance();
|
|
@@ -57,6 +63,7 @@ module.exports = async (opts) => {
|
|
|
57
63
|
schemaStrategy: 'ignore', // for an export to file, schemaStrategy will always be skipped
|
|
58
64
|
exclude: opts.exclude,
|
|
59
65
|
only: opts.only,
|
|
66
|
+
throttle: opts.throttle,
|
|
60
67
|
transforms: {
|
|
61
68
|
links: [
|
|
62
69
|
{
|
|
@@ -82,6 +89,20 @@ module.exports = async (opts) => {
|
|
|
82
89
|
|
|
83
90
|
const progress = engine.progress.stream;
|
|
84
91
|
|
|
92
|
+
const { updateLoader } = loadersFactory();
|
|
93
|
+
|
|
94
|
+
progress.on(`stage::start`, ({ stage, data }) => {
|
|
95
|
+
updateLoader(stage, data).start();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
progress.on('stage::finish', ({ stage, data }) => {
|
|
99
|
+
updateLoader(stage, data).succeed();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
progress.on('stage::progress', ({ stage, data }) => {
|
|
103
|
+
updateLoader(stage, data);
|
|
104
|
+
});
|
|
105
|
+
|
|
85
106
|
const getTelemetryPayload = (/* payload */) => {
|
|
86
107
|
return {
|
|
87
108
|
eventProperties: {
|
|
@@ -92,33 +113,41 @@ module.exports = async (opts) => {
|
|
|
92
113
|
};
|
|
93
114
|
|
|
94
115
|
progress.on('transfer::start', async () => {
|
|
95
|
-
|
|
116
|
+
console.log(`Starting export...`);
|
|
117
|
+
|
|
96
118
|
await strapi.telemetry.send('didDEITSProcessStart', getTelemetryPayload());
|
|
97
119
|
});
|
|
98
120
|
|
|
121
|
+
let results;
|
|
122
|
+
let outFile;
|
|
99
123
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
+
results = await engine.transfer();
|
|
131
|
+
outFile = results.destination.file.path;
|
|
106
132
|
const outFileExists = await fs.pathExists(outFile);
|
|
107
133
|
if (!outFileExists) {
|
|
108
134
|
throw new TransferEngineTransferError(`Export file not created "${outFile}"`);
|
|
109
135
|
}
|
|
110
|
-
|
|
111
|
-
logger.log(`${chalk.bold('Export process has been completed successfully!')}`);
|
|
112
|
-
logger.log(`Export archive is in ${chalk.green(outFile)}`);
|
|
113
136
|
} catch {
|
|
114
137
|
await strapi.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
|
|
115
|
-
|
|
116
|
-
process.exit(1);
|
|
138
|
+
exitWith(1, exitMessageText('export', true));
|
|
117
139
|
}
|
|
118
140
|
|
|
119
|
-
// Note: Telemetry can't be sent in a finish event, because it runs async after this block but we can't await it, so if process.exit is used it won't send
|
|
120
141
|
await strapi.telemetry.send('didDEITSProcessFinish', getTelemetryPayload());
|
|
121
|
-
|
|
142
|
+
try {
|
|
143
|
+
const table = buildTransferTable(results.engine);
|
|
144
|
+
console.log(table.toString());
|
|
145
|
+
} catch (e) {
|
|
146
|
+
console.error('There was an error displaying the results of the transfer.');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
console.log(`Export archive is in ${chalk.green(outFile)}`);
|
|
150
|
+
exitWith(0, exitMessageText('export'));
|
|
122
151
|
};
|
|
123
152
|
|
|
124
153
|
/**
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
createTransferEngine,
|
|
11
|
-
|
|
12
|
-
DEFAULT_SCHEMA_STRATEGY,
|
|
13
|
-
} = require('@strapi/data-transfer/lib/engine');
|
|
4
|
+
file: {
|
|
5
|
+
providers: { createLocalFileSourceProvider },
|
|
6
|
+
},
|
|
7
|
+
strapi: {
|
|
8
|
+
providers: { createLocalStrapiDestinationProvider, DEFAULT_CONFLICT_STRATEGY },
|
|
9
|
+
},
|
|
10
|
+
engine: { createTransferEngine, DEFAULT_VERSION_STRATEGY, DEFAULT_SCHEMA_STRATEGY },
|
|
11
|
+
} = require('@strapi/data-transfer');
|
|
14
12
|
|
|
15
13
|
const { isObject } = require('lodash/fp');
|
|
16
14
|
|
|
@@ -19,19 +17,37 @@ const {
|
|
|
19
17
|
DEFAULT_IGNORED_CONTENT_TYPES,
|
|
20
18
|
createStrapiInstance,
|
|
21
19
|
formatDiagnostic,
|
|
20
|
+
loadersFactory,
|
|
21
|
+
exitMessageText,
|
|
22
|
+
abortTransfer,
|
|
22
23
|
} = require('./utils');
|
|
24
|
+
const { exitWith } = require('../utils/helpers');
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
|
-
* @typedef {import('@strapi/data-transfer').ILocalFileSourceProviderOptions} ILocalFileSourceProviderOptions
|
|
27
|
+
* @typedef {import('@strapi/data-transfer/src/file/providers').ILocalFileSourceProviderOptions} ILocalFileSourceProviderOptions
|
|
26
28
|
*/
|
|
27
29
|
|
|
28
|
-
|
|
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
|
+
*/
|
|
29
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Import command.
|
|
42
|
+
*
|
|
43
|
+
* It transfers data from a file to a local Strapi instance
|
|
44
|
+
*
|
|
45
|
+
* @param {ImportCommandOptions} opts
|
|
46
|
+
*/
|
|
30
47
|
module.exports = async (opts) => {
|
|
31
48
|
// validate inputs from Commander
|
|
32
49
|
if (!isObject(opts)) {
|
|
33
|
-
|
|
34
|
-
process.exit(1);
|
|
50
|
+
exitWith(1, 'Could not parse arguments');
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
/**
|
|
@@ -66,6 +82,7 @@ module.exports = async (opts) => {
|
|
|
66
82
|
schemaStrategy: opts.schemaStrategy || DEFAULT_SCHEMA_STRATEGY,
|
|
67
83
|
exclude: opts.exclude,
|
|
68
84
|
only: opts.only,
|
|
85
|
+
throttle: opts.throttle,
|
|
69
86
|
rules: {
|
|
70
87
|
links: [
|
|
71
88
|
{
|
|
@@ -90,6 +107,21 @@ module.exports = async (opts) => {
|
|
|
90
107
|
engine.diagnostics.onDiagnostic(formatDiagnostic('import'));
|
|
91
108
|
|
|
92
109
|
const progress = engine.progress.stream;
|
|
110
|
+
|
|
111
|
+
const { updateLoader } = loadersFactory();
|
|
112
|
+
|
|
113
|
+
progress.on(`stage::start`, ({ stage, data }) => {
|
|
114
|
+
updateLoader(stage, data).start();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
progress.on('stage::finish', ({ stage, data }) => {
|
|
118
|
+
updateLoader(stage, data).succeed();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
progress.on('stage::progress', ({ stage, data }) => {
|
|
122
|
+
updateLoader(stage, data);
|
|
123
|
+
});
|
|
124
|
+
|
|
93
125
|
const getTelemetryPayload = () => {
|
|
94
126
|
return {
|
|
95
127
|
eventProperties: {
|
|
@@ -100,27 +132,35 @@ module.exports = async (opts) => {
|
|
|
100
132
|
};
|
|
101
133
|
|
|
102
134
|
progress.on('transfer::start', async () => {
|
|
103
|
-
|
|
135
|
+
console.log('Starting import...');
|
|
104
136
|
await strapiInstance.telemetry.send('didDEITSProcessStart', getTelemetryPayload());
|
|
105
137
|
});
|
|
106
138
|
|
|
139
|
+
let results;
|
|
107
140
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
+
});
|
|
111
146
|
|
|
112
|
-
|
|
147
|
+
results = await engine.transfer();
|
|
113
148
|
} catch (e) {
|
|
114
149
|
await strapiInstance.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
|
|
115
|
-
|
|
116
|
-
|
|
150
|
+
exitWith(1, exitMessageText('import', true));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const table = buildTransferTable(results.engine);
|
|
155
|
+
console.log(table.toString());
|
|
156
|
+
} catch (e) {
|
|
157
|
+
console.error('There was an error displaying the results of the transfer.');
|
|
117
158
|
}
|
|
118
159
|
|
|
119
|
-
// Note: Telemetry can't be sent in a finish event, because it runs async after this block but we can't await it, so if process.exit is used it won't send
|
|
120
160
|
await strapiInstance.telemetry.send('didDEITSProcessFinish', getTelemetryPayload());
|
|
121
161
|
await strapiInstance.destroy();
|
|
122
162
|
|
|
123
|
-
|
|
163
|
+
exitWith(0, exitMessageText('import'));
|
|
124
164
|
};
|
|
125
165
|
|
|
126
166
|
/**
|