@strapi/data-transfer 4.14.0-alpha.0 → 4.14.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.
Files changed (92) hide show
  1. package/dist/commands/commander.d.ts +35 -0
  2. package/dist/commands/commander.js +138 -0
  3. package/dist/commands/commander.js.map +1 -0
  4. package/dist/commands/data-transfer.d.ts +135 -0
  5. package/dist/commands/data-transfer.js +359 -0
  6. package/dist/commands/data-transfer.js.map +1 -0
  7. package/dist/commands/export/action.d.ts +20 -0
  8. package/dist/commands/export/action.js +156 -0
  9. package/dist/commands/export/action.js.map +1 -0
  10. package/dist/commands/export/command.d.ts +8 -0
  11. package/dist/commands/export/command.js +30 -0
  12. package/dist/commands/export/command.js.map +1 -0
  13. package/dist/commands/helpers.d.ts +30 -0
  14. package/dist/commands/helpers.js +87 -0
  15. package/dist/commands/helpers.js.map +1 -0
  16. package/dist/commands/import/action.d.ts +19 -0
  17. package/dist/commands/import/action.js +139 -0
  18. package/dist/commands/import/action.js.map +1 -0
  19. package/dist/commands/import/command.d.ts +8 -0
  20. package/dist/commands/import/command.js +75 -0
  21. package/dist/commands/import/command.js.map +1 -0
  22. package/dist/commands/index.d.ts +3 -0
  23. package/dist/commands/index.js +13 -0
  24. package/dist/commands/index.js.map +1 -0
  25. package/dist/commands/transfer/action.d.ts +18 -0
  26. package/dist/commands/transfer/action.js +161 -0
  27. package/dist/commands/transfer/action.js.map +1 -0
  28. package/dist/commands/transfer/command.d.ts +8 -0
  29. package/dist/commands/transfer/command.js +69 -0
  30. package/dist/commands/transfer/command.js.map +1 -0
  31. package/dist/engine/index.d.ts +2 -1
  32. package/dist/engine/index.js +330 -297
  33. package/dist/engine/index.js.map +1 -1
  34. package/dist/engine/validation/schemas/index.js.map +1 -1
  35. package/dist/errors/base.js +3 -0
  36. package/dist/errors/base.js.map +1 -1
  37. package/dist/file/providers/destination/index.js +51 -55
  38. package/dist/file/providers/destination/index.js.map +1 -1
  39. package/dist/file/providers/source/index.d.ts +1 -1
  40. package/dist/file/providers/source/index.js +111 -119
  41. package/dist/file/providers/source/index.js.map +1 -1
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.js +2 -1
  44. package/dist/index.js.map +1 -1
  45. package/dist/strapi/providers/local-destination/index.d.ts +4 -3
  46. package/dist/strapi/providers/local-destination/index.js +120 -125
  47. package/dist/strapi/providers/local-destination/index.js.map +1 -1
  48. package/dist/strapi/providers/local-destination/strategies/restore/configuration.d.ts +3 -2
  49. package/dist/strapi/providers/local-destination/strategies/restore/configuration.js.map +1 -1
  50. package/dist/strapi/providers/local-destination/strategies/restore/entities.d.ts +2 -2
  51. package/dist/strapi/providers/local-destination/strategies/restore/entities.js +5 -2
  52. package/dist/strapi/providers/local-destination/strategies/restore/entities.js.map +1 -1
  53. package/dist/strapi/providers/local-destination/strategies/restore/index.d.ts +2 -2
  54. package/dist/strapi/providers/local-destination/strategies/restore/index.js.map +1 -1
  55. package/dist/strapi/providers/local-destination/strategies/restore/links.d.ts +2 -1
  56. package/dist/strapi/providers/local-destination/strategies/restore/links.js.map +1 -1
  57. package/dist/strapi/providers/local-source/assets.d.ts +2 -1
  58. package/dist/strapi/providers/local-source/assets.js +1 -1
  59. package/dist/strapi/providers/local-source/assets.js.map +1 -1
  60. package/dist/strapi/providers/local-source/configuration.d.ts +2 -1
  61. package/dist/strapi/providers/local-source/configuration.js.map +1 -1
  62. package/dist/strapi/providers/local-source/entities.d.ts +2 -1
  63. package/dist/strapi/providers/local-source/entities.js.map +1 -1
  64. package/dist/strapi/providers/local-source/index.d.ts +4 -3
  65. package/dist/strapi/providers/local-source/index.js +5 -3
  66. package/dist/strapi/providers/local-source/index.js.map +1 -1
  67. package/dist/strapi/providers/local-source/links.d.ts +2 -1
  68. package/dist/strapi/providers/local-source/links.js.map +1 -1
  69. package/dist/strapi/providers/remote-destination/index.d.ts +1 -1
  70. package/dist/strapi/providers/remote-destination/index.js +95 -94
  71. package/dist/strapi/providers/remote-destination/index.js.map +1 -1
  72. package/dist/strapi/providers/remote-source/index.d.ts +1 -1
  73. package/dist/strapi/providers/remote-source/index.js +93 -93
  74. package/dist/strapi/providers/remote-source/index.js.map +1 -1
  75. package/dist/strapi/providers/utils.d.ts +2 -2
  76. package/dist/strapi/queries/entity.d.ts +2 -1
  77. package/dist/strapi/queries/entity.js +4 -4
  78. package/dist/strapi/queries/entity.js.map +1 -1
  79. package/dist/strapi/queries/link.d.ts +2 -1
  80. package/dist/strapi/queries/link.js +13 -4
  81. package/dist/strapi/queries/link.js.map +1 -1
  82. package/dist/strapi/remote/handlers/pull.js.map +1 -1
  83. package/dist/strapi/remote/handlers/push.js.map +1 -1
  84. package/dist/utils/components.d.ts +22 -0
  85. package/dist/utils/components.js +381 -0
  86. package/dist/utils/components.js.map +1 -0
  87. package/dist/utils/providers.d.ts +2 -1
  88. package/dist/utils/providers.js.map +1 -1
  89. package/dist/utils/schema.d.ts +1 -1
  90. package/dist/utils/transaction.d.ts +2 -2
  91. package/dist/utils/transaction.js.map +1 -1
  92. package/package.json +17 -10
