@strapi/data-transfer 4.6.0-beta.1 → 4.6.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 (113) 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/{dist → lib}/engine/index.d.ts +18 -4
  6. package/{dist → lib}/engine/index.js +211 -45
  7. package/lib/engine/validation/index.d.ts +2 -0
  8. package/{dist → lib/engine/validation}/index.js +2 -2
  9. package/lib/engine/validation/provider.d.ts +3 -0
  10. package/lib/engine/validation/provider.js +18 -0
  11. package/{dist/strategies → lib/engine/validation/schemas}/index.d.ts +2 -2
  12. package/{dist/strategies → lib/engine/validation/schemas}/index.js +3 -2
  13. package/lib/errors/base.d.ts +8 -0
  14. package/lib/errors/base.js +13 -0
  15. package/lib/errors/constants.d.ts +3 -0
  16. package/lib/errors/constants.js +9 -0
  17. package/lib/errors/index.d.ts +2 -0
  18. package/{dist/providers → lib/errors}/index.js +2 -6
  19. package/lib/errors/providers.d.ts +21 -0
  20. package/lib/errors/providers.js +32 -0
  21. package/lib/file/index.d.ts +1 -0
  22. package/{dist/providers/shared → lib/file}/index.js +2 -2
  23. package/{dist/providers/local-file-destination-provider → lib/file/providers/destination}/index.d.ts +6 -6
  24. package/{dist/providers/local-file-destination-provider → lib/file/providers/destination}/index.js +7 -7
  25. package/{dist/providers/local-file-destination-provider → lib/file/providers/destination}/utils.d.ts +0 -0
  26. package/{dist/providers/local-file-destination-provider → lib/file/providers/destination}/utils.js +0 -0
  27. package/lib/file/providers/index.d.ts +2 -0
  28. package/lib/file/providers/index.js +19 -0
  29. package/{dist/providers/local-file-source-provider → lib/file/providers/source}/index.d.ts +9 -8
  30. package/{dist/providers/local-file-source-provider → lib/file/providers/source}/index.js +42 -56
  31. package/lib/index.d.ts +4 -0
  32. package/lib/index.js +31 -0
  33. package/lib/strapi/index.d.ts +4 -0
  34. package/lib/strapi/index.js +35 -0
  35. package/lib/strapi/providers/index.d.ts +3 -0
  36. package/lib/strapi/providers/index.js +22 -0
  37. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/index.d.ts +10 -7
  38. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/index.js +65 -37
  39. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/index.d.ts +0 -0
  40. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/index.js +0 -0
  41. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/restore/configuration.d.ts +2 -2
  42. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/restore/configuration.js +17 -10
  43. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/restore/entities.d.ts +2 -0
  44. package/lib/strapi/providers/local-destination/strategies/restore/entities.js +103 -0
  45. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/restore/index.d.ts +0 -0
  46. package/{dist/providers/local-strapi-destination-provider → lib/strapi/providers/local-destination}/strategies/restore/index.js +4 -3
  47. package/lib/strapi/providers/local-destination/strategies/restore/links.d.ts +4 -0
  48. package/lib/strapi/providers/local-destination/strategies/restore/links.js +32 -0
  49. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/assets.d.ts +0 -0
  50. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/assets.js +0 -0
  51. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/configuration.d.ts +0 -0
  52. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/configuration.js +12 -13
  53. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/entities.d.ts +0 -0
  54. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/entities.js +11 -4
  55. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/index.d.ts +6 -6
  56. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/index.js +12 -27
  57. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/links.d.ts +0 -0
  58. package/{dist/providers/local-strapi-source-provider → lib/strapi/providers/local-source}/links.js +1 -1
  59. package/lib/strapi/providers/remote-destination/index.d.ts +40 -0
  60. package/lib/strapi/providers/remote-destination/index.js +186 -0
  61. package/lib/strapi/providers/remote-destination/utils.d.ts +31 -0
  62. package/lib/strapi/providers/remote-destination/utils.js +72 -0
  63. package/{dist/providers/shared/strapi → lib/strapi/queries}/entity.d.ts +0 -0
  64. package/{dist/providers/shared/strapi → lib/strapi/queries}/entity.js +0 -0
  65. package/{dist/providers/shared/strapi → lib/strapi/queries}/index.d.ts +0 -0
  66. package/{dist/providers/shared/strapi → lib/strapi/queries}/index.js +0 -0
  67. package/{dist/providers/shared/strapi → lib/strapi/queries}/link.d.ts +2 -2
  68. package/{dist/providers/shared/strapi → lib/strapi/queries}/link.js +17 -3
  69. package/lib/strapi/register.d.ts +7 -0
  70. package/lib/strapi/register.js +13 -0
  71. package/lib/strapi/remote/constants.d.ts +2 -0
  72. package/lib/strapi/remote/constants.js +6 -0
  73. package/lib/strapi/remote/controllers/index.d.ts +1 -0
  74. package/lib/strapi/remote/controllers/index.js +18 -0
  75. package/lib/strapi/remote/controllers/push.d.ts +25 -0
  76. package/lib/strapi/remote/controllers/push.js +95 -0
  77. package/lib/strapi/remote/handlers.d.ts +3 -0
  78. package/lib/strapi/remote/handlers.js +193 -0
  79. package/lib/strapi/remote/index.d.ts +3 -0
  80. package/lib/strapi/remote/index.js +30 -0
  81. package/lib/strapi/remote/routes.d.ts +21 -0
  82. package/lib/strapi/remote/routes.js +22 -0
  83. package/lib/utils/encryption/decrypt.d.ts +11 -0
  84. package/{dist → lib/utils}/encryption/decrypt.js +8 -0
  85. package/lib/utils/encryption/encrypt.d.ts +11 -0
  86. package/{dist → lib/utils}/encryption/encrypt.js +8 -0
  87. package/{dist → lib/utils}/encryption/index.d.ts +0 -0
  88. package/{dist → lib/utils}/encryption/index.js +0 -0
  89. package/{dist → lib}/utils/index.d.ts +2 -0
  90. package/{dist → lib}/utils/index.js +3 -1
  91. package/{dist → lib}/utils/json.d.ts +7 -0
  92. package/{dist → lib}/utils/json.js +8 -1
  93. package/lib/utils/providers.d.ts +2 -0
  94. package/lib/utils/providers.js +11 -0
  95. package/{dist → lib}/utils/schema.d.ts +4 -0
  96. package/{dist → lib}/utils/schema.js +9 -2
  97. package/lib/utils/stream.d.ts +27 -0
  98. package/lib/utils/stream.js +59 -0
  99. package/lib/utils/transaction.d.ts +3 -0
  100. package/lib/utils/transaction.js +70 -0
  101. package/package.json +20 -12
  102. package/dist/encryption/decrypt.d.ts +0 -3
  103. package/dist/encryption/encrypt.d.ts +0 -3
  104. package/dist/index.d.ts +0 -2
  105. package/dist/providers/index.d.ts +0 -4
  106. package/dist/providers/local-strapi-destination-provider/strategies/restore/entities.js +0 -88
  107. package/dist/providers/local-strapi-destination-provider/strategies/restore/links.d.ts +0 -3
  108. package/dist/providers/local-strapi-destination-provider/strategies/restore/links.js +0 -29
  109. package/dist/providers/shared/index.d.ts +0 -1
  110. package/dist/providers/test-utils/index.d.ts +0 -111
  111. package/dist/providers/test-utils/index.js +0 -64
  112. package/dist/utils/stream.d.ts +0 -10
  113. package/dist/utils/stream.js +0 -39
