@strapi/data-transfer 4.6.0-beta.2 → 4.6.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.
Files changed (43) hide show
  1. package/lib/engine/diagnostic.d.ts +40 -0
  2. package/lib/engine/diagnostic.js +50 -0
  3. package/lib/engine/errors.d.ts +28 -0
  4. package/lib/engine/errors.js +29 -0
  5. package/lib/engine/index.d.ts +11 -3
  6. package/lib/engine/index.js +143 -30
  7. package/lib/engine/validation/index.d.ts +2 -1
  8. package/lib/engine/validation/index.js +4 -13
  9. package/lib/engine/validation/provider.d.ts +3 -0
  10. package/lib/engine/validation/provider.js +18 -0
  11. package/lib/errors/base.d.ts +8 -0
  12. package/lib/errors/base.js +13 -0
  13. package/lib/errors/constants.d.ts +3 -0
  14. package/lib/errors/constants.js +9 -0
  15. package/lib/errors/index.d.ts +2 -0
  16. package/lib/errors/index.js +19 -0
  17. package/lib/errors/providers.d.ts +21 -0
  18. package/lib/errors/providers.js +32 -0
  19. package/lib/file/providers/source/index.js +29 -14
  20. package/lib/strapi/providers/local-destination/index.d.ts +3 -1
  21. package/lib/strapi/providers/local-destination/index.js +53 -33
  22. package/lib/strapi/providers/local-destination/strategies/restore/configuration.d.ts +2 -2
  23. package/lib/strapi/providers/local-destination/strategies/restore/configuration.js +17 -10
  24. package/lib/strapi/providers/local-destination/strategies/restore/entities.d.ts +2 -0
  25. package/lib/strapi/providers/local-destination/strategies/restore/entities.js +57 -54
  26. package/lib/strapi/providers/local-destination/strategies/restore/index.js +2 -1
  27. package/lib/strapi/providers/local-destination/strategies/restore/links.d.ts +2 -1
  28. package/lib/strapi/providers/local-destination/strategies/restore/links.js +18 -15
  29. package/lib/strapi/providers/local-source/index.js +6 -21
  30. package/lib/strapi/providers/remote-destination/index.js +21 -6
  31. package/lib/strapi/queries/link.d.ts +1 -1
  32. package/lib/strapi/queries/link.js +17 -3
  33. package/lib/strapi/remote/constants.d.ts +1 -0
  34. package/lib/strapi/remote/constants.js +2 -1
  35. package/lib/strapi/remote/handlers.js +28 -12
  36. package/lib/utils/index.d.ts +1 -0
  37. package/lib/utils/index.js +2 -1
  38. package/lib/utils/json.js +6 -6
  39. package/lib/utils/providers.d.ts +2 -0
  40. package/lib/utils/providers.js +11 -0
  41. package/lib/utils/transaction.d.ts +3 -0
  42. package/lib/utils/transaction.js +70 -0
  43. package/package.json +7 -6