@@ -22,18 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
- };
30
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
31
- if (kind === "m") throw new TypeError("Private method is not writable");
32
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
33
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
34
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
35
- };
36
- var _TransferEngine_instances, _TransferEngine_metadata, _TransferEngine_schema, _TransferEngine_handlers, _TransferEngine_currentStream, _TransferEngine_createStageTransformStream, _TransferEngine_updateTransferProgress, _TransferEngine_progressTracker, _TransferEngine_emitTransferUpdate, _TransferEngine_emitStageUpdate, _TransferEngine_assertStrapiVersionIntegrity, _TransferEngine_assertSchemasMatching, _TransferEngine_transferStage, _TransferEngine_resolveProviderResource, _TransferEngine_getSchemas;
37
25
  Object.defineProperty(exports, "__esModule", { value: true });
38
26
  exports.errors = exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TransferGroupPresets = exports.TRANSFER_STAGES = void 0;
39
27
  const stream_1 = require("stream");
@@ -81,36 +69,41 @@ exports.TransferGroupPresets = {
81
69
  exports.DEFAULT_VERSION_STRATEGY = 'ignore';
82
70
  exports.DEFAULT_SCHEMA_STRATEGY = 'strict';
83
71
  class TransferEngine {
72
+ sourceProvider;
73
+ destinationProvider;
74
+ options;
75
+ #metadata = {};
76
+ #schema = {};
77
+ // Progress of the current stage
78
+ progress;
79
+ diagnostics;
80
+ #handlers = {
81
+ schemaDiff: [],
82
+ errors: {},
83
+ };
84
84
  onSchemaDiff(handler) {
85
- __classPrivateFieldGet(this, _TransferEngine_handlers, "f")?.schemaDiff?.push(handler);
85
+ this.#handlers?.schemaDiff?.push(handler);
86
86
  }
87
87
  addErrorHandler(handlerName, handler) {
88
- if (!__classPrivateFieldGet(this, _TransferEngine_handlers, "f").errors[handlerName]) {
89
- __classPrivateFieldGet(this, _TransferEngine_handlers, "f").errors[handlerName] = [];
88
+ if (!this.#handlers.errors[handlerName]) {
89
+ this.#handlers.errors[handlerName] = [];
90
90
  }
91
- __classPrivateFieldGet(this, _TransferEngine_handlers, "f").errors[handlerName]?.push(handler);
91
+ this.#handlers.errors[handlerName]?.push(handler);
92
92
  }
93
93
  async attemptResolveError(error) {
94
94
  const context = {};
95
95
  if (error instanceof providers_1.ProviderTransferError && error.details?.details.code) {
96
96
  const errorCode = error.details?.details.code;
97
- if (!__classPrivateFieldGet(this, _TransferEngine_handlers, "f").errors[errorCode]) {
98
- __classPrivateFieldGet(this, _TransferEngine_handlers, "f").errors[errorCode] = [];
97
+ if (!this.#handlers.errors[errorCode]) {
98
+ this.#handlers.errors[errorCode] = [];
99
99
  }
100
- await utils.middleware.runMiddleware(context ?? {}, __classPrivateFieldGet(this, _TransferEngine_handlers, "f").errors[errorCode] ?? []);
100
+ await utils.middleware.runMiddleware(context ?? {}, this.#handlers.errors[errorCode] ?? []);
101
101
  }
102
102
  return !!context.ignore;
103
103
  }
104
+ // Save the currently open stream so that we can access it at any time
105
+ #currentStream;
104
106
  constructor(sourceProvider, destinationProvider, options) {
105
- _TransferEngine_instances.add(this);
106
- _TransferEngine_metadata.set(this, {});
107
- _TransferEngine_schema.set(this, {});
108
- _TransferEngine_handlers.set(this, {
109
- schemaDiff: [],
110
- errors: {},
111
- });
112
- // Save the currently open stream so that we can access it at any time
113
- _TransferEngine_currentStream.set(this, void 0);
114
107
  this.diagnostics = (0, diagnostic_1.createDiagnosticReporter)();
115
108
  (0, validation_1.validateProvider)('source', sourceProvider);
116
109
  (0, validation_1.validateProvider)('destination', destinationProvider);
@@ -159,6 +152,207 @@ class TransferEngine {
159
152
  details: { createdAt: new Date(), message, params },
160
153
  });
161
154
  }
155
+ /**
156
+ * Create and return a transform stream based on the given stage and options.
157
+ *
158
+ * Allowed transformations includes 'filter' and 'map'.
159
+ */
160
+ #createStageTransformStream(key, options = {}) {
161
+ const { includeGlobal = true } = options;
162
+ const { throttle } = this.options;
163
+ const { global: globalTransforms, [key]: stageTransforms } = this.options?.transforms ?? {};
164
+ let stream = new stream_1.PassThrough({ objectMode: true });
165
+ const applyTransforms = (transforms = []) => {
166
+ const chainTransforms = [];
167
+ for (const transform of transforms) {
168
+ if ('filter' in transform) {
169
+ chainTransforms.push(utils.stream.filter(transform.filter));
170
+ }
171
+ if ('map' in transform) {
172
+ chainTransforms.push(utils.stream.map(transform.map));
173
+ }
174
+ }
175
+ if (chainTransforms.length) {
176
+ stream = stream.pipe((0, stream_chain_1.chain)(chainTransforms));
177
+ }
178
+ };
179
+ if (includeGlobal) {
180
+ applyTransforms(globalTransforms);
181
+ }
182
+ if ((0, fp_1.isNumber)(throttle) && throttle > 0) {
183
+ stream = stream.pipe(new stream_1.PassThrough({
184
+ objectMode: true,
185
+ async transform(data, _encoding, callback) {
186
+ await new Promise((resolve) => {
187
+ setTimeout(resolve, throttle);
188
+ });
189
+ callback(null, data);
190
+ },
191
+ }));
192
+ }
193
+ applyTransforms(stageTransforms);
194
+ return stream;
195
+ }
196
+ /**
197
+ * Update the Engine's transfer progress data for a given stage.
198
+ *
199
+ * Providing aggregate options enable custom computation to get the size (bytes) or the aggregate key associated with the data
200
+ */
201
+ #updateTransferProgress(stage, data, aggregate) {
202
+ if (!this.progress.data[stage]) {
203
+ this.progress.data[stage] = { count: 0, bytes: 0, startTime: Date.now() };
204
+ }
205
+ const stageProgress = this.progress.data[stage];
206
+ if (!stageProgress) {
207
+ return;
208
+ }
209
+ const size = aggregate?.size?.(data) ?? JSON.stringify(data).length;
210
+ const key = aggregate?.key?.(data);
211
+ stageProgress.count += 1;
212
+ stageProgress.bytes += size;
213
+ // Handle aggregate updates if necessary
214
+ if (key) {
215
+ if (!stageProgress.aggregates) {
216
+ stageProgress.aggregates = {};
217
+ }
218
+ const { aggregates } = stageProgress;
219
+ if (!aggregates[key]) {
220
+ aggregates[key] = { count: 0, bytes: 0 };
221
+ }
222
+ aggregates[key].count += 1;
223
+ aggregates[key].bytes += size;
224
+ }
225
+ }
226
+ /**
227
+ * Create and return a PassThrough stream.
228
+ *
229
+ * Upon writing data into it, it'll update the Engine's transfer progress data and trigger stage update events.
230
+ */
231
+ #progressTracker(stage, aggregate) {
232
+ return new stream_1.PassThrough({
233
+ objectMode: true,
234
+ transform: (data, _encoding, callback) => {
235
+ this.#updateTransferProgress(stage, data, aggregate);
236
+ this.#emitStageUpdate('progress', stage);
237
+ callback(null, data);
238
+ },
239
+ });
240
+ }
241
+ /**
242
+ * Shorthand method used to trigger transfer update events to every listeners
243
+ */
244
+ #emitTransferUpdate(type, payload) {
245
+ this.progress.stream.emit(`transfer::${type}`, payload);
246
+ }
247
+ /**
248
+ * Shorthand method used to trigger stage update events to every listeners
249
+ */
250
+ #emitStageUpdate(type, transferStage) {
251
+ this.progress.stream.emit(`stage::${type}`, {
252
+ data: this.progress.data,
253
+ stage: transferStage,
254
+ });
255
+ }
256
+ /**
257
+ * Run a version check between two strapi version (source and destination) using the strategy given to the engine during initialization.
258
+ *
259
+ * If there is a mismatch, throws a validation error.
260
+ */
261
+ #assertStrapiVersionIntegrity(sourceVersion, destinationVersion) {
262
+ const strategy = this.options.versionStrategy || exports.DEFAULT_VERSION_STRATEGY;
263
+ const reject = () => {
264
+ throw new errors_1.TransferEngineValidationError(`The source and destination provide are targeting incompatible Strapi versions (using the "${strategy}" strategy). The source (${this.sourceProvider.name}) version is ${sourceVersion} and the destination (${this.destinationProvider.name}) version is ${destinationVersion}`, {
265
+ check: 'strapi.version',
266
+ strategy,
267
+ versions: { source: sourceVersion, destination: destinationVersion },
268
+ });
269
+ };
270
+ if (!sourceVersion ||
271
+ !destinationVersion ||
272
+ strategy === 'ignore' ||
273
+ destinationVersion === sourceVersion) {
274
+ return;
275
+ }
276
+ let diff;
277
+ try {
278
+ diff = (0, semver_1.diff)(sourceVersion, destinationVersion);
279
+ }
280
+ catch {
281
+ reject();
282
+ }
283
+ if (!diff) {
284
+ return;
285
+ }
286
+ const validPatch = ['prelease', 'build'];
287
+ const validMinor = [...validPatch, 'patch', 'prepatch'];
288
+ const validMajor = [...validMinor, 'minor', 'preminor'];
289
+ if (strategy === 'patch' && validPatch.includes(diff)) {
290
+ return;
291
+ }
292
+ if (strategy === 'minor' && validMinor.includes(diff)) {
293
+ return;
294
+ }
295
+ if (strategy === 'major' && validMajor.includes(diff)) {
296
+ return;
297
+ }
298
+ reject();
299
+ }
300
+ /**
301
+ * Run a check between two set of schemas (source and destination) using the strategy given to the engine during initialization.
302
+ *
303
+ * If there are differences and/or incompatibilities between source and destination schemas, then throw a validation error.
304
+ */
305
+ #assertSchemasMatching(sourceSchemas, destinationSchemas) {
306
+ const strategy = this.options.schemaStrategy || exports.DEFAULT_SCHEMA_STRATEGY;
307
+ if (strategy === 'ignore') {
308
+ return;
309
+ }
310
+ const keys = (0, fp_1.uniq)(Object.keys(sourceSchemas).concat(Object.keys(destinationSchemas)));
311
+ const diffs = {};
312
+ keys.forEach((key) => {
313
+ const sourceSchema = sourceSchemas[key];
314
+ const destinationSchema = destinationSchemas[key];
315
+ const schemaDiffs = (0, validation_1.compareSchemas)(sourceSchema, destinationSchema, strategy);
316
+ if (schemaDiffs.length) {
317
+ diffs[key] = schemaDiffs;
318
+ }
319
+ });
320
+ if (!(0, fp_1.isEmpty)(diffs)) {
321
+ const formattedDiffs = Object.entries(diffs)
322
+ .map(([uid, ctDiffs]) => {
323
+ let msg = `- ${uid}:${os_1.EOL}`;
324
+ msg += ctDiffs
325
+ .sort((a, b) => (a.kind > b.kind ? -1 : 1))
326
+ .map((diff) => {
327
+ const path = diff.path.join('.');
328
+ if (diff.kind === 'added') {
329
+ return `${path} exists in destination schema but not in source schema and the data will not be transferred.`;
330
+ }
331
+ if (diff.kind === 'deleted') {
332
+ return `${path} exists in source schema but not in destination schema and the data will not be transferred.`;
333
+ }
334
+ if (diff.kind === 'modified') {
335
+ if (diff.types[0] === diff.types[1]) {
336
+ return `Schema value changed at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
337
+ }
338
+ return `Schema has differing data types at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
339
+ }
340
+ throw new errors_1.TransferEngineValidationError(`Invalid diff found for "${uid}"`, {
341
+ check: `schema on ${uid}`,
342
+ });
343
+ })
344
+ .map((line) => ` - ${line}`)
345
+ .join(os_1.EOL);
346
+ return msg;
347
+ })
348
+ .join(os_1.EOL);
349
+ throw new errors_1.TransferEngineValidationError(`Invalid schema changes detected during integrity checks (using the ${strategy} strategy). Please find a summary of the changes below:\n${formattedDiffs}`, {
350
+ check: 'schema.changes',
351
+ strategy,
352
+ diffs,
353
+ });
354
+ }
355
+ }
162
356
  shouldSkipStage(stage) {
163
357
  const { exclude, only } = this.options;
164
358
  // schemas must always be included
@@ -167,12 +361,12 @@ class TransferEngine {
167
361
  }
168
362
  // everything is included by default unless 'only' has been set
169
363
  let included = (0, fp_1.isEmpty)(only);
170
- if (only?.length > 0) {
364
+ if (only && only.length > 0) {
171
365
  included = only.some((transferGroup) => {
172
366
  return exports.TransferGroupPresets[transferGroup][stage];
173
367
  });
174
368
  }
175
- if (exclude?.length > 0) {
369
+ if (exclude && exclude.length > 0) {
176
370
  if (included) {
177
371
  included = !exclude.some((transferGroup) => {
178
372
  return exports.TransferGroupPresets[transferGroup][stage];
@@ -181,20 +375,74 @@ class TransferEngine {
181
375
  }
182
376
  return !included;
183
377
  }
378
+ async #transferStage(options) {
379
+ const { stage, source, destination, transform, tracker } = options;
380
+ const updateEndTime = () => {
381
+ const stageData = this.progress.data[stage];
382
+ if (stageData) {
383
+ stageData.endTime = Date.now();
384
+ }
385
+ };
386
+ if (!source || !destination || this.shouldSkipStage(stage)) {
387
+ // Wait until source and destination are closed
388
+ const results = await Promise.allSettled([source, destination].map((stream) => {
389
+ // if stream is undefined or already closed, resolve immediately
390
+ if (!stream || stream.destroyed) {
391
+ return Promise.resolve();
392
+ }
393
+ // Wait until the close event is produced and then destroy the stream and resolve
394
+ return new Promise((resolve, reject) => {
395
+ stream.on('close', resolve).on('error', reject).destroy();
396
+ });
397
+ }));
398
+ results.forEach((state) => {
399
+ if (state.status === 'rejected') {
400
+ this.reportWarning(state.reason, `transfer(${stage})`);
401
+ }
402
+ });
403
+ this.#emitStageUpdate('skip', stage);
404
+ return;
405
+ }
406
+ this.#emitStageUpdate('start', stage);
407
+ await new Promise((resolve, reject) => {
408
+ let stream = source;
409
+ if (transform) {
410
+ stream = stream.pipe(transform);
411
+ }
412
+ if (tracker) {
413
+ stream = stream.pipe(tracker);
414
+ }
415
+ this.#currentStream = stream
416
+ .pipe(destination)
417
+ .on('error', (e) => {
418
+ updateEndTime();
419
+ this.#emitStageUpdate('error', stage);
420
+ this.reportError(e, 'error');
421
+ destination.destroy(e);
422
+ reject(e);
423
+ })
424
+ .on('close', () => {
425
+ this.#currentStream = undefined;
426
+ updateEndTime();
427
+ resolve();
428
+ });
429
+ });
430
+ this.#emitStageUpdate('finish', stage);
431
+ }
184
432
  // Cause an ongoing transfer to abort gracefully
185
433
  async abortTransfer() {
186
434
  const err = new errors_1.TransferEngineError('fatal', 'Transfer aborted.');
187
- if (!__classPrivateFieldGet(this, _TransferEngine_currentStream, "f")) {
435
+ if (!this.#currentStream) {
188
436
  throw err;
189
437
  }
190
- __classPrivateFieldGet(this, _TransferEngine_currentStream, "f").destroy(err);
438
+ this.#currentStream.destroy(err);
191
439
  }
192
440
  async init() {
193
441
  // Resolve providers' resource and store
194
442
  // them in the engine's internal state
195
- await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_resolveProviderResource).call(this);
443
+ await this.#resolveProviderResource();
196
444
  // Update the destination provider's source metadata
197
- const { source: sourceMetadata } = __classPrivateFieldGet(this, _TransferEngine_metadata, "f");
445
+ const { source: sourceMetadata } = this.#metadata;
198
446
  if (sourceMetadata) {
199
447
  this.destinationProvider.setMetadata?.('source', sourceMetadata);
200
448
  }
@@ -227,16 +475,38 @@ class TransferEngine {
227
475
  }
228
476
  });
229
477
  }
478
+ async #resolveProviderResource() {
479
+ const sourceMetadata = await this.sourceProvider.getMetadata();
480
+ const destinationMetadata = await this.destinationProvider.getMetadata();
481
+ if (sourceMetadata) {
482
+ this.#metadata.source = sourceMetadata;
483
+ }
484
+ if (destinationMetadata) {
485
+ this.#metadata.destination = destinationMetadata;
486
+ }
487
+ }
488
+ async #getSchemas() {
489
+ if (!this.#schema.source) {
490
+ this.#schema.source = (await this.sourceProvider.getSchemas?.());
491
+ }
492
+ if (!this.#schema.destination) {
493
+ this.#schema.destination = (await this.destinationProvider.getSchemas?.());
494
+ }
495
+ return {
496
+ sourceSchemas: this.#schema.source,
497
+ destinationSchemas: this.#schema.destination,
498
+ };
499
+ }
230
500
  async integrityCheck() {
231
501
  const sourceMetadata = await this.sourceProvider.getMetadata();
232
502
  const destinationMetadata = await this.destinationProvider.getMetadata();
233
503
  if (sourceMetadata && destinationMetadata) {
234
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_assertStrapiVersionIntegrity).call(this, sourceMetadata?.strapi?.version, destinationMetadata?.strapi?.version);
504
+ this.#assertStrapiVersionIntegrity(sourceMetadata?.strapi?.version, destinationMetadata?.strapi?.version);
235
505
  }
236
- const { sourceSchemas, destinationSchemas } = await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_getSchemas).call(this);
506
+ const { sourceSchemas, destinationSchemas } = await this.#getSchemas();
237
507
  try {
238
508
  if (sourceSchemas && destinationSchemas) {
239
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_assertSchemasMatching).call(this, sourceSchemas, destinationSchemas);
509
+ this.#assertSchemasMatching(sourceSchemas, destinationSchemas);
240
510
  }