@@ -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,7 +1,13 @@
1
1
  /// <reference types="node" />
2
2
  import { PassThrough } from 'stream';
3
- import type { IDestinationProvider, ISourceProvider, ITransferEngine, ITransferEngineOptions, TransferProgress, ITransferResults, TransferStage } from '../../types';
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>;
6
+ export declare type TransferGroupFilter = Record<TransferFilterPreset, TransferFilters>;
7
+ /**
8
+ * Preset filters for only/exclude options
9
+ * */
10
+ export declare const TransferGroupPresets: TransferGroupFilter;
5
11
  export declare const DEFAULT_VERSION_STRATEGY = "ignore";
6
12
  export declare const DEFAULT_SCHEMA_STRATEGY = "strict";
7
13
  declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D extends IDestinationProvider = IDestinationProvider> implements ITransferEngine {
@@ -13,11 +19,19 @@ declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D exte
13
19
  data: TransferProgress;
14
20
  stream: PassThrough;
15
21
  };
16
- constructor(sourceProvider: ISourceProvider, destinationProvider: IDestinationProvider, options: ITransferEngineOptions);
22
+ diagnostics: IDiagnosticReporter;
23
+ constructor(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions);
24
+ shouldSkipStage(stage: TransferStage): boolean;
17
25
  init(): Promise<void>;