@@ -0,0 +1,40 @@
1
+ export interface IDiagnosticReporterOptions {
2
+ stackSize?: number;
3
+ }
4
+ export declare type GenericDiagnostic<K extends DiagnosticKind, T = unknown> = {
5
+ kind: K;
6
+ details: {
7
+ message: string;
8
+ createdAt: Date;
9
+ } & T;
10
+ };
11
+ export declare type DiagnosticKind = 'error' | 'warning' | 'info';
12
+ export declare type DiagnosticListener<T extends DiagnosticKind = DiagnosticKind> = (diagnostic: {
13
+ kind: T;
14
+ } & Diagnostic extends infer U ? U : 'foo') => void | Promise<void>;
15
+ export declare type DiagnosticEvent = 'diagnostic' | `diagnostic.${DiagnosticKind}`;
16
+ export declare type GetEventListener<E extends DiagnosticEvent> = E extends 'diagnostic' ? DiagnosticListener : E extends `diagnostic.${infer K}` ? K extends DiagnosticKind ? DiagnosticListener<K> : never : never;
17
+ export declare type Diagnostic = ErrorDiagnostic | WarningDiagnostic | InfoDiagnostic;
18
+ export declare type ErrorDiagnosticSeverity = 'fatal' | 'error' | 'silly';
19
+ export declare type ErrorDiagnostic = GenericDiagnostic<'error', {
20
+ name: string;
21
+ severity: ErrorDiagnosticSeverity;
22
+ error: Error;
23
+ }>;
24
+ export declare type WarningDiagnostic = GenericDiagnostic<'warning', {
25
+ origin?: string;
26
+ }>;
27
+ export declare type InfoDiagnostic<T = unknown> = GenericDiagnostic<'info', {
28
+ params?: T;
29
+ }>;
30
+ export interface IDiagnosticReporter {
31
+ stack: {
32
+ readonly size: number;
33
+ readonly items: Diagnostic[];
34
+ };
35
+ report(diagnostic: Diagnostic): IDiagnosticReporter;
36
+ onDiagnostic(listener: DiagnosticListener): IDiagnosticReporter;
37
+ on<T extends DiagnosticKind>(kind: T, listener: DiagnosticListener<T>): IDiagnosticReporter;
38
+ }
39
+ declare const createDiagnosticReporter: (options?: IDiagnosticReporterOptions) => IDiagnosticReporter;
40
+ export { createDiagnosticReporter };
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDiagnosticReporter = void 0;
4
+ const events_1 = require("events");
5
+ const createDiagnosticReporter = (options = {}) => {
6
+ const { stackSize = -1 } = options;
7
+ const emitter = new events_1.EventEmitter();
8
+ const stack = [];
9
+ const addListener = (event, listener) => {
10
+ emitter.on(event, listener);
11
+ };
12
+ const isDiagnosticValid = (diagnostic) => {
13
+ if (!diagnostic.kind || !diagnostic.details || !diagnostic.details.message) {
14
+ return false;
15
+ }
16
+ return true;
17
+ };
18
+ return {
19
+ stack: {
20
+ get size() {
21
+ return stack.length;
22
+ },
23
+ get items() {
24
+ return stack;
25
+ },
26
+ },
27
+ report(diagnostic) {
28
+ if (!isDiagnosticValid(diagnostic)) {
29
+ return this;
30
+ }
31
+ emitter.emit('diagnostic', diagnostic);
32
+ emitter.emit(`diagnostic.${diagnostic.kind}`, diagnostic);
33
+ if (stackSize !== -1 && stack.length >= stackSize) {
34
+ stack.shift();
35
+ }
36
+ stack.push(diagnostic);
37
+ return this;
38
+ },
39
+ onDiagnostic(listener) {
40
+ addListener('diagnostic', listener);
41
+ return this;
42
+ },
43
+ on(kind, listener) {
44
+ addListener(`diagnostic.${kind}`, listener);
45
+ return this;
46
+ },
47
+ };
48
+ };
49
+ exports.createDiagnosticReporter = createDiagnosticReporter;
50
+ //# sourceMappingURL=diagnostic.js.map
@@ -0,0 +1,28 @@
1
+ import { DataTransferError, Severity } from '../errors';
2
+ declare type TransferEngineStep = 'initialization' | 'validation' | 'transfer';
3
+ declare type TransferEngineErrorDetails<P extends TransferEngineStep = TransferEngineStep, U = never> = {
4
+ step: P;
5
+ } & ([U] extends [never] ? unknown : {
6
+ details?: U;
7
+ });
8
+ declare class TransferEngineError<P extends TransferEngineStep = TransferEngineStep, U = never, T extends TransferEngineErrorDetails<P, U> = TransferEngineErrorDetails<P, U>> extends DataTransferError<T> {
9
+ constructor(severity: Severity, message?: string, details?: T | null);
10
+ }
11
+ declare class TransferEngineInitializationError extends TransferEngineError<'initialization'> {
12
+ constructor(message?: string);
13
+ }
14
+ declare class TransferEngineValidationError<T extends {
15
+ check: string;
16
+ } = {
17
+ check: string;
18
+ }> extends TransferEngineError<'validation', T> {
19
+ constructor(message?: string, details?: T);
20
+ }
21
+ declare class TransferEngineTransferError<T extends {
22
+ check: string;
23
+ } = {
24
+ check: string;
25
+ }> extends TransferEngineError<'transfer', T> {
26
+ constructor(message?: string, details?: T);
27
+ }
28
+ export { TransferEngineError, TransferEngineInitializationError, TransferEngineValidationError, TransferEngineTransferError, };
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransferEngineTransferError = exports.TransferEngineValidationError = exports.TransferEngineInitializationError = exports.TransferEngineError = void 0;
4
+ const errors_1 = require("../errors");
5
+ class TransferEngineError extends errors_1.DataTransferError {
6
+ constructor(severity, message, details) {
7
+ super('engine', severity, message, details);
8
+ }
9
+ }
10
+ exports.TransferEngineError = TransferEngineError;
11
+ class TransferEngineInitializationError extends TransferEngineError {
12
+ constructor(message) {
13
+ super(errors_1.SeverityKind.FATAL, message, { step: 'initialization' });
14
+ }
15
+ }
16
+ exports.TransferEngineInitializationError = TransferEngineInitializationError;
17
+ class TransferEngineValidationError extends TransferEngineError {
18
+ constructor(message, details) {
19
+ super(errors_1.SeverityKind.FATAL, message, { step: 'validation', details });
20
+ }
21
+ }
22
+ exports.TransferEngineValidationError = TransferEngineValidationError;
23
+ class TransferEngineTransferError extends TransferEngineError {
24
+ constructor(message, details) {
25
+ super(errors_1.SeverityKind.FATAL, message, { step: 'transfer', details });
26
+ }
27
+ }
28
+ exports.TransferEngineTransferError = TransferEngineTransferError;
29
+ //# sourceMappingURL=errors.js.map
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { PassThrough } from 'stream';
3
3
  import type { IDestinationProvider, ISourceProvider, ITransferEngine, ITransferEngineOptions, TransferProgress, ITransferResults, TransferStage, TransferFilters, TransferFilterPreset } from '../../types';
