@strapi/data-transfer 0.0.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.
- package/LICENSE +22 -0
- package/dist/encryption/decrypt.d.ts +3 -0
- package/dist/encryption/decrypt.js +39 -0
- package/dist/encryption/encrypt.d.ts +3 -0
- package/dist/encryption/encrypt.js +39 -0
- package/dist/encryption/index.d.ts +2 -0
- package/dist/encryption/index.js +19 -0
- package/dist/engine/index.d.ts +29 -0
- package/dist/engine/index.js +324 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.js +23 -0
- package/dist/providers/local-file-destination-provider.d.ts +41 -0
- package/dist/providers/local-file-destination-provider.js +195 -0
- package/dist/providers/local-file-source-provider.d.ts +43 -0
- package/dist/providers/local-file-source-provider.js +162 -0
- package/dist/providers/local-strapi-destination-provider.d.ts +22 -0
- package/dist/providers/local-strapi-destination-provider.js +78 -0
- package/dist/providers/local-strapi-source-provider/configuration.d.ts +5 -0
- package/dist/providers/local-strapi-source-provider/configuration.js +37 -0
- package/dist/providers/local-strapi-source-provider/entities.d.ts +10 -0
- package/dist/providers/local-strapi-source-provider/entities.js +58 -0
- package/dist/providers/local-strapi-source-provider/index.d.ts +26 -0
- package/dist/providers/local-strapi-source-provider/index.js +83 -0
- package/dist/providers/local-strapi-source-provider/links/index.d.ts +5 -0
- package/dist/providers/local-strapi-source-provider/links/index.js +37 -0
- package/dist/providers/local-strapi-source-provider/links/utils.d.ts +27 -0
- package/dist/providers/local-strapi-source-provider/links/utils.js +155 -0
- package/dist/strategies/index.d.ts +7 -0
- package/dist/strategies/index.js +29 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +90 -0
- package/jest.config.js +12 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015-present Strapi Solutions SAS
|
|
2
|
+
|
|
3
|
+
Portions of the Strapi software are licensed as follows:
|
|
4
|
+
|
|
5
|
+
- All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE".
|
|
6
|
+
|
|
7
|
+
- All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below.
|
|
8
|
+
|
|
9
|
+
MIT Expat License
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDecryptionCipher = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
// different key values depending on algorithm chosen
|
|
6
|
+
const getDecryptionStrategy = (algorithm) => {
|
|
7
|
+
const strategies = {
|
|
8
|
+
'aes-128-ecb': (key) => {
|
|
9
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 16);
|
|
10
|
+
const initVector = null;
|
|
11
|
+
const securityKey = hashedKey;
|
|
12
|
+
return (0, crypto_1.createDecipheriv)(algorithm, securityKey, initVector);
|
|
13
|
+
},
|
|
14
|
+
aes128: (key) => {
|
|
15
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 32);
|
|
16
|
+
const initVector = hashedKey.slice(16);
|
|
17
|
+
const securityKey = hashedKey.slice(0, 16);
|
|
18
|
+
return (0, crypto_1.createDecipheriv)(algorithm, securityKey, initVector);
|
|
19
|
+
},
|
|
20
|
+
aes192: (key) => {
|
|
21
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 40);
|
|
22
|
+
const initVector = hashedKey.slice(24);
|
|
23
|
+
const securityKey = hashedKey.slice(0, 24);
|
|
24
|
+
return (0, crypto_1.createDecipheriv)(algorithm, securityKey, initVector);
|
|
25
|
+
},
|
|
26
|
+
aes256: (key) => {
|
|
27
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 48);
|
|
28
|
+
const initVector = hashedKey.slice(32);
|
|
29
|
+
const securityKey = hashedKey.slice(0, 32);
|
|
30
|
+
return (0, crypto_1.createDecipheriv)(algorithm, securityKey, initVector);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return strategies[algorithm];
|
|
34
|
+
};
|
|
35
|
+
const createDecryptionCipher = (key, algorithm = 'aes-128-ecb') => {
|
|
36
|
+
return getDecryptionStrategy(algorithm)(key);
|
|
37
|
+
};
|
|
38
|
+
exports.createDecryptionCipher = createDecryptionCipher;
|
|
39
|
+
//# sourceMappingURL=decrypt.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createEncryptionCipher = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
// different key values depending on algorithm chosen
|
|
6
|
+
const getEncryptionStrategy = (algorithm) => {
|
|
7
|
+
const strategies = {
|
|
8
|
+
'aes-128-ecb': (key) => {
|
|
9
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 16);
|
|
10
|
+
const initVector = null;
|
|
11
|
+
const securityKey = hashedKey;
|
|
12
|
+
return (0, crypto_1.createCipheriv)(algorithm, securityKey, initVector);
|
|
13
|
+
},
|
|
14
|
+
aes128: (key) => {
|
|
15
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 32);
|
|
16
|
+
const initVector = hashedKey.slice(16);
|
|
17
|
+
const securityKey = hashedKey.slice(0, 16);
|
|
18
|
+
return (0, crypto_1.createCipheriv)(algorithm, securityKey, initVector);
|
|
19
|
+
},
|
|
20
|
+
aes192: (key) => {
|
|
21
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 40);
|
|
22
|
+
const initVector = hashedKey.slice(24);
|
|
23
|
+
const securityKey = hashedKey.slice(0, 24);
|
|
24
|
+
return (0, crypto_1.createCipheriv)(algorithm, securityKey, initVector);
|
|
25
|
+
},
|
|
26
|
+
aes256: (key) => {
|
|
27
|
+
const hashedKey = (0, crypto_1.scryptSync)(key, '', 48);
|
|
28
|
+
const initVector = hashedKey.slice(32);
|
|
29
|
+
const securityKey = hashedKey.slice(0, 32);
|
|
30
|
+
return (0, crypto_1.createCipheriv)(algorithm, securityKey, initVector);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return strategies[algorithm];
|
|
34
|
+
};
|
|
35
|
+
const createEncryptionCipher = (key, algorithm = 'aes-128-ecb') => {
|
|
36
|
+
return getEncryptionStrategy(algorithm)(key);
|
|
37
|
+
};
|
|
38
|
+
exports.createEncryptionCipher = createEncryptionCipher;
|
|
39
|
+
//# sourceMappingURL=encrypt.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./encrypt"), exports);
|
|
18
|
+
__exportStar(require("./decrypt"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { PassThrough } from 'stream-chain';
|
|
3
|
+
import type { IDestinationProvider, ISourceProvider, ITransferEngine, ITransferEngineOptions, ITransferResults } from '../../types';
|
|
4
|
+
declare type TransferEngineProgress = {
|
|
5
|
+
data: any;
|
|
6
|
+
stream: PassThrough;
|
|
7
|
+
};
|
|
8
|
+
export declare const VALID_STRATEGIES: string[];
|
|
9
|
+
declare class TransferEngine<S extends ISourceProvider = ISourceProvider, D extends IDestinationProvider = IDestinationProvider> implements ITransferEngine {
|
|
10
|
+
#private;
|
|
11
|
+
sourceProvider: ISourceProvider;
|
|
12
|
+
destinationProvider: IDestinationProvider;
|
|
13
|
+
options: ITransferEngineOptions;
|
|
14
|
+
get progress(): TransferEngineProgress;
|
|
15
|
+
constructor(sourceProvider: ISourceProvider, destinationProvider: IDestinationProvider, options: ITransferEngineOptions);
|
|
16
|
+
init(): Promise<void>;
|
|
17
|
+
bootstrap(): Promise<void>;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
integrityCheck(): Promise<boolean>;
|
|
20
|
+
validateTransferOptions(): void;
|
|
21
|
+
transfer(): Promise<ITransferResults<S, D>>;
|
|
22
|
+
transferSchemas(): Promise<void>;
|
|
23
|
+
transferEntities(): Promise<void>;
|
|
24
|
+
transferLinks(): Promise<void>;
|
|
25
|
+
transferMedia(): Promise<void>;
|
|
26
|
+
transferConfiguration(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export declare const createTransferEngine: <S extends ISourceProvider = ISourceProvider, D extends IDestinationProvider = IDestinationProvider>(sourceProvider: S, destinationProvider: D, options: ITransferEngineOptions) => TransferEngine<S, D>;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,324 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
var _TransferEngine_instances, _TransferEngine_metadata, _TransferEngine_transferProgress, _TransferEngine_progressStream, _TransferEngine_increaseTransferProgress, _TransferEngine_countRecorder, _TransferEngine_updateStage, _TransferEngine_assertStrapiVersionIntegrity, _TransferEngine_assertSchemasMatching, _TransferEngine_resolveProviderResource;
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createTransferEngine = exports.VALID_STRATEGIES = void 0;
|
|
13
|
+
const stream_chain_1 = require("stream-chain");
|
|
14
|
+
const fp_1 = require("lodash/fp");
|
|
15
|
+
const semverDiff = require('semver/functions/diff');
|
|
16
|
+
const strategies_1 = __importDefault(require("../strategies"));
|
|
17
|
+
exports.VALID_STRATEGIES = ['restore', 'merge'];
|
|
18
|
+
class TransferEngine {
|
|
19
|
+
constructor(sourceProvider, destinationProvider, options) {
|
|
20
|
+
_TransferEngine_instances.add(this);
|
|
21
|
+
_TransferEngine_metadata.set(this, {});
|
|
22
|
+
_TransferEngine_transferProgress.set(this, {});
|
|
23
|
+
// TODO: Type the stream chunks. Doesn't seem trivial, especially since PassThrough doesn't provide a PassThroughOptions type
|
|
24
|
+
_TransferEngine_progressStream.set(this, new stream_chain_1.PassThrough({ objectMode: true }));
|
|
25
|
+
_TransferEngine_countRecorder.set(this, (transferStage, aggregateKey) => {
|
|
26
|
+
return new stream_chain_1.PassThrough({
|
|
27
|
+
objectMode: true,
|
|
28
|
+
transform: (data, _encoding, callback) => {
|
|
29
|
+
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_increaseTransferProgress).call(this, transferStage, data, aggregateKey);
|
|
30
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'progress', transferStage);
|
|
31
|
+
callback(null, data);
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
_TransferEngine_updateStage.set(this, (type, transferStage) => {
|
|
36
|
+
__classPrivateFieldGet(this, _TransferEngine_progressStream, "f").emit(type, {
|
|
37
|
+
data: __classPrivateFieldGet(this, _TransferEngine_transferProgress, "f"),
|
|
38
|
+
stage: transferStage,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
if (sourceProvider.type !== 'source') {
|
|
42
|
+
throw new Error("SourceProvider does not have type 'source'");
|
|
43
|
+
}
|
|
44
|
+
if (destinationProvider.type !== 'destination') {
|
|
45
|
+
throw new Error("DestinationProvider does not have type 'destination'");
|
|
46
|
+
}
|
|
47
|
+
this.sourceProvider = sourceProvider;
|
|
48
|
+
this.destinationProvider = destinationProvider;
|
|
49
|
+
this.options = options;
|
|
50
|
+
}
|
|
51
|
+
get progress() {
|
|
52
|
+
return {
|
|
53
|
+
data: __classPrivateFieldGet(this, _TransferEngine_transferProgress, "f"),
|
|
54
|
+
stream: __classPrivateFieldGet(this, _TransferEngine_progressStream, "f"),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async init() {
|
|
58
|
+
// Resolve providers' resource and store
|
|
59
|
+
// them in the engine's internal state
|
|
60
|
+
await __classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_resolveProviderResource).call(this);
|
|
61
|
+
// Update the destination provider's source metadata
|
|
62
|
+
const { source: sourceMetadata } = __classPrivateFieldGet(this, _TransferEngine_metadata, "f");
|
|
63
|
+
if (sourceMetadata) {
|
|
64
|
+
this.destinationProvider.setMetadata?.('source', sourceMetadata);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async bootstrap() {
|
|
68
|
+
await Promise.all([this.sourceProvider.bootstrap?.(), this.destinationProvider.bootstrap?.()]);
|
|
69
|
+
}
|
|
70
|
+
async close() {
|
|
71
|
+
await Promise.all([this.sourceProvider.close?.(), this.destinationProvider.close?.()]);
|
|
72
|
+
}
|
|
73
|
+
async integrityCheck() {
|
|
74
|
+
try {
|
|
75
|
+
const sourceMetadata = await this.sourceProvider.getMetadata();
|
|
76
|
+
const destinationMetadata = await this.destinationProvider.getMetadata();
|
|
77
|
+
if (sourceMetadata && destinationMetadata) {
|
|
78
|
+
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_assertStrapiVersionIntegrity).call(this, sourceMetadata?.strapi?.version, destinationMetadata?.strapi?.version);
|
|
79
|
+
}
|
|
80
|
+
const sourceSchemas = await this.sourceProvider.getSchemas?.();
|
|
81
|
+
const destinationSchemas = await this.destinationProvider.getSchemas?.();
|
|
82
|
+
if (sourceSchemas && destinationSchemas) {
|
|
83
|
+
__classPrivateFieldGet(this, _TransferEngine_instances, "m", _TransferEngine_assertSchemasMatching).call(this, sourceSchemas, destinationSchemas);
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
validateTransferOptions() {
|
|
92
|
+
if (!exports.VALID_STRATEGIES.includes(this.options.strategy)) {
|
|
93
|
+
throw new Error('Invalid stategy ' + this.options.strategy);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async transfer() {
|
|
97
|
+
try {
|
|
98
|
+
this.validateTransferOptions();
|
|
99
|
+
await this.bootstrap();
|
|
100
|
+
await this.init();
|
|
101
|
+
const isValidTransfer = await this.integrityCheck();
|
|
102
|
+
if (!isValidTransfer) {
|
|
103
|
+
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.`);
|
|
104
|
+
}
|
|
105
|
+
// Run the transfer stages
|
|
106
|
+
await this.transferSchemas();
|
|
107
|
+
await this.transferEntities();
|
|
108
|
+
await this.transferMedia();
|
|
109
|
+
await this.transferLinks();
|
|
110
|
+
await this.transferConfiguration();
|
|
111
|
+
// Gracefully close the providers
|
|
112
|
+
await this.close();
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
// Rollback the destination provider if an exception is thrown during the transfer
|
|
116
|
+
// Note: This will be configurable in the future
|
|
117
|
+
await this.destinationProvider.rollback?.(e);
|
|
118
|
+
throw e;
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
source: this.sourceProvider.results,
|
|
122
|
+
destination: this.destinationProvider.results,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
async transferSchemas() {
|
|
126
|
+
const stageName = 'schemas';
|
|
127
|
+
const inStream = await this.sourceProvider.streamSchemas?.();
|
|
128
|
+
if (!inStream) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const outStream = await this.destinationProvider.getSchemasStream?.();
|
|
132
|
+
if (!outStream) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'start', stageName);
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
inStream
|
|
138
|
+
// Throw on error in the source
|
|
139
|
+
.on('error', reject);
|
|
140
|
+
outStream
|
|
141
|
+
// Throw on error in the destination
|
|
142
|
+
.on('error', reject)
|
|
143
|
+
// Resolve the promise when the destination has finished reading all the data from the source
|
|
144
|
+
.on('close', () => {
|
|
145
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'complete', stageName);
|
|
146
|
+
resolve();
|
|
147
|
+
});
|
|
148
|
+
inStream.pipe(__classPrivateFieldGet(this, _TransferEngine_countRecorder, "f").call(this, stageName)).pipe(outStream);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async transferEntities() {
|
|
152
|
+
const stageName = 'entities';
|
|
153
|
+
const inStream = await this.sourceProvider.streamEntities?.();
|
|
154
|
+
if (!inStream) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const outStream = await this.destinationProvider.getEntitiesStream?.();
|
|
158
|
+
if (!outStream) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'start', stageName);
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
inStream
|
|
164
|
+
// Throw on error in the source
|
|
165
|
+
.on('error', (e) => {
|
|
166
|
+
reject(e);
|
|
167
|
+
});
|
|
168
|
+
outStream
|
|
169
|
+
// Throw on error in the destination
|
|
170
|
+
.on('error', (e) => {
|
|
171
|
+
reject(e);
|
|
172
|
+
})
|
|
173
|
+
// Resolve the promise when the destination has finished reading all the data from the source
|
|
174
|
+
.on('close', () => {
|
|
175
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'complete', stageName);
|
|
176
|
+
resolve();
|
|
177
|
+
});
|
|
178
|
+
inStream.pipe(__classPrivateFieldGet(this, _TransferEngine_countRecorder, "f").call(this, stageName, 'type')).pipe(outStream);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async transferLinks() {
|
|
182
|
+
const stageName = 'links';
|
|
183
|
+
const inStream = await this.sourceProvider.streamLinks?.();
|
|
184
|
+
if (!inStream) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const outStream = await this.destinationProvider.getLinksStream?.();
|
|
188
|
+
if (!outStream) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'start', 'links');
|
|
192
|
+
return new Promise((resolve, reject) => {
|
|
193
|
+
inStream
|
|
194
|
+
// Throw on error in the source
|
|
195
|
+
.on('error', reject);
|
|
196
|
+
outStream
|
|
197
|
+
// Throw on error in the destination
|
|
198
|
+
.on('error', reject)
|
|
199
|
+
// Resolve the promise when the destination has finished reading all the data from the source
|
|
200
|
+
.on('close', () => {
|
|
201
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'complete', stageName);
|
|
202
|
+
resolve();
|
|
203
|
+
});
|
|
204
|
+
inStream.pipe(__classPrivateFieldGet(this, _TransferEngine_countRecorder, "f").call(this, stageName)).pipe(outStream);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
async transferMedia() {
|
|
208
|
+
const stageName = 'media';
|
|
209
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'start', stageName);
|
|
210
|
+
console.warn('transferMedia not yet implemented');
|
|
211
|
+
return new Promise((resolve) => (() => {
|
|
212
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'complete', stageName);
|
|
213
|
+
resolve();
|
|
214
|
+
})());
|
|
215
|
+
}
|
|
216
|
+
async transferConfiguration() {
|
|
217
|
+
const stageName = 'configuration';
|
|
218
|
+
const inStream = await this.sourceProvider.streamConfiguration?.();
|
|
219
|
+
if (!inStream) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const outStream = await this.destinationProvider.getConfigurationStream?.();
|
|
223
|
+
if (!outStream) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'start', stageName);
|
|
227
|
+
return new Promise((resolve, reject) => {
|
|
228
|
+
inStream
|
|
229
|
+
// Throw on error in the source
|
|
230
|
+
.on('error', reject);
|
|
231
|
+
outStream
|
|
232
|
+
// Throw on error in the destination
|
|
233
|
+
.on('error', reject)
|
|
234
|
+
// Resolve the promise when the destination has finished reading all the data from the source
|
|
235
|
+
.on('close', () => {
|
|
236
|
+
__classPrivateFieldGet(this, _TransferEngine_updateStage, "f").call(this, 'complete', stageName);
|
|
237
|
+
resolve();
|
|
238
|
+
});
|
|
239
|
+
inStream.pipe(__classPrivateFieldGet(this, _TransferEngine_countRecorder, "f").call(this, stageName)).pipe(outStream);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
_TransferEngine_metadata = new WeakMap(), _TransferEngine_transferProgress = new WeakMap(), _TransferEngine_progressStream = new WeakMap(), _TransferEngine_countRecorder = new WeakMap(), _TransferEngine_updateStage = new WeakMap(), _TransferEngine_instances = new WeakSet(), _TransferEngine_increaseTransferProgress = function _TransferEngine_increaseTransferProgress(transferStage, data, aggregateKey) {
|
|
244
|
+
if (!__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage]) {
|
|
245
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage] = { count: 0, bytes: 0 };
|
|
246
|
+
}
|
|
247
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].count += 1;
|
|
248
|
+
const size = JSON.stringify(data).length;
|
|
249
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].bytes += size;
|
|
250
|
+
if (aggregateKey && data && data[aggregateKey]) {
|
|
251
|
+
const aggKeyValue = data[aggregateKey];
|
|
252
|
+
if (!__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage]['aggregates']) {
|
|
253
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].aggregates = {};
|
|
254
|
+
}
|
|
255
|
+
if (!(__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].aggregates &&
|
|
256
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].aggregates[aggKeyValue])) {
|
|
257
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].aggregates[aggKeyValue] = { count: 0, bytes: 0 };
|
|
258
|
+
}
|
|
259
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].aggregates[aggKeyValue].count += 1;
|
|
260
|
+
__classPrivateFieldGet(this, _TransferEngine_transferProgress, "f")[transferStage].aggregates[aggKeyValue].bytes += size;
|
|
261
|
+
}
|
|
262
|
+
}, _TransferEngine_assertStrapiVersionIntegrity = function _TransferEngine_assertStrapiVersionIntegrity(sourceVersion, destinationVersion) {
|
|
263
|
+
const strategy = this.options.versionMatching;
|
|
264
|
+
if (!sourceVersion ||
|
|
265
|
+
!destinationVersion ||
|
|
266
|
+
strategy === 'ignore' ||
|
|
267
|
+
destinationVersion === sourceVersion) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
let diff;
|
|
271
|
+
try {
|
|
272
|
+
diff = semverDiff(sourceVersion, destinationVersion);
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
throw new Error(`Strapi versions doesn't match (${strategy} check): ${sourceVersion} does not match with ${destinationVersion}`);
|
|
276
|
+
}
|
|
277
|
+
if (!diff) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const validPatch = ['prelease', 'build'];
|
|
281
|
+
const validMinor = [...validPatch, 'patch', 'prepatch'];
|
|
282
|
+
const validMajor = [...validMinor, 'minor', 'preminor'];
|
|
283
|
+
if (strategy === 'patch' && validPatch.includes(diff)) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (strategy === 'minor' && validMinor.includes(diff)) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (strategy === 'major' && validMajor.includes(diff)) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
throw new Error(`Strapi versions doesn't match (${strategy} check): ${sourceVersion} does not match with ${destinationVersion}`);
|
|
293
|
+
}, _TransferEngine_assertSchemasMatching = function _TransferEngine_assertSchemasMatching(sourceSchemas, destinationSchemas) {
|
|
294
|
+
const strategy = this.options.schemasMatching || 'strict';
|
|
295
|
+
const keys = (0, fp_1.uniq)(Object.keys(sourceSchemas).concat(Object.keys(destinationSchemas)));
|
|
296
|
+
const diffs = {};
|
|
297
|
+
keys.forEach((key) => {
|
|
298
|
+
const sourceSchema = sourceSchemas[key];
|
|
299
|
+
const destinationSchema = destinationSchemas[key];
|
|
300
|
+
const schemaDiffs = (0, strategies_1.default)(sourceSchema, destinationSchema, strategy);
|
|
301
|
+
if (schemaDiffs.length) {
|
|
302
|
+
diffs[key] = schemaDiffs;
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
if (!(0, fp_1.isEmpty)(diffs)) {
|
|
306
|
+
throw new Error(`Import process failed because the project doesn't have a matching data structure
|
|
307
|
+
${JSON.stringify(diffs, null, 2)}
|
|
308
|
+
`);
|
|
309
|
+
}
|
|
310
|
+
}, _TransferEngine_resolveProviderResource = async function _TransferEngine_resolveProviderResource() {
|
|
311
|
+
const sourceMetadata = await this.sourceProvider.getMetadata();
|
|
312
|
+
const destinationMetadata = await this.destinationProvider.getMetadata();
|
|
313
|
+
if (sourceMetadata) {
|
|
314
|
+
__classPrivateFieldGet(this, _TransferEngine_metadata, "f").source = sourceMetadata;
|
|
315
|
+
}
|
|
316
|
+
if (destinationMetadata) {
|
|
317
|
+
__classPrivateFieldGet(this, _TransferEngine_metadata, "f").destination = destinationMetadata;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const createTransferEngine = (sourceProvider, destinationProvider, options) => {
|
|
321
|
+
return new TransferEngine(sourceProvider, destinationProvider, options);
|
|
322
|
+
};
|
|
323
|
+
exports.createTransferEngine = createTransferEngine;
|
|
324
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./engine"), exports);
|
|
18
|
+
__exportStar(require("./providers"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// source providers
|
|
18
|
+
__exportStar(require("./local-file-source-provider"), exports);
|
|
19
|
+
__exportStar(require("./local-strapi-source-provider"), exports);
|
|
20
|
+
// destination providers
|
|
21
|
+
__exportStar(require("./local-file-destination-provider"), exports);
|
|
22
|
+
__exportStar(require("./local-strapi-destination-provider"), exports);
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/// <reference types="stream-chain" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import type { IDestinationProvider, IDestinationProviderTransferResults, IMetadata, ProviderType } from '../../types';
|
|
4
|
+
export interface ILocalFileDestinationProviderOptions {
|
|
5
|
+
encryption: {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
key?: string;
|
|
8
|
+
};
|
|
9
|
+
compression: {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
};
|
|
12
|
+
file: {
|
|
13
|
+
path: string;
|
|
14
|
+
maxSize?: number;
|
|
15
|
+
maxSizeJsonl?: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface ILocalFileDestinationProviderTransferResults extends IDestinationProviderTransferResults {
|
|
19
|
+
file?: {
|
|
20
|
+
path?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export declare const createLocalFileDestinationProvider: (options: ILocalFileDestinationProviderOptions) => LocalFileDestinationProvider;
|
|
24
|
+
declare class LocalFileDestinationProvider implements IDestinationProvider {
|
|
25
|
+
#private;
|
|
26
|
+
name: string;
|
|
27
|
+
type: ProviderType;
|
|
28
|
+
options: ILocalFileDestinationProviderOptions;
|
|
29
|
+
results: ILocalFileDestinationProviderTransferResults;
|
|
30
|
+
constructor(options: ILocalFileDestinationProviderOptions);
|
|
31
|
+
setMetadata(target: ProviderType, metadata: IMetadata): IDestinationProvider;
|
|
32
|
+
bootstrap(): void | Promise<void>;
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
rollback(): Promise<void>;
|
|
35
|
+
getMetadata(): null;
|
|
36
|
+
getSchemasStream(): import("stream-chain");
|
|
37
|
+
getEntitiesStream(): NodeJS.WritableStream;
|
|
38
|
+
getLinksStream(): NodeJS.WritableStream;
|
|
39
|
+
getConfigurationStream(): NodeJS.WritableStream;
|
|
40
|
+
}
|
|
41
|
+
export {};
|