26
+ /**
27
+ * Run the bootstrap method in both source and destination providers
28
+ */
18
29
  bootstrap(): Promise<void>;
30
+ /**
31
+ * Run the close method in both source and destination providers
32
+ */
19
33
  close(): Promise<void>;
20
- integrityCheck(): Promise<boolean>;
34
+ integrityCheck(): Promise<void>;
21
35
  transfer(): Promise<ITransferResults<S, D>>;
22
36
  beforeTransfer(): Promise<void>;
23
37
  transferSchemas(): Promise<void>;
@@ -26,5 +40,5 @@ declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D exte
26
40
  transferAssets(): Promise<void>;
27
41
  transferConfiguration(): Promise<void>;
28
42
  }
29
- 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>;
30
44
  export {};
@@ -4,18 +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 __importDefault = (this && this.__importDefault) || function (mod) {
8
- return (mod && mod.__esModule) ? mod : { "default": mod };
9
- };
10
- 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;
11
8
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TRANSFER_STAGES = void 0;
9
+ exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TransferGroupPresets = exports.TRANSFER_STAGES = void 0;
13
10
  const stream_1 = require("stream");
14
11
  const path_1 = require("path");
12
+ const os_1 = require("os");
15
13
  const fp_1 = require("lodash/fp");
16
14
  const semver_1 = require("semver");
17
- const strategies_1 = __importDefault(require("../strategies"));
15
+ const validation_1 = require("./validation");
18
16
  const stream_2 = require("../utils/stream");