4
+ import { IDiagnosticReporter } from './diagnostic';
4
5
  export declare const TRANSFER_STAGES: ReadonlyArray<TransferStage>;
5
6
  export declare type TransferGroupFilter = Record<TransferFilterPreset, TransferFilters>;
6
7
  /**
@@ -18,12 +19,19 @@ declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D exte
18
19
  data: TransferProgress;
19
20
  stream: PassThrough;
20
21
  };
21
- constructor(sourceProvider: ISourceProvider, destinationProvider: IDestinationProvider, options: ITransferEngineOptions);
22
+ diagnostics: IDiagnosticReporter;
23
+ constructor(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions);
22
24
  shouldSkipStage(stage: TransferStage): boolean;
23
25
  init(): Promise<void>;
26
+ /**
27
+ * Run the bootstrap method in both source and destination providers
28
+ */
24
29
  bootstrap(): Promise<void>;
30
+ /**
31
+ * Run the close method in both source and destination providers
32
+ */
25
33
  close(): Promise<void>;
26
- integrityCheck(): Promise<boolean>;
34
+ integrityCheck(): Promise<void>;
27
35
  transfer(): Promise<ITransferResults<S, D>>;
28
36
  beforeTransfer(): Promise<void>;
29
37
  transferSchemas(): Promise<void>;
@@ -32,5 +40,5 @@ declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D exte
32
40
  transferAssets(): Promise<void>;
33
41
  transferConfiguration(): Promise<void>;
34
42
  }
35
- export declare const createTransferEngine: <S extends ISourceProvider = ISourceProvider, D extends IDestinationProvider = IDestinationProvider>(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions) => TransferEngine<S, D>;
43
+ export declare const createTransferEngine: <S extends ISourceProvider, D extends IDestinationProvider>(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions) => TransferEngine<S, D>;
36
44
  export {};
@@ -4,15 +4,18 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  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");
5
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
6
  };
7
- var _TransferEngine_instances, _TransferEngine_metadata, _TransferEngine_createStageTransformStream, _TransferEngine_updateTransferProgress, _TransferEngine_progressTracker, _TransferEngine_emitTransferUpdate, _TransferEngine_emitStageUpdate, _TransferEngine_assertStrapiVersionIntegrity, _TransferEngine_assertSchemasMatching, _TransferEngine_transferStage, _TransferEngine_resolveProviderResource;
7
+ var _TransferEngine_instances, _TransferEngine_metadata, _TransferEngine_panic, _TransferEngine_reportError, _TransferEngine_reportWarning, _TransferEngine_reportInfo, _TransferEngine_createStageTransformStream, _TransferEngine_updateTransferProgress, _TransferEngine_progressTracker, _TransferEngine_emitTransferUpdate, _TransferEngine_emitStageUpdate, _TransferEngine_assertStrapiVersionIntegrity, _TransferEngine_assertSchemasMatching, _TransferEngine_transferStage, _TransferEngine_resolveProviderResource;
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TransferGroupPresets = exports.TRANSFER_STAGES = void 0;
10
10
  const stream_1 = require("stream");
