@strapi/data-transfer 4.8.2 → 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 +1 -0
- package/lib/engine/index.js +30 -4
- package/lib/strapi/providers/index.d.ts +1 -0
- package/lib/strapi/providers/index.js +1 -0
- package/lib/strapi/providers/remote-destination/index.d.ts +1 -1
- package/lib/strapi/providers/remote-destination/index.js +3 -3
- 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} +1 -1
- package/lib/strapi/remote/constants.d.ts +3 -1
- package/lib/strapi/remote/constants.js +1 -1
- package/lib/strapi/remote/flows/index.d.ts +4 -4
- 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 +0 -1
- package/lib/strapi/remote/index.js +1 -2
- package/package.json +4 -4
- 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 -26
- package/lib/strapi/remote/controllers/push.js +0 -116
- package/lib/strapi/remote/handlers.d.ts +0 -10
- package/lib/strapi/remote/handlers.js +0 -285
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
|
package/lib/engine/index.js
CHANGED
|
@@ -27,7 +27,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
27
27
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
28
28
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
29
29
|
};
|
|
30
|
-
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;
|
|
31
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
38
|
exports.errors = exports.createTransferEngine = exports.DEFAULT_SCHEMA_STRATEGY = exports.DEFAULT_VERSION_STRATEGY = exports.TransferGroupPresets = exports.TRANSFER_STAGES = void 0;
|
|
33
39
|
const stream_1 = require("stream");
|
|
@@ -77,6 +83,8 @@ class TransferEngine {
|
|
|
77
83
|
constructor(sourceProvider, destinationProvider, options) {
|
|
78
84
|
_TransferEngine_instances.add(this);
|
|
79
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);
|
|
80
88
|
this.diagnostics = (0, diagnostic_1.createDiagnosticReporter)();
|
|
81
89
|
(0, validation_1.validateProvider)('source', sourceProvider);
|
|
82
90
|
(0, validation_1.validateProvider)('destination', destinationProvider);
|
|
@@ -107,6 +115,10 @@ class TransferEngine {
|
|
|
107
115
|
}
|
|
108
116
|
return !included;
|
|
109
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
|
+
}
|
|
110
122
|
async init() {
|
|
111
123
|
// Resolve providers' resource and store
|
|
112
124
|
// them in the engine's internal state
|
|
@@ -266,7 +278,7 @@ class TransferEngine {
|
|
|
266
278
|
await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_transferStage).call(this, { stage, source, destination, transform, tracker });
|
|
267
279
|
}
|
|
268
280
|
}
|
|
269
|
-
_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) {
|
|
270
282
|
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, error, 'fatal');
|
|
271
283
|
throw error;
|
|
272
284
|
}, _TransferEngine_reportError = function _TransferEngine_reportError(error, severity) {
|
|
@@ -292,6 +304,7 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
292
304
|
});
|
|
293
305
|
}, _TransferEngine_createStageTransformStream = function _TransferEngine_createStageTransformStream(key, options = {}) {
|
|
294
306
|
const { includeGlobal = true } = options;
|
|
307
|
+
const { throttle } = this.options;
|
|
295
308
|
const { global: globalTransforms, [key]: stageTransforms } = this.options?.transforms ?? {};
|
|
296
309
|
let stream = new stream_1.PassThrough({ objectMode: true });
|
|
297
310
|
const applyTransforms = (transforms = []) => {
|
|
@@ -307,6 +320,17 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
307
320
|
if (includeGlobal) {
|
|
308
321
|
applyTransforms(globalTransforms);
|
|
309
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
|
+
}
|
|
310
334
|
applyTransforms(stageTransforms);
|
|
311
335
|
return stream;
|
|
312
336
|
}, _TransferEngine_updateTransferProgress = function _TransferEngine_updateTransferProgress(stage, data, aggregate) {
|
|
@@ -474,18 +498,20 @@ _TransferEngine_metadata = new WeakMap(), _TransferEngine_instances = new WeakSe
|
|
|
474
498
|
if (tracker) {
|
|
475
499
|
stream = stream.pipe(tracker);
|
|
476
500
|
}
|
|
477
|
-
stream
|
|
501
|
+
__classPrivateFieldSet(this, _TransferEngine_currentStream, stream
|
|
478
502
|
.pipe(destination)
|
|
479
503
|
.on('error', (e) => {
|
|
480
504
|
updateEndTime();
|
|
505
|
+
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'error', stage);
|
|
481
506
|
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_reportError).call(this, e, 'error');
|
|
482
507
|
destination.destroy(e);
|
|
483
508
|
reject(e);
|
|
484
509
|
})
|
|
485
510
|
.on('close', () => {
|
|
511
|
+
__classPrivateFieldSet(this, _TransferEngine_currentStream, undefined, "f");
|
|
486
512
|
updateEndTime();
|
|
487
513
|
resolve();
|
|
488
|
-
});
|
|
514
|
+
}), "f");
|
|
489
515
|
});
|
|
490
516
|
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_emitStageUpdate).call(this, 'finish', stage);
|
|
491
517
|
}, _TransferEngine_resolveProviderResource = async function _TransferEngine_resolveProviderResource() {
|
|
@@ -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
|
|
@@ -1,7 +1,7 @@
|
|
|
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
7
|
interface ITransferTokenAuth {
|
|
@@ -11,7 +11,7 @@ const ws_1 = require("ws");
|
|
|
11
11
|
const uuid_1 = require("uuid");
|
|
12
12
|
const stream_1 = require("stream");
|
|
13
13
|
const fp_1 = require("lodash/fp");
|
|
14
|
-
const utils_1 = require("
|
|
14
|
+
const utils_1 = require("../utils");
|
|
15
15
|
const constants_1 = require("../../remote/constants");
|
|
16
16
|
const providers_1 = require("../../../errors/providers");
|
|
17
17
|
const jsonLength = (obj) => Buffer.byteLength(JSON.stringify(obj));
|
|
@@ -34,7 +34,7 @@ class RemoteStrapiDestinationProvider {
|
|
|
34
34
|
try {
|
|
35
35
|
const query = this.dispatcher?.dispatchCommand({
|
|
36
36
|
command: 'init',
|
|
37
|
-
params: {
|
|
37
|
+
params: { strategy, restore },
|
|
38
38
|
});
|
|
39
39
|
const res = (await query);
|
|
40
40
|
if (!res?.transferID) {
|
|
@@ -65,7 +65,7 @@ class RemoteStrapiDestinationProvider {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
68
|
-
const wsUrl = `${wsProtocol}//${url.host}${url.pathname}${constants_1.TRANSFER_PATH}`;
|
|
68
|
+
const wsUrl = `${wsProtocol}//${url.host}${url.pathname}${constants_1.TRANSFER_PATH}/push`;
|
|
69
69
|
// No auth defined, trying public access for transfer
|
|
70
70
|
if (!auth) {
|
|
71
71
|
ws = new ws_1.WebSocket(wsUrl);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Readable } from 'stream';
|
|
3
|
+
import { WebSocket } from 'ws';
|
|
4
|
+
import type { IMetadata, ISourceProvider, ISourceProviderTransferResults, MaybePromise, ProviderType } from '../../../../types';
|
|
5
|
+
import { ILocalStrapiSourceProviderOptions } from '../local-source';
|
|
6
|
+
import { createDispatcher } from '../utils';
|
|
7
|
+
interface ITransferTokenAuth {
|
|
8
|
+
type: 'token';
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
export interface IRemoteStrapiSourceProviderOptions extends ILocalStrapiSourceProviderOptions {
|
|
12
|
+
url: URL;
|
|
13
|
+
auth?: ITransferTokenAuth;
|
|
14
|
+
}
|
|
15
|
+
declare class RemoteStrapiSourceProvider implements ISourceProvider {
|
|
16
|
+
#private;
|
|
17
|
+
name: string;
|
|
18
|
+
type: ProviderType;
|
|
19
|
+
options: IRemoteStrapiSourceProviderOptions;
|
|
20
|
+
ws: WebSocket | null;
|
|
21
|
+
dispatcher: ReturnType<typeof createDispatcher> | null;
|
|
22
|
+
constructor(options: IRemoteStrapiSourceProviderOptions);
|
|
23
|
+
results?: ISourceProviderTransferResults | undefined;
|
|
24
|
+
createEntitiesReadStream(): MaybePromise<Readable>;
|
|
25
|
+
createLinksReadStream(): MaybePromise<Readable>;
|
|
26
|
+
createAssetsReadStream(): Promise<Readable>;
|
|
27
|
+
createConfigurationReadStream(): MaybePromise<Readable>;
|
|
28
|
+
getMetadata(): Promise<IMetadata | null>;
|
|
29
|
+
assertValidProtocol(url: URL): void;
|
|
30
|
+
initTransfer(): Promise<string>;
|
|
31
|
+
bootstrap(): Promise<void>;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
getSchemas(): Promise<Strapi.Schemas | null>;
|
|
34
|
+
}
|
|
35
|
+
export declare const createRemoteStrapiSourceProvider: (options: IRemoteStrapiSourceProviderOptions) => RemoteStrapiSourceProvider;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var _RemoteStrapiSourceProvider_instances, _RemoteStrapiSourceProvider_createStageReadStream, _RemoteStrapiSourceProvider_startStep, _RemoteStrapiSourceProvider_respond, _RemoteStrapiSourceProvider_endStep;
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createRemoteStrapiSourceProvider = void 0;
|
|
10
|
+
const stream_1 = require("stream");
|
|
11
|
+
const ws_1 = require("ws");
|
|
12
|
+
const providers_1 = require("../../../errors/providers");
|
|
13
|
+
const constants_1 = require("../../remote/constants");
|
|
14
|
+
const utils_1 = require("../utils");
|
|
15
|
+
class RemoteStrapiSourceProvider {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
_RemoteStrapiSourceProvider_instances.add(this);
|
|
18
|
+
this.name = 'source::remote-strapi';
|
|
19
|
+
this.type = 'source';
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.ws = null;
|
|
22
|
+
this.dispatcher = null;
|
|
23
|
+
}
|
|
24
|
+
createEntitiesReadStream() {
|
|
25
|
+
return __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_createStageReadStream).call(this, 'entities');
|
|
26
|
+
}
|
|
27
|
+
createLinksReadStream() {
|
|
28
|
+
return __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_createStageReadStream).call(this, 'links');
|
|
29
|
+
}
|
|
30
|
+
async createAssetsReadStream() {
|
|
31
|
+
const assets = {};
|
|
32
|
+
const stream = await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_createStageReadStream).call(this, 'assets');
|
|
33
|
+
const pass = new stream_1.PassThrough({ objectMode: true });
|
|
34
|
+
stream
|
|
35
|
+
.on('data', (asset) => {
|
|
36
|
+
const { chunk, ...rest } = asset;
|
|
37
|
+
if (!(asset.filename in assets)) {
|
|
38
|
+
const assetStream = new stream_1.PassThrough();
|
|
39
|
+
assets[asset.filename] = assetStream;
|
|
40
|
+
pass.push({ ...rest, stream: assetStream });
|
|
41
|
+
}
|
|
42
|
+
if (asset.filename in assets) {
|
|
43
|
+
// The buffer has gone through JSON operations and is now of shape { type: "Buffer"; data: UInt8Array }
|
|
44
|
+
// We need to transform it back into a Buffer instance
|
|
45
|
+
assets[asset.filename].push(Buffer.from(chunk.data));
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.on('end', () => {
|
|
49
|
+
Object.values(assets).forEach((s) => {
|
|
50
|
+
s.push(null);
|
|
51
|
+
});
|
|
52
|
+
})
|
|
53
|
+
.on('close', () => {
|
|
54
|
+
pass.end();
|
|
55
|
+
});
|
|
56
|
+
return pass;
|
|
57
|
+
}
|
|
58
|
+
createConfigurationReadStream() {
|
|
59
|
+
return __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_createStageReadStream).call(this, 'configuration');
|
|
60
|
+
}
|
|
61
|
+
async getMetadata() {
|
|
62
|
+
const metadata = await this.dispatcher?.dispatchTransferAction('getMetadata');
|
|
63
|
+
return metadata ?? null;
|
|
64
|
+
}
|
|
65
|
+
assertValidProtocol(url) {
|
|
66
|
+
const validProtocols = ['https:', 'http:'];
|
|
67
|
+
if (!validProtocols.includes(url.protocol)) {
|
|
68
|
+
throw new providers_1.ProviderValidationError(`Invalid protocol "${url.protocol}"`, {
|
|
69
|
+
check: 'url',
|
|
70
|
+
details: {
|
|
71
|
+
protocol: url.protocol,
|
|
72
|
+
validProtocols,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async initTransfer() {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
this.ws
|
|
80
|
+
?.on('unexpected-response', (_req, res) => {
|
|
81
|
+
if (res.statusCode === 401) {
|
|
82
|
+
return reject(new providers_1.ProviderInitializationError('Failed to initialize the connexion: Authentication Error'));
|
|
83
|
+
}
|
|
84
|
+
if (res.statusCode === 403) {
|
|
85
|
+
return reject(new providers_1.ProviderInitializationError('Failed to initialize the connexion: Authorization Error'));
|
|
86
|
+
}
|
|
87
|
+
if (res.statusCode === 404) {
|
|
88
|
+
return reject(new providers_1.ProviderInitializationError('Failed to initialize the connexion: Data transfer is not enabled on the remote host'));
|
|
89
|
+
}
|
|
90
|
+
return reject(new providers_1.ProviderInitializationError(`Failed to initialize the connexion: Unexpected server response ${res.statusCode}`));
|
|
91
|
+
})
|
|
92
|
+
?.once('open', async () => {
|
|
93
|
+
const query = this.dispatcher?.dispatchCommand({
|
|
94
|
+
command: 'init',
|
|
95
|
+
});
|
|
96
|
+
const res = (await query);
|
|
97
|
+
if (!res?.transferID) {
|
|
98
|
+
return reject(new providers_1.ProviderTransferError('Init failed, invalid response from the server'));
|
|
99
|
+
}
|
|
100
|
+
resolve(res.transferID);
|
|
101
|
+
})
|
|
102
|
+
.once('error', reject);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async bootstrap() {
|
|
106
|
+
const { url, auth } = this.options;
|
|
107
|
+
let ws;
|
|
108
|
+
this.assertValidProtocol(url);
|
|
109
|
+
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
110
|
+
const wsUrl = `${wsProtocol}//${url.host}${url.pathname}${constants_1.TRANSFER_PATH}/pull`;
|
|
111
|
+
// No auth defined, trying public access for transfer
|
|
112
|
+
if (!auth) {
|
|
113
|
+
ws = new ws_1.WebSocket(wsUrl);
|
|
114
|
+
}
|
|
115
|
+
// Common token auth, this should be the main auth method
|
|
116
|
+
else if (auth.type === 'token') {
|
|
117
|
+
const headers = { Authorization: `Bearer ${auth.token}` };
|
|
118
|
+
ws = new ws_1.WebSocket(wsUrl, { headers });
|
|
119
|
+
}
|
|
120
|
+
// Invalid auth method provided
|
|
121
|
+
else {
|
|
122
|
+
throw new providers_1.ProviderValidationError('Auth method not available', {
|
|
123
|
+
check: 'auth.type',
|
|
124
|
+
details: {
|
|
125
|
+
auth: auth.type,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
this.ws = ws;
|
|
130
|
+
this.dispatcher = (0, utils_1.createDispatcher)(this.ws);
|
|
131
|
+
const transferID = await this.initTransfer();
|
|
132
|
+
this.dispatcher.setTransferProperties({ id: transferID, kind: 'pull' });
|
|
133
|
+
await this.dispatcher.dispatchTransferAction('bootstrap');
|
|
134
|
+
}
|
|
135
|
+
async close() {
|
|
136
|
+
await this.dispatcher?.dispatchTransferAction('close');
|
|
137
|
+
await new Promise((resolve) => {
|
|
138
|
+
const { ws } = this;
|
|
139
|
+
if (!ws || ws.CLOSED) {
|
|
140
|
+
resolve();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
ws.on('close', () => resolve()).close();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
async getSchemas() {
|
|
147
|
+
const schemas = (await this.dispatcher?.dispatchTransferAction('getSchemas')) ?? null;
|
|
148
|
+
return schemas;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
_RemoteStrapiSourceProvider_instances = new WeakSet(), _RemoteStrapiSourceProvider_createStageReadStream = async function _RemoteStrapiSourceProvider_createStageReadStream(stage) {
|
|
152
|
+
const startResult = await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_startStep).call(this, stage);
|
|
153
|
+
if (startResult instanceof Error) {
|
|
154
|
+
throw startResult;
|
|
155
|
+
}
|
|
156
|
+
const { id: processID } = startResult;
|
|
157
|
+
const stream = new stream_1.PassThrough({ objectMode: true });
|
|
158
|
+
const listener = async (raw) => {
|
|
159
|
+
const parsed = JSON.parse(raw.toString());
|
|
160
|
+
// If not a message related to our transfer process, ignore it
|
|
161
|
+
if (!parsed.uuid || parsed?.data?.type !== 'transfer' || parsed?.data?.id !== processID) {
|
|
162
|
+
this.ws?.once('message', listener);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const { uuid, data: message } = parsed;
|
|
166
|
+
const { ended, error, data } = message;
|
|
167
|
+
if (ended) {
|
|
168
|
+
await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_respond).call(this, uuid);
|
|
169
|
+
await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_endStep).call(this, stage);
|
|
170
|
+
stream.end();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (error) {
|
|
174
|
+
await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_respond).call(this, uuid);
|
|
175
|
+
await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_endStep).call(this, stage);
|
|
176
|
+
stream.destroy(error);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
stream.push(data);
|
|
180
|
+
this.ws?.once('message', listener);
|
|
181
|
+
await __classPrivateFieldGet(this, _RemoteStrapiSourceProvider_instances, "m", _RemoteStrapiSourceProvider_respond).call(this, uuid);
|
|
182
|
+
};
|
|
183
|
+
this.ws?.once('message', listener);
|
|
184
|
+
return stream;
|
|
185
|
+
}, _RemoteStrapiSourceProvider_startStep = async function _RemoteStrapiSourceProvider_startStep(step) {
|
|
186
|
+
try {
|
|
187
|
+
return await this.dispatcher?.dispatchTransferStep({ action: 'start', step });
|
|
188
|
+
}
|
|
189
|
+
catch (e) {
|
|
190
|
+
if (e instanceof Error) {
|
|
191
|
+
return e;
|
|
192
|
+
}
|
|
193
|
+
if (typeof e === 'string') {
|
|
194
|
+
return new providers_1.ProviderTransferError(e);
|
|
195
|
+
}
|
|
196
|
+
return new providers_1.ProviderTransferError('Unexpected error');
|
|
197
|
+
}
|
|
198
|
+
}, _RemoteStrapiSourceProvider_respond = async function _RemoteStrapiSourceProvider_respond(uuid) {
|
|
199
|
+
return new Promise((resolve, reject) => {
|
|
200
|
+
this.ws?.send(JSON.stringify({ uuid }), (e) => {
|
|
201
|
+
if (e) {
|
|
202
|
+
reject(e);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
resolve(e);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}, _RemoteStrapiSourceProvider_endStep = async function _RemoteStrapiSourceProvider_endStep(step) {
|
|
210
|
+
try {
|
|
211
|
+
await this.dispatcher?.dispatchTransferStep({ action: 'end', step });
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
if (e instanceof Error) {
|
|
215
|
+
return e;
|
|
216
|
+
}
|
|
217
|
+
if (typeof e === 'string') {
|
|
218
|
+
return new providers_1.ProviderTransferError(e);
|
|
219
|
+
}
|
|
220
|
+
return new providers_1.ProviderTransferError('Unexpected error');
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
};
|
|
224
|
+
const createRemoteStrapiSourceProvider = (options) => {
|
|
225
|
+
return new RemoteStrapiSourceProvider(options);
|
|
226
|
+
};
|
|
227
|
+
exports.createRemoteStrapiSourceProvider = createRemoteStrapiSourceProvider;
|
|
228
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebSocket } from 'ws';
|
|
2
|
-
import type { client } from '
|
|
2
|
+
import type { client } from '../../../types/remote/protocol';
|
|
3
3
|
interface IDispatcherState {
|
|
4
4
|
transfer?: {
|
|
5
5
|
kind: client.TransferKind;
|
|
@@ -12,13 +12,13 @@ interface IDispatchOptions {
|
|
|
12
12
|
declare type Dispatch<T> = Omit<T, 'transferID' | 'uuid'>;
|
|
13
13
|
declare const createDispatcher: (ws: WebSocket) => {
|
|
14
14
|
readonly transferID: string | undefined;
|
|
15
|
-
readonly transferKind:
|
|
15
|
+
readonly transferKind: any;
|
|
16
16
|
setTransferProperties: (properties: Exclude<IDispatcherState['transfer'], undefined>) => void;
|
|
17
17
|
dispatch: <U = null>(message: Dispatch<client.Message>, options?: IDispatchOptions) => Promise<U | null>;
|
|
18
18
|
dispatchCommand: <U_1 extends "end" | "init" | "status">(payload: {
|
|
19
19
|
command: U_1;
|
|
20
20
|
} & ([client.GetCommandParams<U_1>] extends [never] ? unknown : {
|
|
21
|
-
params
|
|
21
|
+
params?: client.GetCommandParams<U_1> | undefined;
|
|
22
22
|
})) => Promise<null>;
|
|
23
23
|
dispatchTransferAction: <T>(action: client.Action['action']) => Promise<T | null>;
|
|
24
24
|
dispatchTransferStep: <T_1, A extends "stream" | "end" | "start" = "stream" | "end" | "start", S extends "entities" | "links" | "configuration" | "assets" = "entities" | "links" | "configuration" | "assets">(payload: {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createDispatcher = void 0;
|
|
4
4
|
const uuid_1 = require("uuid");
|
|
5
|
-
const providers_1 = require("
|
|
5
|
+
const providers_1 = require("../../errors/providers");
|
|
6
6
|
const createDispatcher = (ws) => {
|
|
7
7
|
const state = {};
|
|
8
8
|
const dispatch = async (message, options = {}) => {
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export declare const TRANSFER_PATH: "/transfer/runner
|
|
1
|
+
export declare const TRANSFER_PATH: "/transfer/runner";
|
|
2
2
|
export declare const TRANSFER_METHODS: readonly ["push", "pull"];
|
|
3
|
+
export declare type TransferPath = typeof TRANSFER_PATH;
|
|
4
|
+
export declare type TransferMethod = (typeof TRANSFER_METHODS)[number];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TRANSFER_METHODS = exports.TRANSFER_PATH = void 0;
|
|
4
|
-
exports.TRANSFER_PATH = '/transfer/runner
|
|
4
|
+
exports.TRANSFER_PATH = '/transfer/runner';
|
|
5
5
|
exports.TRANSFER_METHODS = ['push', 'pull'];
|
|
6
6
|
//# sourceMappingURL=constants.js.map
|
|
@@ -8,11 +8,11 @@ export declare type Step = {
|
|
|
8
8
|
locked?: boolean;
|
|
9
9
|
};
|
|
10
10
|
export { default as DEFAULT_TRANSFER_FLOW } from './default';
|
|
11
|
-
export
|
|
11
|
+
export interface TransferFlow {
|
|
12
12
|
has(step: Step): boolean;
|
|
13
13
|
can(step: Step): boolean;
|
|
14
14
|
cannot(step: Step): boolean;
|
|
15
|
-
set(step: Step):
|
|
15
|
+
set(step: Step): this;
|
|
16
16
|
get(): Step | null;
|
|
17
|
-
}
|
|
18
|
-
export declare
|
|
17
|
+
}
|
|
18
|
+
export declare const createFlow: (flow: readonly Step[]) => TransferFlow;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { WebSocket, RawData } from 'ws';
|
|
3
|
+
import type { ValidTransferCommand } from './constants';
|
|
4
|
+
import type { TransferMethod } from '../constants';
|
|
5
|
+
declare type BufferLike = Parameters<WebSocket['send']>[0];
|
|
6
|
+
export interface TransferState {
|
|
7
|
+
id?: string;
|
|
8
|
+
startedAt?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface Handler {
|
|
11
|
+
get transferID(): TransferState['id'];
|
|
12
|
+
set transferID(id: TransferState['id']);
|
|
13
|
+
get startedAt(): TransferState['startedAt'];
|
|
14
|
+
set startedAt(id: TransferState['startedAt']);
|
|
15
|
+
/**
|
|
16
|
+
* Returns whether a transfer is currently in progress or not
|
|
17
|
+
*/
|
|
18
|
+
isTransferStarted(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Make sure the current transfer is started and initialized
|
|
21
|
+
*/
|
|
22
|
+
assertValidTransfer(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Checks that the given string is a valid transfer command
|
|
25
|
+
*/
|
|
26
|
+
assertValidTransferCommand(command: string): asserts command is ValidTransferCommand;
|
|
27
|
+
/**
|
|
28
|
+
* Respond to a specific message
|
|
29
|
+
*/
|
|
30
|
+
respond<T = unknown>(uuid?: string, e?: Error | null, data?: T): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* It sends a message to the client
|
|
33
|
+
*/
|
|
34
|
+
send<T extends BufferLike>(message: T, cb?: (err?: Error) => void): void;
|
|
35
|
+
/**
|
|
36
|
+
* It sends a message to the client and waits for a confirmation
|
|
37
|
+
*/
|
|
38
|
+
confirm<T = unknown>(message: T): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Check the current auth has the permission for the given scope
|
|
41
|
+
*/
|
|
42
|
+
verifyAuth(scope?: TransferMethod): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Invoke a function and return its result to the client
|
|
45
|
+
*/
|
|
46
|
+
executeAndRespond<T = unknown>(uuid: string, fn: () => T): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Lifecycle called on error or when the ws connection is closed
|
|
49
|
+
*/
|
|
50
|
+
teardown(): Promise<void> | void;
|
|
51
|
+
/**
|
|
52
|
+
* Lifecycle called to cleanup the transfer state
|
|
53
|
+
*/
|
|
54
|
+
cleanup(): Promise<void> | void;
|
|
55
|
+
init(...args: unknown[]): unknown;
|
|
56
|
+
end(...args: unknown[]): unknown;
|
|
57
|
+
status(...args: unknown[]): unknown;
|
|
58
|
+
onMessage(message: RawData, isBinary: boolean): Promise<void> | void;
|
|
59
|
+
onClose(code: number, reason: Buffer): Promise<void> | void;
|
|
60
|
+
onError(err: Error): Promise<void> | void;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlerControllerFactory = exports.createPullController = exports.createPushController = void 0;
|
|
4
|
+
var push_1 = require("./push");
|
|
5
|
+
Object.defineProperty(exports, "createPushController", { enumerable: true, get: function () { return push_1.createPushController; } });
|
|
6
|
+
var pull_1 = require("./pull");
|
|
7
|
+
Object.defineProperty(exports, "createPullController", { enumerable: true, get: function () { return pull_1.createPullController; } });
|
|
8
|
+
var utils_1 = require("./utils");
|
|
9
|
+
Object.defineProperty(exports, "handlerControllerFactory", { enumerable: true, get: function () { return utils_1.handlerControllerFactory; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="koa" />
|
|
3
|
+
import { Readable } from 'stream';
|
|
4
|
+
import { Handler } from './abstract';
|
|
5
|
+
import { ILocalStrapiSourceProvider } from '../../providers';
|
|
6
|
+
import type { TransferStage, Protocol } from '../../../../types';
|
|
7
|
+
declare const VALID_TRANSFER_ACTIONS: readonly ["bootstrap", "close", "getMetadata", "getSchemas"];
|
|
8
|
+
declare type PullTransferAction = (typeof VALID_TRANSFER_ACTIONS)[number];
|
|
9
|
+
export interface PullHandler extends Handler {
|
|
10
|
+
provider?: ILocalStrapiSourceProvider;
|
|
11
|
+
streams?: {
|
|
12
|
+
[stage in TransferStage]?: Readable;
|
|
13
|
+
};
|
|
14
|
+
assertValidTransferAction(action: string): asserts action is PullTransferAction;
|
|
15
|
+
onTransferMessage(msg: Protocol.client.TransferMessage): Promise<unknown> | unknown;
|
|
16
|
+
onTransferAction(msg: Protocol.client.Action): Promise<unknown> | unknown;
|
|
17
|
+
onTransferStep(msg: Protocol.client.TransferPullMessage): Promise<unknown> | unknown;
|
|
18
|
+
createReadableStreamForStep(step: TransferStage): Promise<void>;
|
|
19
|
+
flush(stage: TransferStage, id: string): Promise<void> | void;
|
|
20
|
+
}
|
|
21
|
+
export declare const createPullController: (options: import("./utils").HandlerOptions) => (ctx: import("koa").Context) => Promise<void>;
|
|
22
|
+
export {};
|