17
+ const errors_1 = require("./errors");
18
+ const diagnostic_1 = require("./diagnostic");
19
19
  exports.TRANSFER_STAGES = Object.freeze([
20
20
  'entities',
21
21
  'links',
@@ -23,23 +23,67 @@ exports.TRANSFER_STAGES = Object.freeze([
23
23
  'schemas',
24
24
  'configuration',
25
25
  ]);
26
+ /**
27
+ * Preset filters for only/exclude options
28
+ * */
29
+ exports.TransferGroupPresets = {
30
+ content: {
31
+ links: true,
32
+ entities: true,
33
+ // TODO: If we need to implement filtering on a running stage, it would be done like this, but we still need to implement it
34
+ // [
35
+ // // Example: content processes the entities stage, but filters individual entities
36
+ // {
37
+ // filter(data) {
38
+ // return shouldIncludeThisData(data);
39
+ // },
40
+ // },
41
+ // ],
42
+ },
43
+ files: {
44
+ assets: true,
45
+ links: true,
46
+ },
47
+ config: {
48
+ configuration: true,
49
+ },
50
+ };
26
51
  exports.DEFAULT_VERSION_STRATEGY = 'ignore';
27
52
  exports.DEFAULT_SCHEMA_STRATEGY = 'strict';
28
53
  class TransferEngine {
29
54
  constructor(sourceProvider, destinationProvider, options) {
30
55
  _TransferEngine_instances.add(this);
31
56
  _TransferEngine_metadata.set(this, {});
32
- if (sourceProvider.type !== 'source') {
33
- throw new Error("SourceProvider does not have type 'source'");
34
- }
35
- if (destinationProvider.type !== 'destination') {
36
- throw new Error("DestinationProvider does not have type 'destination'");
37
- }
57
+ this.diagnostics = (0, diagnostic_1.createDiagnosticReporter)();
58
+ (0, validation_1.validateProvider)('source', sourceProvider);
59
+ (0, validation_1.validateProvider)('destination', destinationProvider);
38
60
  this.sourceProvider = sourceProvider;
39
61
  this.destinationProvider = destinationProvider;
40
62
  this.options = options;
41
63
  this.progress = { data: {}, stream: new stream_1.PassThrough({ objectMode: true }) };
42
64
  }
65
+ shouldSkipStage(stage) {
66
+ const { exclude, only } = this.options;
67
+ // schemas must always be included
68
+ if (stage === 'schemas') {
69
+ return false;
70
+ }
71
+ // everything is included by default unless 'only' has been set
72
+ let included = (0, fp_1.isEmpty)(only);
73
+ if (only?.length > 0) {
74
+ included = only.some((transferGroup) => {
75
+ return exports.TransferGroupPresets[transferGroup][stage];
76
+ });
77
+ }
78
+ if (exclude?.length > 0) {
79
+ if (included) {
80
+ included = !exclude.some((transferGroup) => {
81
+ return exports.TransferGroupPresets[transferGroup][stage];
82
+ });
83
+ }
84
+ }
85
+ return !included;
86
+ }
43
87
  async init() {
44
88
  // Resolve providers' resource and store
45
89
  // them in the engine's internal state
@@ -50,11 +94,33 @@ class TransferEngine {
50
94
  this.destinationProvider.setMetadata?.('source', sourceMetadata);
51
95
  }
52
96
  }
97
+ /**
98
+ * Run the bootstrap method in both source and destination providers
99
+ */
53
100
  async bootstrap() {
54
- 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
+ });
55
110
  }
111
+ /**
112
+ * Run the close method in both source and destination providers
113
+ */
56
114
  async close() {
57
- 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
+ });
58
124
  }
59
125
  async integrityCheck() {
60
126
  try {
@@ -68,24 +134,23 @@ class TransferEngine {
68
134
  if (sourceSchemas && destinationSchemas) {
69
135
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_assertSchemasMatching).call(this, sourceSchemas, destinationSchemas);
70
136
  }
71
- return true;
72
137
  }
73
138
  catch (error) {
74
- return false;
139
+ if (error instanceof Error) {
140
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_panic).call(this, error);
141
+ }
142
+ throw error;
75
143
  }
76
144
  }
77
145
  async transfer() {
78
146
  // reset data between transfers
79
147
  this.progress.data = {};
80
- __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'start');
81
148
  try {
149
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'init');
82
150
  await this.bootstrap();
83
151
  await this.init();