11
11
  const path_1 = require("path");
12
+ const os_1 = require("os");
12
13
  const fp_1 = require("lodash/fp");
13
14
  const semver_1 = require("semver");
14
- const schemas_1 = require("./validation/schemas");
15
+ const validation_1 = require("./validation");
15
16
  const stream_2 = require("../utils/stream");
17
+ const errors_1 = require("./errors");
18
+ const diagnostic_1 = require("./diagnostic");
16
19
  exports.TRANSFER_STAGES = Object.freeze([
17
20
  'entities',
18
21
  'links',
@@ -51,12 +54,9 @@ class TransferEngine {
51
54
  constructor(sourceProvider, destinationProvider, options) {
52
55
  _TransferEngine_instances.add(this);
53
56
  _TransferEngine_metadata.set(this, {});
54
- if (sourceProvider.type !== 'source') {
55
- throw new Error("SourceProvider does not have type 'source'");
56
- }
57
- if (destinationProvider.type !== 'destination') {
58
- throw new Error("DestinationProvider does not have type 'destination'");
59
- }
57
+ this.diagnostics = (0, diagnostic_1.createDiagnosticReporter)();
58
+ (0, validation_1.validateProvider)('source', sourceProvider);
59
+ (0, validation_1.validateProvider)('destination', destinationProvider);
60
60
  this.sourceProvider = sourceProvider;
61
61
  this.destinationProvider = destinationProvider;
62
62
  this.options = options;
@@ -94,11 +94,33 @@ class TransferEngine {
94
94
  this.destinationProvider.setMetadata?.('source', sourceMetadata);
95
95
  }
96
96
  }
97
+ /**
98
+ * Run the bootstrap method in both source and destination providers
99
+ */
97
100
  async bootstrap() {
98
- await Promise.all([this.sourceProvider.bootstrap?.(), this.destinationProvider.bootstrap?.()]);
101
+ const results = await Promise.allSettled([
102
+ this.sourceProvider.bootstrap?.(),
103
+ this.destinationProvider.bootstrap?.(),
104
+ ]);
105
+ results.forEach((result) => {
106
+ if (result.status === 'rejected') {
107
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_panic).call(this, result.reason);
108
+ }
109
+ });
99
110
  }
111
+ /**
112
+ * Run the close method in both source and destination providers
113
+ */
100
114
  async close() {
101
- await Promise.all([this.sourceProvider.close?.(), this.destinationProvider.close?.()]);
115
+ const results = await Promise.allSettled([
116
+ this.sourceProvider.close?.(),
117
+ this.destinationProvider.close?.(),
118
+ ]);
119
+ results.forEach((result) => {
120
+ if (result.status === 'rejected') {
121
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_panic).call(this, result.reason);
122
+ }
123
+ });
102
124
  }
103
125
  async integrityCheck() {
104
126
  try {
@@ -112,10 +134,12 @@ class TransferEngine {
112
134
  if (sourceSchemas && destinationSchemas) {
113
135
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_assertSchemasMatching).call(this, sourceSchemas, destinationSchemas);
114
136
  }
115
- return true;
116
137
  }
117
138
  catch (error) {
118
- return false;
139
+ if (error instanceof Error) {
140
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_panic).call(this, error);
141
+ }
142
+ throw error;
119
143
  }
120
144
  }
121
145
  async transfer() {
@@ -125,11 +149,7 @@ class TransferEngine {
125
149
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'init');
126
150
  await this.bootstrap();
127
151
  await this.init();
128
- const isValidTransfer = await this.integrityCheck();
129
- if (!isValidTransfer) {
130
- // TODO: provide the log from the integrity check
131
- throw new Error(`Unable to transfer the data between ${this.sourceProvider.name} and ${this.destinationProvider.name}.\nPlease refer to the log above for more information.`);
132
- }
152
+ await this.integrityCheck();
133
153
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'start');
134
154
  await this.beforeTransfer();
135
155
  // Run the transfer stages
@@ -144,6 +164,12 @@ class TransferEngine {
144
164
  }