241
511
  }
242
512
  catch (error) {
@@ -250,10 +520,10 @@ class TransferEngine {
250
520
  destination: this.destinationProvider,
251
521
  };
252
522
  // if we don't have any handlers, throw the original error
253
- if ((0, fp_1.isEmpty)(__classPrivateFieldGet(this, _TransferEngine_handlers, "f").schemaDiff)) {
523
+ if ((0, fp_1.isEmpty)(this.#handlers.schemaDiff)) {
254
524
  throw error;
255
525
  }
256
- await utils.middleware.runMiddleware(context, __classPrivateFieldGet(this, _TransferEngine_handlers, "f").schemaDiff);
526
+ await utils.middleware.runMiddleware(context, this.#handlers.schemaDiff);
257
527
  // if there are any remaining diffs that weren't ignored
258
528
  const unresolvedDiffs = utils.json.diff(context.diffs, context.ignoredDiffs);
259
529
  if (unresolvedDiffs.length) {
@@ -271,11 +541,11 @@ class TransferEngine {
271
541
  // reset data between transfers
272
542
  this.progress.data = {};
273
543
  try {
274
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'init');
544
+ this.#emitTransferUpdate('init');
275
545
  await this.bootstrap();
276
546
  await this.init();
277
547
  await this.integrityCheck();
278
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'start');
548
+ this.#emitTransferUpdate('start');
279
549
  await this.beforeTransfer();
280
550
  // Run the transfer stages
281
551
  await this.transferSchemas();
@@ -285,10 +555,10 @@ class TransferEngine {
285
555
  await this.transferConfiguration();
286
556
  // Gracefully close the providers
287
557
  await this.close();
288
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'finish');
558
+ this.#emitTransferUpdate('finish');
289
559
  }
290
560
  catch (e) {
291
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'error', { error: e });
561
+ this.#emitTransferUpdate('error', { error: e });
292
562
  const lastDiagnostic = (0, fp_1.last)(this.diagnostics.stack.items);
293
563
  // Do not report an error diagnostic if the last one reported the same error
294
564
  if (e instanceof Error &&
@@ -334,11 +604,11 @@ class TransferEngine {
334
604
  }
335
605
  const source = await this.sourceProvider.createSchemasReadStream?.();
336
606
  const destination = await this.destinationProvider.createSchemasWriteStream?.();
337
- const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
338
- const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, {
607
+ const transform = this.#createStageTransformStream(stage);
608
+ const tracker = this.#progressTracker(stage, {
339
609
  key: (value) => value.modelType,
340
610
  });
341
- await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
611
+ await this.#transferStage({ stage, source, destination, transform, tracker });
342
612
  }
343
613
  async transferEntities() {
344
614
  const stage = 'entities';
@@ -348,11 +618,11 @@ class TransferEngine {
348
618
  const source = await this.sourceProvider.createEntitiesReadStream?.();
349
619
  const destination = await this.destinationProvider.createEntitiesWriteStream?.();
350
620
  const transform = (0, stream_chain_1.chain)([
351
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage),
621
+ this.#createStageTransformStream(stage),
352
622
  new stream_1.Transform({
353
623
  objectMode: true,
354
624
  transform: async (entity, _encoding, callback) => {
355
- const { destinationSchemas: schemas } = await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_getSchemas).call(this);
625
+ const { destinationSchemas: schemas } = await this.#getSchemas();
356
626
  if (!schemas) {
357
627
  return callback(null, entity);
358
628
  }
@@ -372,8 +642,8 @@ class TransferEngine {
372
642
  },
373
643
  }),
374
644
  ]);
375
- const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, { key: (value) => value.type });
376
- await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
645
+ const tracker = this.#progressTracker(stage, { key: (value) => value.type });
646
+ await this.#transferStage({ stage, source, destination, transform, tracker });
377
647
  }
378
648
  async transferLinks() {
379
649
  const stage = 'links';
@@ -383,11 +653,11 @@ class TransferEngine {
383
653
  const source = await this.sourceProvider.createLinksReadStream?.();
384
654
  const destination = await this.destinationProvider.createLinksWriteStream?.();
385
655
  const transform = (0, stream_chain_1.chain)([
386
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage),
656
+ this.#createStageTransformStream(stage),
387
657
  new stream_1.Transform({
388
658
  objectMode: true,
389
659
  transform: async (link, _encoding, callback) => {
390
- const { destinationSchemas: schemas } = await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_getSchemas).call(this);
660
+ const { destinationSchemas: schemas } = await this.#getSchemas();
391
661
  if (!schemas) {
392
662
  return callback(null, link);
393
663
  }
@@ -401,8 +671,8 @@ class TransferEngine {
401
671
  },
402
672
  }),
403
673
  ]);
404
- const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage);
405
- await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
674
+ const tracker = this.#progressTracker(stage);
675
+ await this.#transferStage({ stage, source, destination, transform, tracker });
406
676
  }
407
677
  async transferAssets() {
408
678
  const stage = 'assets';
@@ -411,12 +681,12 @@ class TransferEngine {
411
681
  }
412
682
  const source = await this.sourceProvider.createAssetsReadStream?.();
413
683
  const destination = await this.destinationProvider.createAssetsWriteStream?.();
414
- const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
415
- const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, {
684
+ const transform = this.#createStageTransformStream(stage);
685
+ const tracker = this.#progressTracker(stage, {
416
686
  size: (value) => value.stats.size,
417
687
  key: (value) => (0, path_1.extname)(value.filename) || 'No extension',
418
688
  });
419
- await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
689
+ await this.#transferStage({ stage, source, destination, transform, tracker });
420
690
  }