84
- const isValidTransfer = await this.integrityCheck();
85
- if (!isValidTransfer) {
86
- // TODO: provide the log from the integrity check
87
- 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.`);
88
- }
152
+ await this.integrityCheck();
153
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitTransferUpdate).call(this, 'start');
89
154
  await this.beforeTransfer();
90
155
  // Run the transfer stages
91
156
  await this.transferSchemas();
@@ -99,6 +164,12 @@ class TransferEngine {
99
164
  }
100
165
  catch (e) {
101
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
+ }
102
173
  // Rollback the destination provider if an exception is thrown during the transfer
103
174
  // Note: This will be configurable in the future
104
175
  await this.destinationProvider.rollback?.(e);
@@ -111,54 +182,92 @@ class TransferEngine {
111
182
  };
112
183
  }
113
184
  async beforeTransfer() {
114
- await this.sourceProvider.beforeTransfer?.();
115
- 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);
116
201
  }
117
202
  async transferSchemas() {
118
203
  const stage = 'schemas';
119
- const source = await this.sourceProvider.streamSchemas?.();
120
- const destination = await this.destinationProvider.getSchemasStream?.();
204
+ const source = await this.sourceProvider.createSchemasReadStream?.();
205
+ const destination = await this.destinationProvider.createSchemasWriteStream?.();
121
206
  const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
122
207
  const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, { key: (value) => value.modelType });
123
208
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
124
209
  }
125
210
  async transferEntities() {
126
211
  const stage = 'entities';
127
- const source = await this.sourceProvider.streamEntities?.();
128
- const destination = await this.destinationProvider.getEntitiesStream?.();
212
+ const source = await this.sourceProvider.createEntitiesReadStream?.();
213
+ const destination = await this.destinationProvider.createEntitiesWriteStream?.();
129
214
  const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
130
215
  const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, { key: (value) => value.type });
131
216
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
132
217
  }
133
218
  async transferLinks() {
134
219
  const stage = 'links';
135
- const source = await this.sourceProvider.streamLinks?.();
136
- const destination = await this.destinationProvider.getLinksStream?.();
220
+ const source = await this.sourceProvider.createLinksReadStream?.();
221
+ const destination = await this.destinationProvider.createLinksWriteStream?.();
137
222
  const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
138
223
  const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage);
139
224
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
140
225
  }
141
226
  async transferAssets() {
142
227
  const stage = 'assets';
143
- const source = await this.sourceProvider.streamAssets?.();
144
- const destination = await this.destinationProvider.getAssetsStream?.();
228
+ const source = await this.sourceProvider.createAssetsReadStream?.();
229
+ const destination = await this.destinationProvider.createAssetsWriteStream?.();
145
230
  const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
146
231
  const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, {
147
232
  size: (value) => value.stats.size,
148
- key: (value) => (0, path_1.extname)(value.filename),
233
+ key: (value) => (0, path_1.extname)(value.filename) ?? 'NA',
149
234
  });
150
235
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
151
236
  }
152
237
  async transferConfiguration() {
153
238
  const stage = 'configuration';
154
- const source = await this.sourceProvider.streamConfiguration?.();
155
- const destination = await this.destinationProvider.getConfigurationStream?.();
239
+ const source = await this.sourceProvider.createConfigurationReadStream?.();
240
+ const destination = await this.destinationProvider.createConfigurationWriteStream?.();
156
241
  const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
157
242
  const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage);
158
243
  await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
159
244
  }
160
245
  }
161
- _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 = {}) {
162
271
  const { includeGlobal = true } = options;
163
272
  const { global: globalTransforms, [key]: stageTransforms } = this.options?.transforms ?? {};
164
273
  let stream = new stream_1.PassThrough({ objectMode: true });
@@ -219,6 +328,13 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
219
328
  });
220
329
  }, _TransferEngine_assertStrapiVersionIntegrity = function _TransferEngine_assertStrapiVersionIntegrity(sourceVersion, destinationVersion) {
221
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
+ };
222
338
  if (!sourceVersion ||
223
339
  !destinationVersion ||
224
340
  strategy === 'ignore' ||
@@ -229,8 +345,8 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
229
345
  try {
230
346
  diff = (0, semver_1.diff)(sourceVersion, destinationVersion);
231
347
  }
232
- catch (e) {
233
- throw new Error(`Strapi versions doesn't match (${strategy} check): ${sourceVersion} does not match with ${destinationVersion}`);
348
+ catch {
349
+ reject();
234
350
  }
235
351
  if (!diff) {
236
352
  return;
@@ -247,7 +363,7 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
247
363
  if (strategy === 'major' && validMajor.includes(diff)) {
248
364
  return;
249
365
  }
250
- throw new Error(`Strapi versions doesn't match (${strategy} check): ${sourceVersion} does not match with ${destinationVersion}`);
366
+ reject();
251
367
  }, _TransferEngine_assertSchemasMatching = function _TransferEngine_assertSchemasMatching(sourceSchemas, destinationSchemas) {
252
368
  const strategy = this.options.schemaStrategy || exports.DEFAULT_SCHEMA_STRATEGY;
253
369
  if (strategy === 'ignore') {
@@ -258,19 +374,62 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
258
374
  keys.forEach((key) => {
259
375
  const sourceSchema = sourceSchemas[key];
260
376
  const destinationSchema = destinationSchemas[key];
261
- const schemaDiffs = (0, strategies_1.default)(sourceSchema, destinationSchema, strategy);
377
+ const schemaDiffs = (0, validation_1.compareSchemas)(destinationSchema, sourceSchema, strategy);
262
378
  if (schemaDiffs.length) {
263
379
  diffs[key] = schemaDiffs;
264
380
  }
265
381
  });
266
382
  if (!(0, fp_1.isEmpty)(diffs)) {
267
- throw new Error(`Import process failed because the project doesn't have a matching data structure
268
- ${JSON.stringify(diffs, null, 2)}
269
- `);
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 `Added "${path}": "${diff.value}" (${diff.type})`;
392
+ }
393
+ if (diff.kind === 'deleted') {
394
+ return `Removed "${path}"`;
395
+ }
396
+ if (diff.kind === 'modified') {
397
+ return `Modified "${path}": "${diff.values[0]}" (${diff.types[0]}) => "${diff.values[1]}" (${diff.types[1]})`;
398
+ }
399
+ throw new errors_1.TransferEngineValidationError(`Invalid diff found for "${uid}"`, {
400
+ check: `schema on ${uid}`,
401
+ });
402
+ })
403
+ .map((line) => ` - ${line}`)
404
+ .join(os_1.EOL);
405
+ return msg;
406
+ })
407
+ .join(os_1.EOL);
408
+ 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}`, {
409
+ check: 'schema.changes',
410
+ strategy,
411
+ diffs,
412
+ });
270
413
  }
271
414
  }, _TransferEngine_transferStage = async function _TransferEngine_transferStage(options) {
272
415
  const { stage, source, destination, transform, tracker } = options;
273
- if (!source || !destination) {
416
+ if (!source || !destination || this.shouldSkipStage(stage)) {
417
+ // Wait until source and destination are closed
418
+ const results = await Promise.allSettled([source, destination].map((stream) => {
419
+ // if stream is undefined or already closed, resolve immediately
420
+ if (!stream || stream.destroyed) {
421
+ return Promise.resolve();
422
+ }
423
+ // Wait until the close event is produced and then destroy the stream and resolve
424
+ return new Promise((resolve, reject) => {
425
+ stream.on('close', resolve).on('error', reject).destroy();
426
+ });
427
+ }));
428
+ results.forEach((state) => {
429
+ if (state.status === 'rejected') {
430
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportWarning).call(this, state.reason, `transfer(${stage})`);
431
+ }
432
+ });
274
433
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'skip', stage);
275
434
  return;
276
435
  }
@@ -283,7 +442,14 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
283
442
  if (tracker) {
284
443
  stream = stream.pipe(tracker);
285
444
  }
286
- stream.pipe(destination).on('error', reject).on('close', resolve);
445
+ stream
446
+ .pipe(destination)
447
+ .on('error', (e) => {
448
+ __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, e, 'error');
449
+ destination.destroy(e);
450
+ reject(e);
451
+ })
452
+ .on('close', resolve);
287
453
  });
288
454
  __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'finish', stage);
289
455
  }, _TransferEngine_resolveProviderResource = async function _TransferEngine_resolveProviderResource() {
@@ -0,0 +1,2 @@
1
+ export * from './schemas';
2
+ export * from './provider';
@@ -14,6 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./engine"), exports);
18
- __exportStar(require("./providers"), exports);
17
+ __exportStar(require("./schemas"), exports);
18
+ __exportStar(require("./provider"), exports);
19
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
@@ -1,7 +1,7 @@
1
- import type { Diff } from '../utils/json';
1
+ import type { Diff } from '../../../utils/json';
2
2
  declare const strategies: {
3
3
  exact(diffs: Diff[]): Diff[];
4
4
  strict(diffs: Diff[]): Diff[];
5
5
  };
6
6
  declare const compareSchemas: <T, P>(a: T, b: P, strategy: keyof typeof strategies) => Diff[];
7
- export default compareSchemas;
7
+ export { compareSchemas };