145
165
  catch (e) {
146
166
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'error', { error: e });
167
+ const lastDiagnostic = (0, fp_1.last)(this.diagnostics.stack.items);
168
+ // Do not report an error diagnostic if the last one reported the same error
169
+ if (e instanceof Error &&
170
+ (!lastDiagnostic || lastDiagnostic.kind !== 'error' || lastDiagnostic.details.error !== e)) {
171
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, e, e.severity || 'fatal');
172
+ }
147
173
  // Rollback the destination provider if an exception is thrown during the transfer
148
174
  // Note: This will be configurable in the future
149
175
  await this.destinationProvider.rollback?.(e);
@@ -156,8 +182,22 @@ class TransferEngine {
156
182
  };
157
183
  }
158
184
  async beforeTransfer() {
159
- await this.sourceProvider.beforeTransfer?.();
160
- await this.destinationProvider.beforeTransfer?.();
185
+ const runWithDiagnostic = async (provider) => {
186
+ try {
187
+ await provider.beforeTransfer?.();
188
+ }
189
+ catch (error) {
190
+ // Error happening during the before transfer step should be considered fatal errors
191
+ if (error instanceof Error) {
192
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_panic).call(this, error);
193
+ }
194
+ else {
195
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_panic).call(this, new Error(`Unknwon error when executing "beforeTransfer" on the ${origin} provider`));
196
+ }
197
+ }
198
+ };
199
+ await runWithDiagnostic(this.sourceProvider);
200
+ await runWithDiagnostic(this.destinationProvider);
161
201
  }
162
202
  async transferSchemas() {
163
203
  const stage = 'schemas';
@@ -190,7 +230,7 @@ class TransferEngine {
190
230
  const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
191
231
  const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, {
192
232
  size: (value) => value.stats.size,
193
- key: (value) => (0, path_1.extname)(value.filename),
233
+ key: (value) => (0, path_1.extname)(value.filename) ?? 'NA',
194
234
  });
195
235
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
196
236
  }
@@ -203,7 +243,31 @@ class TransferEngine {
203
243
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
204
244
  }
205
245
  }
206
- _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSet(), _TransferEngine_createStageTransformStream = function _TransferEngine_createStageTransformStream(key, options = {}) {
246
+ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSet(), _TransferEngine_panic = function _TransferEngine_panic(error) {
247
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, error, 'fatal');
248
+ throw error;
249
+ }, _TransferEngine_reportError = function _TransferEngine_reportError(error, severity) {
250
+ this.diagnostics.report({
251
+ kind: 'error',
252
+ details: {
253
+ severity,
254
+ createdAt: new Date(),
255
+ name: error.name,
256
+ message: error.message,
257
+ error,
258
+ },
259
+ });
260
+ }, _TransferEngine_reportWarning = function _TransferEngine_reportWarning(message, origin) {
261
+ this.diagnostics.report({
262
+ kind: 'warning',
263
+ details: { createdAt: new Date(), message, origin },
264
+ });
265
+ }, _TransferEngine_reportInfo = function _TransferEngine_reportInfo(message, params) {
266
+ this.diagnostics.report({
267
+ kind: 'info',
268
+ details: { createdAt: new Date(), message, params },
269
+ });
270
+ }, _TransferEngine_createStageTransformStream = function _TransferEngine_createStageTransformStream(key, options = {}) {
207
271
  const { includeGlobal = true } = options;
208
272
  const { global: globalTransforms, [key]: stageTransforms } = this.options?.transforms ?? {};
209
273
  let stream = new stream_1.PassThrough({ objectMode: true });
@@ -264,6 +328,13 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
264
328
  });
