@strapi/data-transfer 4.9.0-alpha.0 → 4.9.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/engine/index.d.ts +2 -1
- package/lib/engine/index.js +67 -7
- package/lib/errors/constants.d.ts +1 -1
- package/lib/file/providers/destination/index.js +7 -0
- package/lib/strapi/index.d.ts +0 -1
- package/lib/strapi/index.js +1 -6
- package/lib/strapi/providers/index.d.ts +1 -0
- package/lib/strapi/providers/index.js +1 -0
- package/lib/strapi/providers/local-destination/index.d.ts +1 -1
- package/lib/strapi/providers/local-destination/index.js +9 -4
- package/lib/strapi/providers/remote-destination/index.d.ts +5 -8
- package/lib/strapi/providers/remote-destination/index.js +157 -59
- package/lib/strapi/providers/remote-source/index.d.ts +36 -0
- package/lib/strapi/providers/remote-source/index.js +228 -0
- package/lib/strapi/providers/{remote-destination/utils.d.ts → utils.d.ts} +3 -3
- package/lib/strapi/providers/{remote-destination/utils.js → utils.js} +2 -2
- package/lib/strapi/remote/constants.d.ts +4 -2
- package/lib/strapi/remote/constants.js +1 -1
- package/lib/strapi/remote/flows/default.d.ts +3 -0
- package/lib/strapi/remote/flows/default.js +41 -0
- package/lib/strapi/remote/flows/index.d.ts +18 -0
- package/lib/strapi/remote/flows/index.js +59 -0
- package/lib/strapi/remote/handlers/abstract.d.ts +62 -0
- package/lib/strapi/remote/handlers/abstract.js +3 -0
- package/lib/strapi/remote/handlers/constants.d.ts +2 -0
- package/lib/strapi/remote/handlers/constants.js +5 -0
- package/lib/strapi/remote/handlers/index.d.ts +3 -0
- package/lib/strapi/remote/handlers/index.js +10 -0
- package/lib/strapi/remote/handlers/pull.d.ts +22 -0
- package/lib/strapi/remote/handlers/pull.js +186 -0
- package/lib/strapi/remote/handlers/push.d.ts +75 -0
- package/lib/strapi/remote/handlers/push.js +297 -0
- package/lib/strapi/remote/handlers/utils.d.ts +25 -0
- package/lib/strapi/remote/handlers/utils.js +181 -0
- package/lib/strapi/remote/index.d.ts +1 -2
- package/lib/strapi/remote/index.js +2 -3
- package/lib/utils/transaction.js +21 -3
- package/package.json +8 -7
- package/lib/strapi/register.d.ts +0 -7
- package/lib/strapi/register.js +0 -13
- package/lib/strapi/remote/controllers/index.d.ts +0 -1
- package/lib/strapi/remote/controllers/index.js +0 -18
- package/lib/strapi/remote/controllers/push.d.ts +0 -25
- package/lib/strapi/remote/controllers/push.js +0 -95
- package/lib/strapi/remote/handlers.d.ts +0 -3
- package/lib/strapi/remote/handlers.js +0 -193
- package/lib/strapi/remote/routes.d.ts +0 -21
- package/lib/strapi/remote/routes.js +0 -22
package/lib/engine/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D exte
|
|
|
22
22
|
diagnostics: IDiagnosticReporter;
|
|
23
23
|
constructor(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions);
|
|
24
24
|
shouldSkipStage(stage: TransferStage): boolean;
|
|
25
|
+
abortTransfer(): Promise<void>;
|
|
25
26
|
init(): Promise<void>;
|
|
26
27
|
/**
|
|
27
28
|
* Run the bootstrap method in both source and destination providers
|
|
@@ -41,4 +42,4 @@ declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D exte
|
|
|
41
42
|
transferConfiguration(): Promise<void>;
|
|
42
43
|
}
|
|
43
44
|
export declare const createTransferEngine: <S extends ISourceProvider, D extends IDestinationProvider>(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions) => TransferEngine<S, D>;
|
|
44
|
-
export
|
|
45
|
+
export * as errors from './errors';
|
package/lib/engine/index.js
CHANGED
|
@@ -1,12 +1,41 @@
|
|
|
1
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 __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;
|
|
24
|
+
};
|
|
2
25
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
26
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
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");
|
|
5
28
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
29
|
};
|
|
7
|
-
var
|
|
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_currentStream, _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
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TransferGroupPresets = exports.TRANSFER_STAGES = void 0;
|
|
38
|
+
exports.errors = exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TransferGroupPresets = exports.TRANSFER_STAGES = void 0;
|
|
10
39
|
const stream_1 = require("stream");
|
|
11
40
|
const path_1 = require("path");
|
|
12
41
|
const os_1 = require("os");
|
|
@@ -54,6 +83,8 @@ class TransferEngine {
|
|
|
54
83
|
constructor(sourceProvider, destinationProvider, options) {
|
|
55
84
|
_TransferEngine_instances.add(this);
|
|
56
85
|
_TransferEngine_metadata.set(this, {});
|
|
86
|
+
// Save the currently open stream so that we can access it at any time
|
|
87
|
+
_TransferEngine_currentStream.set(this, void 0);
|
|
57
88
|
this.diagnostics = (0, diagnostic_1.createDiagnosticReporter)();
|
|
58
89
|
(0, validation_1.validateProvider)('source', sourceProvider);
|
|
59
90
|
(0, validation_1.validateProvider)('destination', destinationProvider);
|
|
@@ -84,6 +115,10 @@ class TransferEngine {
|
|
|
84
115
|
}
|
|
85
116
|
return !included;
|
|
86
117
|
}
|
|
118
|
+
// Cause an ongoing transfer to abort gracefully
|
|
119
|
+
async abortTransfer() {
|
|
120
|
+
__classPrivateFieldGet(this, _TransferEngine_currentStream, "f")?.destroy(new errors_1.TransferEngineError('fatal', 'Transfer aborted.'));
|
|
121
|
+
}
|
|
87
122
|
async init() {
|
|
88
123
|
// Resolve providers' resource and store
|
|
89
124
|
// them in the engine's internal state
|
|
@@ -230,7 +265,7 @@ class TransferEngine {
|
|
|
230
265
|
const transform = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_createStageTransformStream).call(this, stage);
|
|
231
266
|
const tracker = __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_progressTracker).call(this, stage, {
|
|
232
267
|
size: (value) => value.stats.size,
|
|
233
|
-
key: (value) => (0, path_1.extname)(value.filename)
|
|
268
|
+
key: (value) => (0, path_1.extname)(value.filename) || 'No extension',
|
|
234
269
|
});
|
|
235
270
|
await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
|
|
236
271
|
}
|
|
@@ -243,7 +278,7 @@ class TransferEngine {
|
|
|
243
278
|
await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
|
|
244
279
|
}
|
|
245
280
|
}
|
|
246
|
-
_TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSet(), _TransferEngine_panic = function _TransferEngine_panic(error) {
|
|
281
|
+
_TransferEngine_metadata = new WeakMap(), _TransferEngine_currentStream = new WeakMap(), _TransferEngine_instances = new WeakSet(), _TransferEngine_panic = function _TransferEngine_panic(error) {
|
|
247
282
|
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, error, 'fatal');
|
|
248
283
|
throw error;
|
|
249
284
|
}, _TransferEngine_reportError = function _TransferEngine_reportError(error, severity) {
|
|
@@ -269,6 +304,7 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
269
304
|
});
|
|
270
305
|
}, _TransferEngine_createStageTransformStream = function _TransferEngine_createStageTransformStream(key, options = {}) {
|
|
271
306
|
const { includeGlobal = true } = options;
|
|
307
|
+
const { throttle } = this.options;
|
|
272
308
|
const { global: globalTransforms, [key]: stageTransforms } = this.options?.transforms ?? {};
|
|
273
309
|
let stream = new stream_1.PassThrough({ objectMode: true });
|
|
274
310
|
const applyTransforms = (transforms = []) => {
|
|
@@ -284,11 +320,22 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
284
320
|
if (includeGlobal) {
|
|
285
321
|
applyTransforms(globalTransforms);
|
|
286
322
|
}
|
|
323
|
+
if ((0, fp_1.isNumber)(throttle) && throttle > 0) {
|
|
324
|
+
stream = stream.pipe(new stream_1.PassThrough({
|
|
325
|
+
objectMode: true,
|
|
326
|
+
async transform(data, _encoding, callback) {
|
|
327
|
+
await new Promise((resolve) => {
|
|
328
|
+
setTimeout(resolve, throttle);
|
|
329
|
+
});
|
|
330
|
+
callback(null, data);
|
|
331
|
+
},
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
287
334
|
applyTransforms(stageTransforms);
|
|
288
335
|
return stream;
|
|
289
336
|
}, _TransferEngine_updateTransferProgress = function _TransferEngine_updateTransferProgress(stage, data, aggregate) {
|
|
290
337
|
if (!this.progress.data[stage]) {
|
|
291
|
-
this.progress.data[stage] = { count: 0, bytes: 0 };
|
|
338
|
+
this.progress.data[stage] = { count: 0, bytes: 0, startTime: Date.now() };
|
|
292
339
|
}
|
|
293
340
|
const stageProgress = this.progress.data[stage];
|
|
294
341
|
if (!stageProgress) {
|
|
@@ -416,6 +463,12 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
416
463
|
}
|
|
417
464
|
}, _TransferEngine_transferStage = async function _TransferEngine_transferStage(options) {
|
|
418
465
|
const { stage, source, destination, transform, tracker } = options;
|
|
466
|
+
const updateEndTime = () => {
|
|
467
|
+
const stageData = this.progress.data[stage];
|
|
468
|
+
if (stageData) {
|
|
469
|
+
stageData.endTime = Date.now();
|
|
470
|
+
}
|
|
471
|
+
};
|
|
419
472
|
if (!source || !destination || this.shouldSkipStage(stage)) {
|
|
420
473
|
// Wait until source and destination are closed
|
|
421
474
|
const results = await Promise.allSettled([source, destination].map((stream) => {
|
|
@@ -445,14 +498,20 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
445
498
|
if (tracker) {
|
|
446
499
|
stream = stream.pipe(tracker);
|
|
447
500
|
}
|
|
448
|
-
stream
|
|
501
|
+
__classPrivateFieldSet(this, _TransferEngine_currentStream, stream
|
|
449
502
|
.pipe(destination)
|
|
450
503
|
.on('error', (e) => {
|
|
504
|
+
updateEndTime();
|
|
505
|
+
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'error', stage);
|
|
451
506
|
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, e, 'error');
|
|
452
507
|
destination.destroy(e);
|
|
453
508
|
reject(e);
|
|
454
509
|
})
|
|
455
|
-
.on('close',
|
|
510
|
+
.on('close', () => {
|
|
511
|
+
__classPrivateFieldSet(this, _TransferEngine_currentStream, undefined, "f");
|
|
512
|
+
updateEndTime();
|
|
513
|
+
resolve();
|
|
514
|
+
}), "f");
|
|
456
515
|
});
|
|
457
516
|
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'finish', stage);
|
|
458
517
|
}, _TransferEngine_resolveProviderResource = async function _TransferEngine_resolveProviderResource() {
|
|
@@ -469,4 +528,5 @@ const createTransferEngine = (sourceProvider, destinationProvider, options) => {
|
|
|
469
528
|
return new TransferEngine(sourceProvider, destinationProvider, options);
|
|
470
529
|
};
|
|
471
530
|
exports.createTransferEngine = createTransferEngine;
|
|
531
|
+
exports.errors = __importStar(require("./errors"));
|
|
472
532
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ErrorDiagnosticSeverity } from '../engine/diagnostic';
|
|
2
2
|
export declare const SeverityKind: Record<string, ErrorDiagnosticSeverity>;
|
|
3
|
-
export declare type Severity = typeof SeverityKind[keyof typeof SeverityKind];
|
|
3
|
+
export declare type Severity = (typeof SeverityKind)[keyof typeof SeverityKind];
|
|
@@ -19,6 +19,7 @@ const stream_chain_1 = require("stream-chain");
|
|
|
19
19
|
const stream_1 = require("stream");
|
|
20
20
|
const encryption_1 = require("../../../utils/encryption");
|
|
21
21
|
const utils_1 = require("./utils");
|
|
22
|
+
const providers_1 = require("../../../errors/providers");
|
|
22
23
|
const createLocalFileDestinationProvider = (options) => {
|
|
23
24
|
return new LocalFileDestinationProvider(options);
|
|
24
25
|
};
|
|
@@ -47,6 +48,12 @@ class LocalFileDestinationProvider {
|
|
|
47
48
|
}
|
|
48
49
|
__classPrivateFieldGet(this, _LocalFileDestinationProvider_archive, "f").stream = tar_stream_1.default.pack();
|
|
49
50
|
const outStream = (0, fs_extra_1.createWriteStream)(__classPrivateFieldGet(this, _LocalFileDestinationProvider_instances, "a", _LocalFileDestinationProvider_archivePath_get));
|
|
51
|
+
outStream.on('error', (err) => {
|
|
52
|
+
if (err.code === 'ENOSPC') {
|
|
53
|
+
throw new providers_1.ProviderTransferError("Your server doesn't have space to proceed with the import.");
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
});
|
|
50
57
|
const archiveTransforms = [];
|
|
51
58
|
if (compression.enabled) {
|
|
52
59
|
archiveTransforms.push(this.createGzip());
|
package/lib/strapi/index.d.ts
CHANGED
package/lib/strapi/index.js
CHANGED
|
@@ -22,14 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.
|
|
26
|
+
exports.remote = exports.queries = exports.providers = void 0;
|
|
30
27
|
exports.providers = __importStar(require("./providers"));
|
|
31
28
|
exports.queries = __importStar(require("./queries"));
|
|
32
29
|
exports.remote = __importStar(require("./remote"));
|
|
33
|
-
var register_1 = require("./register");
|
|
34
|
-
Object.defineProperty(exports, "register", { enumerable: true, get: function () { return __importDefault(register_1).default; } });
|
|
35
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -19,4 +19,5 @@ __exportStar(require("./local-destination"), exports);
|
|
|
19
19
|
__exportStar(require("./local-source"), exports);
|
|
20
20
|
// Remote
|
|
21
21
|
__exportStar(require("./remote-destination"), exports);
|
|
22
|
+
__exportStar(require("./remote-source"), exports);
|
|
22
23
|
//# sourceMappingURL=index.js.map
|
|
@@ -21,7 +21,7 @@ declare class LocalStrapiDestinationProvider implements IDestinationProvider {
|
|
|
21
21
|
constructor(options: ILocalStrapiDestinationProviderOptions);
|
|
22
22
|
bootstrap(): Promise<void>;
|
|
23
23
|
close(): Promise<void>;
|
|
24
|
-
rollback(): void
|
|
24
|
+
rollback(): Promise<void>;
|
|
25
25
|
beforeTransfer(): Promise<void>;
|
|
26
26
|
getMetadata(): IMetadata;
|
|
27
27
|
getSchemas(): import("lodash").Dictionary<Partial<import("@strapi/strapi").Schema>>;
|
|
@@ -73,8 +73,8 @@ class LocalStrapiDestinationProvider {
|
|
|
73
73
|
await this.strapi?.destroy();
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
rollback() {
|
|
77
|
-
this.transaction?.rollback();
|
|
76
|
+
async rollback() {
|
|
77
|
+
await this.transaction?.rollback();
|
|
78
78
|
}
|
|
79
79
|
async beforeTransfer() {
|
|
80
80
|
if (!this.strapi) {
|
|
@@ -151,12 +151,17 @@ class LocalStrapiDestinationProvider {
|
|
|
151
151
|
const writableStream = fse.createWriteStream(entryPath);
|
|
152
152
|
chunk.stream
|
|
153
153
|
.pipe(writableStream)
|
|
154
|
-
.on('close',
|
|
154
|
+
.on('close', () => {
|
|
155
|
+
callback(null);
|
|
156
|
+
})
|
|
155
157
|
.on('error', async (error) => {
|
|
158
|
+
const errorMessage = error.code === 'ENOSPC'
|
|
159
|
+
? " Your server doesn't have space to proceed with the import. "
|
|
160
|
+
: ' ';
|
|
156
161
|
try {
|
|
157
162
|
await fse.rm(assetsDirectory, { recursive: true, force: true });
|
|
158
163
|
await fse.move(backupDirectory, assetsDirectory);
|
|
159
|
-
this.destroy(new providers_1.ProviderTransferError(`There was an error during the transfer process
|
|
164
|
+
this.destroy(new providers_1.ProviderTransferError(`There was an error during the transfer process.${errorMessage}The original files have been restored to ${assetsDirectory}`));
|
|
160
165
|
}
|
|
161
166
|
catch (err) {
|
|
162
167
|
throw new providers_1.ProviderTransferError(`There was an error doing the rollback process. The original files are in ${backupDirectory}, but we failed to restore them to ${assetsDirectory}`);
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { WebSocket } from 'ws';
|
|
3
3
|
import { Writable } from 'stream';
|
|
4
|
-
import { createDispatcher } from '
|
|
4
|
+
import { createDispatcher } from '../utils';
|
|
5
5
|
import type { IDestinationProvider, IMetadata, ProviderType } from '../../../../types';
|
|
6
6
|
import type { ILocalStrapiDestinationProviderOptions } from '../local-destination';
|
|
7
|
-
interface
|
|
7
|
+
interface ITransferTokenAuth {
|
|
8
8
|
type: 'token';
|
|
9
9
|
token: string;
|
|
10
10
|
}
|
|
11
|
-
interface ICredentialsAuth {
|
|
12
|
-
type: 'credentials';
|
|
13
|
-
email: string;
|
|
14
|
-
password: string;
|
|
15
|
-
}
|
|
16
11
|
export interface IRemoteStrapiDestinationProviderOptions extends Pick<ILocalStrapiDestinationProviderOptions, 'restore' | 'strategy'> {
|
|
17
12
|
url: URL;
|
|
18
|
-
auth?:
|
|
13
|
+
auth?: ITransferTokenAuth;
|
|
19
14
|
}
|
|
20
15
|
declare class RemoteStrapiDestinationProvider implements IDestinationProvider {
|
|
21
16
|
#private;
|
|
@@ -24,12 +19,14 @@ declare class RemoteStrapiDestinationProvider implements IDestinationProvider {
|
|
|
24
19
|
options: IRemoteStrapiDestinationProviderOptions;
|
|
25
20
|
ws: WebSocket | null;
|
|
26
21
|
dispatcher: ReturnType<typeof createDispatcher> | null;
|
|
22
|
+
transferID: string | null;
|
|
27
23
|
constructor(options: IRemoteStrapiDestinationProviderOptions);
|
|
28
24
|
initTransfer(): Promise<string>;
|
|
29
25
|
bootstrap(): Promise<void>;
|
|
30
26
|
close(): Promise<void>;
|
|
31
27
|
getMetadata(): Promise<IMetadata | null> | null;
|
|
32
28
|
beforeTransfer(): Promise<void>;
|
|
29
|
+
rollback(): Promise<void>;
|
|
33
30
|
getSchemas(): Promise<Strapi.Schemas | null>;
|
|
34
31
|
createEntitiesWriteStream(): Writable;
|
|
35
32
|
createLinksWriteStream(): Writable;
|
|
@@ -4,15 +4,17 @@ 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 _RemoteStrapiDestinationProvider_instances, _RemoteStrapiDestinationProvider_streamStep;
|
|
7
|
+
var _RemoteStrapiDestinationProvider_instances, _RemoteStrapiDestinationProvider_startStepOnce, _RemoteStrapiDestinationProvider_startStep, _RemoteStrapiDestinationProvider_endStep, _RemoteStrapiDestinationProvider_streamStep, _RemoteStrapiDestinationProvider_writeStream;
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.createRemoteStrapiDestinationProvider = void 0;
|
|
10
10
|
const ws_1 = require("ws");
|
|
11
11
|
const uuid_1 = require("uuid");
|
|
12
12
|
const stream_1 = require("stream");
|
|
13
|
-
const
|
|
13
|
+
const fp_1 = require("lodash/fp");
|
|
14
|
+
const utils_1 = require("../utils");
|
|
14
15
|
const constants_1 = require("../../remote/constants");
|
|
15
16
|
const providers_1 = require("../../../errors/providers");
|
|
17
|
+
const jsonLength = (obj) => Buffer.byteLength(JSON.stringify(obj));
|
|
16
18
|
class RemoteStrapiDestinationProvider {
|
|
17
19
|
constructor(options) {
|
|
18
20
|
_RemoteStrapiDestinationProvider_instances.add(this);
|
|
@@ -21,6 +23,7 @@ class RemoteStrapiDestinationProvider {
|
|
|
21
23
|
this.options = options;
|
|
22
24
|
this.ws = null;
|
|
23
25
|
this.dispatcher = null;
|
|
26
|
+
this.transferID = null;
|
|
24
27
|
}
|
|
25
28
|
async initTransfer() {
|
|
26
29
|
const { strategy, restore } = this.options;
|
|
@@ -28,17 +31,24 @@ class RemoteStrapiDestinationProvider {
|
|
|
28
31
|
return new Promise((resolve, reject) => {
|
|
29
32
|
this.ws
|
|
30
33
|
?.once('open', async () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
try {
|
|
35
|
+
const query = this.dispatcher?.dispatchCommand({
|
|
36
|
+
command: 'init',
|
|
37
|
+
params: { strategy, restore },
|
|
38
|
+
});
|
|
39
|
+
const res = (await query);
|
|
40
|
+
if (!res?.transferID) {
|
|
41
|
+
throw new providers_1.ProviderTransferError('Init failed, invalid response from the server');
|
|
42
|
+
}
|
|
43
|
+
resolve(res.transferID);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
reject(e);
|
|
38
47
|
}
|
|
39
|
-
resolve(res.transferID);
|
|
40
48
|
})
|
|
41
|
-
.once('error',
|
|
49
|
+
.once('error', (message) => {
|
|
50
|
+
reject(message);
|
|
51
|
+
});
|
|
42
52
|
});
|
|
43
53
|
}
|
|
44
54
|
async bootstrap() {
|
|
@@ -55,8 +65,7 @@ class RemoteStrapiDestinationProvider {
|
|
|
55
65
|
});
|
|
56
66
|
}
|
|
57
67
|
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
58
|
-
const wsUrl = `${wsProtocol}//${url.host}${url.pathname}${constants_1.TRANSFER_PATH}`;
|
|
59
|
-
const validAuthMethods = ['token'];
|
|
68
|
+
const wsUrl = `${wsProtocol}//${url.host}${url.pathname}${constants_1.TRANSFER_PATH}/push`;
|
|
60
69
|
// No auth defined, trying public access for transfer
|
|
61
70
|
if (!auth) {
|
|
62
71
|
ws = new ws_1.WebSocket(wsUrl);
|
|
@@ -68,22 +77,28 @@ class RemoteStrapiDestinationProvider {
|
|
|
68
77
|
}
|
|
69
78
|
// Invalid auth method provided
|
|
70
79
|
else {
|
|
71
|
-
throw new providers_1.ProviderValidationError('Auth method not
|
|
80
|
+
throw new providers_1.ProviderValidationError('Auth method not available', {
|
|
72
81
|
check: 'auth.type',
|
|
73
82
|
details: {
|
|
74
83
|
auth: auth.type,
|
|
75
|
-
validAuthMethods,
|
|
76
84
|
},
|
|
77
85
|
});
|
|
78
86
|
}
|
|
79
87
|
this.ws = ws;
|
|
80
88
|
this.dispatcher = (0, utils_1.createDispatcher)(this.ws);
|
|
81
|
-
|
|
82
|
-
this.dispatcher.setTransferProperties({ id: transferID, kind: 'push' });
|
|
89
|
+
this.transferID = await this.initTransfer();
|
|
90
|
+
this.dispatcher.setTransferProperties({ id: this.transferID, kind: 'push' });
|
|
83
91
|
await this.dispatcher.dispatchTransferAction('bootstrap');
|
|
84
92
|
}
|
|
85
93
|
async close() {
|
|
86
|
-
|
|
94
|
+
// Gracefully close the remote transfer process
|
|
95
|
+
if (this.transferID && this.dispatcher) {
|
|
96
|
+
await this.dispatcher.dispatchTransferAction('close');
|
|
97
|
+
await this.dispatcher.dispatchCommand({
|
|
98
|
+
command: 'end',
|
|
99
|
+
params: { transferID: this.transferID },
|
|
100
|
+
});
|
|
101
|
+
}
|
|
87
102
|
await new Promise((resolve) => {
|
|
88
103
|
const { ws } = this;
|
|
89
104
|
if (!ws || ws.CLOSED) {
|
|
@@ -99,6 +114,9 @@ class RemoteStrapiDestinationProvider {
|
|
|
99
114
|
async beforeTransfer() {
|
|
100
115
|
await this.dispatcher?.dispatchTransferAction('beforeTransfer');
|
|
101
116
|
}
|
|
117
|
+
async rollback() {
|
|
118
|
+
await this.dispatcher?.dispatchTransferAction('rollback');
|
|
119
|
+
}
|
|
102
120
|
getSchemas() {
|
|
103
121
|
if (!this.dispatcher) {
|
|
104
122
|
return Promise.resolve(null);
|
|
@@ -106,65 +124,111 @@ class RemoteStrapiDestinationProvider {
|
|
|
106
124
|
return this.dispatcher.dispatchTransferAction('getSchemas');
|
|
107
125
|
}
|
|
108
126
|
createEntitiesWriteStream() {
|
|
109
|
-
return
|
|
110
|
-
objectMode: true,
|
|
111
|
-
write: async (entity, _encoding, callback) => {
|
|
112
|
-
const e = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'entities', entity);
|
|
113
|
-
callback(e);
|
|
114
|
-
},
|
|
115
|
-
});
|
|
127
|
+
return __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_writeStream).call(this, 'entities');
|
|
116
128
|
}
|
|
117
129
|
createLinksWriteStream() {
|
|
118
|
-
return
|
|
119
|
-
objectMode: true,
|
|
120
|
-
write: async (link, _encoding, callback) => {
|
|
121
|
-
const e = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'links', link);
|
|
122
|
-
callback(e);
|
|
123
|
-
},
|
|
124
|
-
});
|
|
130
|
+
return __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_writeStream).call(this, 'links');
|
|
125
131
|
}
|
|
126
132
|
createConfigurationWriteStream() {
|
|
127
|
-
return
|
|
128
|
-
objectMode: true,
|
|
129
|
-
write: async (configuration, _encoding, callback) => {
|
|
130
|
-
const e = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'configuration', configuration);
|
|
131
|
-
callback(e);
|
|
132
|
-
},
|
|
133
|
-
});
|
|
133
|
+
return __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_writeStream).call(this, 'configuration');
|
|
134
134
|
}
|
|
135
135
|
createAssetsWriteStream() {
|
|
136
|
+
let batch = [];
|
|
137
|
+
let hasStarted = false;
|
|
138
|
+
const batchSize = 1024 * 1024; // 1MB;
|
|
139
|
+
const batchLength = () => {
|
|
140
|
+
return batch.reduce((acc, chunk) => (chunk.action === 'stream' ? acc + chunk.data.byteLength : acc), 0);
|
|
141
|
+
};
|
|
142
|
+
const startAssetsTransferOnce = __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_startStepOnce).call(this, 'assets');
|
|
143
|
+
const flush = async () => {
|
|
144
|
+
const streamError = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'assets', batch);
|
|
145
|
+
batch = [];
|
|
146
|
+
return streamError;
|
|
147
|
+
};
|
|
148
|
+
const safePush = async (chunk) => {
|
|
149
|
+
batch.push(chunk);
|
|
150
|
+
if (batchLength() >= batchSize) {
|
|
151
|
+
const streamError = await flush();
|
|
152
|
+
if (streamError) {
|
|
153
|
+
throw streamError;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
136
157
|
return new stream_1.Writable({
|
|
137
158
|
objectMode: true,
|
|
138
159
|
final: async (callback) => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
160
|
+
if (batch.length > 0) {
|
|
161
|
+
await flush();
|
|
162
|
+
}
|
|
163
|
+
if (hasStarted) {
|
|
164
|
+
await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'assets', null);
|
|
165
|
+
const endStepError = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_endStep).call(this, 'assets');
|
|
166
|
+
if (endStepError) {
|
|
167
|
+
return callback(endStepError);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return callback(null);
|
|
142
171
|
},
|
|
143
|
-
|
|
144
|
-
const
|
|
172
|
+
async write(asset, _encoding, callback) {
|
|
173
|
+
const startError = await startAssetsTransferOnce();
|
|
174
|
+
if (startError) {
|
|
175
|
+
return callback(startError);
|
|
176
|
+
}
|
|
177
|
+
hasStarted = true;
|
|
145
178
|
const assetID = (0, uuid_1.v4)();
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
});
|
|
151
|
-
for await (const chunk of stream) {
|
|
152
|
-
await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'assets', {
|
|
153
|
-
action: 'stream',
|
|
179
|
+
const { filename, filepath, stats, stream } = asset;
|
|
180
|
+
try {
|
|
181
|
+
await safePush({
|
|
182
|
+
action: 'start',
|
|
154
183
|
assetID,
|
|
155
|
-
data:
|
|
184
|
+
data: { filename, filepath, stats },
|
|
156
185
|
});
|
|
186
|
+
for await (const chunk of stream) {
|
|
187
|
+
await safePush({ action: 'stream', assetID, data: chunk });
|
|
188
|
+
}
|
|
189
|
+
await safePush({ action: 'end', assetID });
|
|
190
|
+
callback();
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (error instanceof Error) {
|
|
194
|
+
callback(error);
|
|
195
|
+
}
|
|
157
196
|
}
|
|
158
|
-
await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, 'assets', {
|
|
159
|
-
action: 'end',
|
|
160
|
-
assetID,
|
|
161
|
-
});
|
|
162
|
-
callback();
|
|
163
197
|
},
|
|
164
198
|
});
|
|
165
199
|
}
|
|
166
200
|
}
|
|
167
|
-
_RemoteStrapiDestinationProvider_instances = new WeakSet(),
|
|
201
|
+
_RemoteStrapiDestinationProvider_instances = new WeakSet(), _RemoteStrapiDestinationProvider_startStepOnce = function _RemoteStrapiDestinationProvider_startStepOnce(stage) {
|
|
202
|
+
return (0, fp_1.once)(() => __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_startStep).call(this, stage));
|
|
203
|
+
}, _RemoteStrapiDestinationProvider_startStep = async function _RemoteStrapiDestinationProvider_startStep(step) {
|
|
204
|
+
try {
|
|
205
|
+
await this.dispatcher?.dispatchTransferStep({ action: 'start', step });
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
if (e instanceof Error) {
|
|
209
|
+
return e;
|
|
210
|
+
}
|
|
211
|
+
if (typeof e === 'string') {
|
|
212
|
+
return new providers_1.ProviderTransferError(e);
|
|
213
|
+
}
|
|
214
|
+
return new providers_1.ProviderTransferError('Unexpected error');
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}, _RemoteStrapiDestinationProvider_endStep = async function _RemoteStrapiDestinationProvider_endStep(step) {
|
|
218
|
+
try {
|
|
219
|
+
await this.dispatcher?.dispatchTransferStep({ action: 'end', step });
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
if (e instanceof Error) {
|
|
223
|
+
return e;
|
|
224
|
+
}
|
|
225
|
+
if (typeof e === 'string') {
|
|
226
|
+
return new providers_1.ProviderTransferError(e);
|
|
227
|
+
}
|
|
228
|
+
return new providers_1.ProviderTransferError('Unexpected error');
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}, _RemoteStrapiDestinationProvider_streamStep = async function _RemoteStrapiDestinationProvider_streamStep(step, data) {
|
|
168
232
|
try {
|
|
169
233
|
await this.dispatcher?.dispatchTransferStep({ action: 'stream', step, data });
|
|
170
234
|
}
|
|
@@ -178,6 +242,40 @@ _RemoteStrapiDestinationProvider_instances = new WeakSet(), _RemoteStrapiDestina
|
|
|
178
242
|
return new providers_1.ProviderTransferError('Unexpected error');
|
|
179
243
|
}
|
|
180
244
|
return null;
|
|
245
|
+
}, _RemoteStrapiDestinationProvider_writeStream = function _RemoteStrapiDestinationProvider_writeStream(step) {
|
|
246
|
+
const batchSize = 1024 * 1024; // 1MB;
|
|
247
|
+
const startTransferOnce = __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_startStepOnce).call(this, step);
|
|
248
|
+
let batch = [];
|
|
249
|
+
const batchLength = () => jsonLength(batch);
|
|
250
|
+
return new stream_1.Writable({
|
|
251
|
+
objectMode: true,
|
|
252
|
+
final: async (callback) => {
|
|
253
|
+
if (batch.length > 0) {
|
|
254
|
+
const streamError = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, step, batch);
|
|
255
|
+
batch = [];
|
|
256
|
+
if (streamError) {
|
|
257
|
+
return callback(streamError);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const e = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_endStep).call(this, step);
|
|
261
|
+
callback(e);
|
|
262
|
+
},
|
|
263
|
+
write: async (chunk, _encoding, callback) => {
|
|
264
|
+
const startError = await startTransferOnce();
|
|
265
|
+
if (startError) {
|
|
266
|
+
return callback(startError);
|
|
267
|
+
}
|
|
268
|
+
batch.push(chunk);
|
|
269
|
+
if (batchLength() >= batchSize) {
|
|
270
|
+
const streamError = await __classPrivateFieldGet(this, _RemoteStrapiDestinationProvider_instances, "m", _RemoteStrapiDestinationProvider_streamStep).call(this, step, batch);
|
|
271
|
+
batch = [];
|
|
272
|
+
if (streamError) {
|
|
273
|
+
return callback(streamError);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
callback();
|
|
277
|
+
},
|
|
278
|
+
});
|
|
181
279
|
};
|
|
182
280
|
const createRemoteStrapiDestinationProvider = (options) => {
|
|
183
281
|
return new RemoteStrapiDestinationProvider(options);
|