421
691
  async transferConfiguration() {
422
692
  const stage = 'configuration';
@@ -425,248 +695,11 @@ class TransferEngine {
425
695
  }
426
696
  const source = await this.sourceProvider.createConfigurationReadStream?.();
427
697
  const destination = await this.destinationProvider.createConfigurationWriteStream?.();
428
- const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
429
- const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage);
430
- await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
698
+ const transform = this.#createStageTransformStream(stage);
699
+ const tracker = this.#progressTracker(stage);
700
+ await this.#transferStage({ stage, source, destination, transform, tracker });
431
701
  }
432
702
  }
433
- _TransferEngine_metadata = new WeakMap(), _TransferEngine_schema = new WeakMap(), _TransferEngine_handlers = new WeakMap(), _TransferEngine_currentStream = new WeakMap(), _TransferEngine_instances = new WeakSet(), _TransferEngine_createStageTransformStream = function _TransferEngine_createStageTransformStream(key, options = {}) {
434
- const { includeGlobal = true } = options;
435
- const { throttle } = this.options;
436
- const { global: globalTransforms, [key]: stageTransforms } = this.options?.transforms ?? {};
437
- let stream = new stream_1.PassThrough({ objectMode: true });
438
- const applyTransforms = (transforms = []) => {
439
- const chainTransforms = [];
440
- for (const transform of transforms) {
441
- if ('filter' in transform) {
442
- chainTransforms.push(utils.stream.filter(transform.filter));
443
- }
444
- if ('map' in transform) {
445
- chainTransforms.push(utils.stream.map(transform.map));
446
- }
447
- }
448
- if (chainTransforms.length) {
449
- stream = stream.pipe((0, stream_chain_1.chain)(chainTransforms));
450
- }
451
- };
452
- if (includeGlobal) {
453
- applyTransforms(globalTransforms);
454
- }
455
- if ((0, fp_1.isNumber)(throttle) && throttle > 0) {
456
- stream = stream.pipe(new stream_1.PassThrough({
457
- objectMode: true,
458
- async transform(data, _encoding, callback) {
459
- await new Promise((resolve) => {
460
- setTimeout(resolve, throttle);
461
- });
462
- callback(null, data);
463
- },
464
- }));
465
- }
466
- applyTransforms(stageTransforms);
467
- return stream;
468
- }, _TransferEngine_updateTransferProgress = function _TransferEngine_updateTransferProgress(stage, data, aggregate) {
469
- if (!this.progress.data[stage]) {
470
- this.progress.data[stage] = { count: 0, bytes: 0, startTime: Date.now() };
471
- }
472
- const stageProgress = this.progress.data[stage];
473
- if (!stageProgress) {
474
- return;
475
- }
476
- const size = aggregate?.size?.(data) ?? JSON.stringify(data).length;
477
- const key = aggregate?.key?.(data);
478
- stageProgress.count += 1;
479
- stageProgress.bytes += size;
480
- // Handle aggregate updates if necessary
481
- if (key) {
482
- if (!stageProgress.aggregates) {
483
- stageProgress.aggregates = {};
484
- }
485
- const { aggregates } = stageProgress;
486
- if (!aggregates[key]) {
487
- aggregates[key] = { count: 0, bytes: 0 };
488
- }
489
- aggregates[key].count += 1;
490
- aggregates[key].bytes += size;
491
- }
492
- }, _TransferEngine_progressTracker = function _TransferEngine_progressTracker(stage, aggregate) {
493
- return new stream_1.PassThrough({
494
- objectMode: true,
495
- transform: (data, _encoding, callback) => {
496
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_updateTransferProgress).call(this, stage, data, aggregate);
497
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'progress', stage);
498
- callback(null, data);
499
- },
500
- });
501
- }, _TransferEngine_emitTransferUpdate = function _TransferEngine_emitTransferUpdate(type, payload) {
502
- this.progress.stream.emit(`transfer::${type}`, payload);
503
- }, _TransferEngine_emitStageUpdate = function _TransferEngine_emitStageUpdate(type, transferStage) {
504
- this.progress.stream.emit(`stage::${type}`, {
505
- data: this.progress.data,
506
- stage: transferStage,
507
- });
508
- }, _TransferEngine_assertStrapiVersionIntegrity = function _TransferEngine_assertStrapiVersionIntegrity(sourceVersion, destinationVersion) {
509
- const strategy = this.options.versionStrategy || exports.DEFAULT_VERSION_STRATEGY;
510
- const reject = () => {
511
- throw new errors_1.TransferEngineValidationError(`The source and destination provide are targeting incompatible Strapi versions (using the "${strategy}" strategy). The source (${this.sourceProvider.name}) version is ${sourceVersion} and the destination (${this.destinationProvider.name}) version is ${destinationVersion}`, {
512
- check: 'strapi.version',
513
- strategy,
514
- versions: { source: sourceVersion, destination: destinationVersion },
515
- });
516
- };
517
- if (!sourceVersion ||
518
- !destinationVersion ||
519
- strategy === 'ignore' ||
520
- destinationVersion === sourceVersion) {
521
- return;
522
- }
523
- let diff;
524
- try {
525
- diff = (0, semver_1.diff)(sourceVersion, destinationVersion);
526
- }
527
- catch {
528
- reject();
529
- }
530
- if (!diff) {
531
- return;
532
- }
533
- const validPatch = ['prelease', 'build'];
534
- const validMinor = [...validPatch, 'patch', 'prepatch'];
535
- const validMajor = [...validMinor, 'minor', 'preminor'];
536
- if (strategy === 'patch' && validPatch.includes(diff)) {
537
- return;
538
- }
539
- if (strategy === 'minor' && validMinor.includes(diff)) {
540
- return;
541
- }
542
- if (strategy === 'major' && validMajor.includes(diff)) {
543
- return;
544
- }
545
- reject();
546
- }, _TransferEngine_assertSchemasMatching = function _TransferEngine_assertSchemasMatching(sourceSchemas, destinationSchemas) {
547
- const strategy = this.options.schemaStrategy || exports.DEFAULT_SCHEMA_STRATEGY;
548
- if (strategy === 'ignore') {
549
- return;
550
- }
551
- const keys = (0, fp_1.uniq)(Object.keys(sourceSchemas).concat(Object.keys(destinationSchemas)));
552
- const diffs = {};
553
- keys.forEach((key) => {
554
- const sourceSchema = sourceSchemas[key];
555
- const destinationSchema = destinationSchemas[key];
556
- const schemaDiffs = (0, validation_1.compareSchemas)(sourceSchema, destinationSchema, strategy);
557
- if (schemaDiffs.length) {
558
- diffs[key] = schemaDiffs;
559
- }
560
- });
561
- if (!(0, fp_1.isEmpty)(diffs)) {
562
- const formattedDiffs = Object.entries(diffs)
563
- .map(([uid, ctDiffs]) => {
564
- let msg = `- ${uid}:${os_1.EOL}`;
565
- msg += ctDiffs
566
- .sort((a, b) => (a.kind > b.kind ? -1 : 1))
567
- .map((diff) => {
568
- const path = diff.path.join('.');
569
- if (diff.kind === 'added') {
570
- return `${path} exists in destination schema but not in source schema and the data will not be transferred.`;
571
- }
572
- if (diff.kind === 'deleted') {
573
- return `${path} exists in source schema but not in destination schema and the data will not be transferred.`;
574
- }
575
- if (diff.kind === 'modified') {
576
- if (diff.types[0] === diff.types[1]) {
577
- return `Schema value changed at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
578
- }
579
- return `Schema has differing data types at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
580
- }
581
- throw new errors_1.TransferEngineValidationError(`Invalid diff found for "${uid}"`, {
582
- check: `schema on ${uid}`,
583
- });
584
- })
585
- .map((line) => ` - ${line}`)
586
- .join(os_1.EOL);
587
- return msg;
588
- })
589
- .join(os_1.EOL);
590
- throw new errors_1.TransferEngineValidationError(`Invalid schema changes detected during integrity checks (using the ${strategy} strategy). Please find a summary of the changes below:\n${formattedDiffs}`, {
591
- check: 'schema.changes',
592
- strategy,
593
- diffs,
594
- });
595
- }
596
- }, _TransferEngine_transferStage = async function _TransferEngine_transferStage(options) {
597
- const { stage, source, destination, transform, tracker } = options;
598
- const updateEndTime = () => {
599
- const stageData = this.progress.data[stage];
600
- if (stageData) {
601
- stageData.endTime = Date.now();
602
- }
603
- };
604
- if (!source || !destination || this.shouldSkipStage(stage)) {
605
- // Wait until source and destination are closed
606
- const results = await Promise.allSettled([source, destination].map((stream) => {
607
- // if stream is undefined or already closed, resolve immediately
608
- if (!stream || stream.destroyed) {
609
- return Promise.resolve();
610
- }
611
- // Wait until the close event is produced and then destroy the stream and resolve
612
- return new Promise((resolve, reject) => {
613
- stream.on('close', resolve).on('error', reject).destroy();
614
- });
615
- }));
616
- results.forEach((state) => {
617
- if (state.status === 'rejected') {
618
- this.reportWarning(state.reason, `transfer(${stage})`);
619
- }
620
- });
621
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'skip', stage);
622
- return;
623
- }
624
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'start', stage);
625
- await new Promise((resolve, reject) => {
626
- let stream = source;
627
- if (transform) {
628
- stream = stream.pipe(transform);
629
- }
630
- if (tracker) {
631
- stream = stream.pipe(tracker);
632
- }
633
- __classPrivateFieldSet(this, _TransferEngine_currentStream, stream
634
- .pipe(destination)
635
- .on('error', (e) => {
636
- updateEndTime();
637
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'error', stage);
638
- this.reportError(e, 'error');
639
- destination.destroy(e);
640
- reject(e);
641
- })
642
- .on('close', () => {
643
- __classPrivateFieldSet(this, _TransferEngine_currentStream, undefined, "f");
644
- updateEndTime();
645
- resolve();
646
- }), "f");
647
- });
648
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'finish', stage);
649
- }, _TransferEngine_resolveProviderResource = async function _TransferEngine_resolveProviderResource() {
650
- const sourceMetadata = await this.sourceProvider.getMetadata();
651
- const destinationMetadata = await this.destinationProvider.getMetadata();
652
- if (sourceMetadata) {
653
- __classPrivateFieldGet(this, _TransferEngine_metadata, "f").source = sourceMetadata;
654
- }
655
- if (destinationMetadata) {
656
- __classPrivateFieldGet(this, _TransferEngine_metadata, "f").destination = destinationMetadata;
657
- }
658
- }, _TransferEngine_getSchemas = async function _TransferEngine_getSchemas() {
659
- if (!__classPrivateFieldGet(this, _TransferEngine_schema, "f").source) {
660
- __classPrivateFieldGet(this, _TransferEngine_schema, "f").source = (await this.sourceProvider.getSchemas?.());
661
- }
662
- if (!__classPrivateFieldGet(this, _TransferEngine_schema, "f").destination) {
663
- __classPrivateFieldGet(this, _TransferEngine_schema, "f").destination = (await this.destinationProvider.getSchemas?.());
664
- }
665
- return {
666
- sourceSchemas: __classPrivateFieldGet(this, _TransferEngine_schema, "f").source,
667
- destinationSchemas: __classPrivateFieldGet(this, _TransferEngine_schema, "f").destination,
668
- };
669
- };
670
703
  const createTransferEngine = (sourceProvider, destinationProvider, options) => {
671
704
  return new TransferEngine(sourceProvider, destinationProvider, options);
672
705
  };