265
329
  }, _TransferEngine_assertStrapiVersionIntegrity = function _TransferEngine_assertStrapiVersionIntegrity(sourceVersion, destinationVersion) {
266
330
  const strategy = this.options.versionStrategy || exports.DEFAULT_VERSION_STRATEGY;
331
+ const reject = () => {
332
+ 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}`, {
333
+ check: 'strapi.version',
334
+ strategy,
335
+ versions: { source: sourceVersion, destination: destinationVersion },
336
+ });
337
+ };
267
338
  if (!sourceVersion ||
268
339
  !destinationVersion ||
269
340
  strategy === 'ignore' ||
@@ -274,8 +345,8 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
274
345
  try {
275
346
  diff = (0, semver_1.diff)(sourceVersion, destinationVersion);
276
347
  }
277
- catch (e) {
278
- throw new Error(`Strapi versions doesn't match (${strategy} check): ${sourceVersion} does not match with ${destinationVersion}`);
348
+ catch {
349
+ reject();
279
350
  }
280
351
  if (!diff) {
281
352
  return;
@@ -292,7 +363,7 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
292
363
  if (strategy === 'major' && validMajor.includes(diff)) {
293
364
  return;
294
365
  }
295
- throw new Error(`Strapi versions doesn't match (${strategy} check): ${sourceVersion} does not match with ${destinationVersion}`);
366
+ reject();
296
367
  }, _TransferEngine_assertSchemasMatching = function _TransferEngine_assertSchemasMatching(sourceSchemas, destinationSchemas) {
297
368
  const strategy = this.options.schemaStrategy || exports.DEFAULT_SCHEMA_STRATEGY;
298
369
  if (strategy === 'ignore') {
@@ -303,21 +374,51 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
303
374
  keys.forEach((key) => {
304
375
  const sourceSchema = sourceSchemas[key];
305
376
  const destinationSchema = destinationSchemas[key];
306
- const schemaDiffs = (0, schemas_1.compareSchemas)(sourceSchema, destinationSchema, strategy);
377
+ const schemaDiffs = (0, validation_1.compareSchemas)(sourceSchema, destinationSchema, strategy);
307
378
  if (schemaDiffs.length) {
308
379
  diffs[key] = schemaDiffs;
309
380
  }
310
381
  });
311
382
  if (!(0, fp_1.isEmpty)(diffs)) {
312
- throw new Error(`Import process failed because the project doesn't have a matching data structure
313
- ${JSON.stringify(diffs, null, 2)}
314
- `);
383
+ const formattedDiffs = Object.entries(diffs)
384
+ .map(([uid, ctDiffs]) => {
385
+ let msg = `- ${uid}:${os_1.EOL}`;
386
+ msg += ctDiffs
387
+ .sort((a, b) => (a.kind > b.kind ? -1 : 1))
388
+ .map((diff) => {
389
+ const path = diff.path.join('.');
390
+ if (diff.kind === 'added') {
391
+ return `${path} exists in destination schema but not in source schema`;
392
+ }
393
+ if (diff.kind === 'deleted') {
394
+ return `${path} exists in source schema but not in destination schema`;
395
+ }
396
+ if (diff.kind === 'modified') {
397
+ if (diff.types[0] === diff.types[1]) {
398
+ return `Schema value changed at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
399
+ }
400
+ return `Schema has differing data types at "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
401
+ }
402
+ throw new errors_1.TransferEngineValidationError(`Invalid diff found for "${uid}"`, {
403
+ check: `schema on ${uid}`,
404
+ });
405
+ })
406
+ .map((line) => ` - ${line}`)
407
+ .join(os_1.EOL);
408
+ return msg;
409
+ })
410
+ .join(os_1.EOL);
411
+ 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}`, {
412
+ check: 'schema.changes',
413
+ strategy,
414
+ diffs,
415
+ });
315
416
  }
316
417
  }, _TransferEngine_transferStage = async function _TransferEngine_transferStage(options) {
317
418
  const { stage, source, destination, transform, tracker } = options;
318
419
  if (!source || !destination || this.shouldSkipStage(stage)) {
319
420
  // Wait until source and destination are closed
320
- await Promise.allSettled([source, destination].map((stream) => {
421
+ const results = await Promise.allSettled([source, destination].map((stream) => {
321
422
  // if stream is undefined or already closed, resolve immediately
322
423
  if (!stream || stream.destroyed) {
323
424
  return Promise.resolve();
@@ -327,6 +428,11 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
327
428
  stream.on('close', resolve).on('error', reject).destroy();
328
429
  });
329
430
  }));
431
+ results.forEach((state) => {
432
+ if (state.status === 'rejected') {
433
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportWarning).call(this, state.reason, `transfer(${stage})`);
434
+ }
435
+ });
330
436
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'skip', stage);
331
437
  return;
332
438
  }
@@ -339,7 +445,14 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
339
445
  if (tracker) {
340
446
  stream = stream.pipe(tracker);
341
447
  }
342
- stream.pipe(destination).on('error', reject).on('close', resolve);
448
+ stream
449
+ .pipe(destination)
450
+ .on('error', (e) => {
451
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, e, 'error');
452
+ destination.destroy(e);
453
+ reject(e);
454
+ })
455
+ .on('close', resolve);
343
456
  });
344
457
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'finish', stage);
345
458
  }, _TransferEngine_resolveProviderResource = async function _TransferEngine_resolveProviderResource() {
@@ -1 +1,2 @@
1
- export * as schemas from './schemas';
1
+ export * from './schemas';
2
+ export * from './provider';
@@ -10,19 +10,10 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
24
15
  };
25
16
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.schemas = void 0;
27
- exports.schemas = __importStar(require("./schemas"));
17
+ __exportStar(require("./schemas"), exports);
18
+ __exportStar(require("./provider"), exports);
28
19
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import type { IDestinationProvider, ISourceProvider, ProviderType } from '../../../types';
2
+ declare const validateProvider: <T extends ProviderType>(type: ProviderType, provider?: ([T] extends ["source"] ? ISourceProvider : IDestinationProvider) | null | undefined) => undefined;
3
+ export { validateProvider };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateProvider = void 0;
4
+ const fp_1 = require("lodash/fp");
5
+ const errors_1 = require("../errors");
6
+ const reject = (reason) => {
7
+ throw new errors_1.TransferEngineValidationError(`Invalid provider supplied. ${reason}`);
8
+ };
9
+ const validateProvider = (type, provider) => {
10
+ if (!provider) {
11
+ return reject(`Expected an instance of "${(0, fp_1.capitalize)(type)}Provider", but got "${typeof provider}" instead.`);
12
+ }
13
+ if (provider.type !== type) {
14
+ return reject(`Expected the provider to be of type "${type}" but got "${provider.type}" instead.`);
15
+ }
16
+ };
17
+ exports.validateProvider = validateProvider;
18
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1,8 @@
1
+ import { Severity } from './constants';
2
+ declare class DataTransferError<T = unknown> extends Error {
3
+ origin: string;
4
+ severity: Severity;
5
+ details: T | null;
6
+ constructor(origin: string, severity: Severity, message?: string, details?: T | null);
7
+ }
8
+ export { DataTransferError };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataTransferError = void 0;
4
+ class DataTransferError extends Error {
5
+ constructor(origin, severity, message, details) {
6
+ super(message);
7
+ this.origin = origin;
8
+ this.severity = severity;
9
+ this.details = details ?? null;
10
+ }
11
+ }
12
+ exports.DataTransferError = DataTransferError;
13
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1,3 @@
1
+ import { ErrorDiagnosticSeverity } from '../engine/diagnostic';
2
+ export declare const SeverityKind: Record<string, ErrorDiagnosticSeverity>;
3
+ export declare type Severity = typeof SeverityKind[keyof typeof SeverityKind];
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SeverityKind = void 0;
4
+ exports.SeverityKind = {
5
+ FATAL: 'fatal',
6
+ ERROR: 'error',
7
+ SILLY: 'silly',
8
+ };
9
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,2 @@
1
+ export * from './constants';
2
+ export * from './base';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./base"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,21 @@
1
+ import { DataTransferError } from './base';
2
+ import { Severity } from './constants';
3
+ declare type ProviderStep = 'initialization' | 'validation' | 'transfer';
4
+ declare type ProviderErrorDetails<P extends ProviderStep = ProviderStep, U = never> = {
5
+ step: P;
6
+ } & ([U] extends [never] ? unknown : {
7
+ details?: U;
8
+ });
9
+ export declare class ProviderError<P extends ProviderStep = ProviderStep, U = never, T extends ProviderErrorDetails<P, U> = ProviderErrorDetails<P, U>> extends DataTransferError<T> {
10
+ constructor(severity: Severity, message?: string, details?: T | null);
11
+ }
12
+ export declare class ProviderInitializationError extends ProviderError<'initialization'> {
13
+ constructor(message?: string);
14
+ }
15
+ export declare class ProviderValidationError<T = ProviderErrorDetails> extends ProviderError<'validation', T> {
16
+ constructor(message?: string, details?: T);
17
+ }
18
+ export declare class ProviderTransferError<T = ProviderErrorDetails> extends ProviderError<'transfer', T> {
19
+ constructor(message?: string, details?: T);
20
+ }
21
+ export {};