@strapi/data-transfer
Version:
Data transfer capabilities for Strapi
249 lines (245 loc) • 10.8 kB
JavaScript
'use strict';
var path = require('path');
var zip = require('zlib');
var stream = require('stream');
var fse = require('fs-extra');
var tar = require('tar-stream');
var Stringer = require('stream-json/jsonl/Stringer');
var streamChain = require('stream-chain');
var encrypt = require('../../../utils/encryption/encrypt.js');
require('crypto');
var utils = require('./utils.js');
var providers = require('../../../errors/providers.js');
function _class_private_field_loose_base(receiver, privateKey) {
if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
throw new TypeError("attempted to use private field on non-instance");
}
return receiver;
}
var id = 0;
function _class_private_field_loose_key(name) {
return "__private_" + id++ + "_" + name;
}
const createLocalFileDestinationProvider = (options)=>{
return new LocalFileDestinationProvider(options);
};
var _providersMetadata = /*#__PURE__*/ _class_private_field_loose_key("_providersMetadata"), _archive = /*#__PURE__*/ _class_private_field_loose_key("_archive"), _diagnostics = /*#__PURE__*/ _class_private_field_loose_key("_diagnostics"), _reportInfo = /*#__PURE__*/ _class_private_field_loose_key("_reportInfo"), _archivePath = /*#__PURE__*/ _class_private_field_loose_key("_archivePath"), _writeMetadata = /*#__PURE__*/ _class_private_field_loose_key("_writeMetadata"), _getMetadataStream = /*#__PURE__*/ _class_private_field_loose_key("_getMetadataStream");
class LocalFileDestinationProvider {
setMetadata(target, metadata) {
_class_private_field_loose_base(this, _providersMetadata)[_providersMetadata][target] = metadata;
return this;
}
createGzip() {
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating gzip');
return zip.createGzip();
}
bootstrap(diagnostics) {
_class_private_field_loose_base(this, _diagnostics)[_diagnostics] = diagnostics;
const { compression, encryption } = this.options;
if (encryption.enabled && !encryption.key) {
throw new Error("Can't encrypt without a key");
}
_class_private_field_loose_base(this, _archive)[_archive].stream = tar.pack();
const outStream = fse.createWriteStream(_class_private_field_loose_base(this, _archivePath)[_archivePath]);
outStream.on('error', (err)=>{
if (err.code === 'ENOSPC') {
throw new providers.ProviderTransferError("Your server doesn't have space to proceed with the import.");
}
throw err;
});
const archiveTransforms = [];
if (compression.enabled) {
archiveTransforms.push(this.createGzip());
}
if (encryption.enabled && encryption.key) {
archiveTransforms.push(encrypt.createEncryptionCipher(encryption.key));
}
_class_private_field_loose_base(this, _archive)[_archive].pipeline = streamChain.chain([
_class_private_field_loose_base(this, _archive)[_archive].stream,
...archiveTransforms,
outStream
]);
this.results.file = {
path: _class_private_field_loose_base(this, _archivePath)[_archivePath]
};
}
async close() {
const { stream, pipeline } = _class_private_field_loose_base(this, _archive)[_archive];
if (!stream) {
return;
}
await _class_private_field_loose_base(this, _writeMetadata)[_writeMetadata]();
stream.finalize();
if (pipeline && !pipeline.closed) {
await new Promise((resolve, reject)=>{
pipeline.on('close', resolve).on('error', reject);
});
}
}
async rollback() {
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('rolling back');
await this.close();
await fse.rm(_class_private_field_loose_base(this, _archivePath)[_archivePath], {
force: true
});
}
getMetadata() {
return null;
}
createSchemasWriteStream() {
if (!_class_private_field_loose_base(this, _archive)[_archive].stream) {
throw new Error('Archive stream is unavailable');
}
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating schemas write stream');
const filePathFactory = utils.createFilePathFactory('schemas');
const entryStream = utils.createTarEntryStream(_class_private_field_loose_base(this, _archive)[_archive].stream, filePathFactory, this.options.file.maxSizeJsonl);
return streamChain.chain([
Stringer.stringer(),
entryStream
]);
}
createEntitiesWriteStream() {
if (!_class_private_field_loose_base(this, _archive)[_archive].stream) {
throw new Error('Archive stream is unavailable');
}
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating entities write stream');
const filePathFactory = utils.createFilePathFactory('entities');
const entryStream = utils.createTarEntryStream(_class_private_field_loose_base(this, _archive)[_archive].stream, filePathFactory, this.options.file.maxSizeJsonl);
return streamChain.chain([
Stringer.stringer(),
entryStream
]);
}
createLinksWriteStream() {
if (!_class_private_field_loose_base(this, _archive)[_archive].stream) {
throw new Error('Archive stream is unavailable');
}
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating links write stream');
const filePathFactory = utils.createFilePathFactory('links');
const entryStream = utils.createTarEntryStream(_class_private_field_loose_base(this, _archive)[_archive].stream, filePathFactory, this.options.file.maxSizeJsonl);
return streamChain.chain([
Stringer.stringer(),
entryStream
]);
}
createConfigurationWriteStream() {
if (!_class_private_field_loose_base(this, _archive)[_archive].stream) {
throw new Error('Archive stream is unavailable');
}
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating configuration write stream');
const filePathFactory = utils.createFilePathFactory('configuration');
const entryStream = utils.createTarEntryStream(_class_private_field_loose_base(this, _archive)[_archive].stream, filePathFactory, this.options.file.maxSizeJsonl);
return streamChain.chain([
Stringer.stringer(),
entryStream
]);
}
createAssetsWriteStream() {
const { stream: archiveStream } = _class_private_field_loose_base(this, _archive)[_archive];
if (!archiveStream) {
throw new Error('Archive stream is unavailable');
}
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating assets write stream');
return new stream.Writable({
objectMode: true,
write (data, _encoding, callback) {
// always write tar files with posix paths so we have a standard format for paths regardless of system
const entryPath = path.posix.join('assets', 'uploads', data.filename);
const entryMetadataPath = path.posix.join('assets', 'metadata', `${data.filename}.json`);
const stringifiedMetadata = JSON.stringify(data.metadata);
archiveStream.entry({
name: entryMetadataPath,
size: stringifiedMetadata.length
}, stringifiedMetadata);
const entry = archiveStream.entry({
name: entryPath,
size: data.stats.size
});
if (!entry) {
callback(new Error(`Failed to created an asset tar entry for ${entryPath}`));
return;
}
data.stream.pipe(entry);
entry.on('finish', ()=>{
callback(null);
}).on('error', (error)=>{
callback(error);
});
}
});
}
constructor(options){
Object.defineProperty(this, _reportInfo, {
value: reportInfo
});
Object.defineProperty(this, _archivePath, {
get: get_archivePath,
set: void 0
});
Object.defineProperty(this, _writeMetadata, {
value: writeMetadata
});
Object.defineProperty(this, _getMetadataStream, {
value: getMetadataStream
});
Object.defineProperty(this, _providersMetadata, {
writable: true,
value: void 0
});
Object.defineProperty(this, _archive, {
writable: true,
value: void 0
});
Object.defineProperty(this, _diagnostics, {
writable: true,
value: void 0
});
this.name = 'destination::local-file';
this.type = 'destination';
this.results = {};
_class_private_field_loose_base(this, _providersMetadata)[_providersMetadata] = {};
_class_private_field_loose_base(this, _archive)[_archive] = {};
this.options = options;
}
}
function reportInfo(message) {
_class_private_field_loose_base(this, _diagnostics)[_diagnostics]?.report({
details: {
createdAt: new Date(),
message,
origin: 'file-destination-provider'
},
kind: 'info'
});
}
function get_archivePath() {
const { encryption, compression, file } = this.options;
let filePath = `${file.path}.tar`;
if (compression.enabled) {
filePath += '.gz';
}
if (encryption.enabled) {
filePath += '.enc';
}
return filePath;
}
async function writeMetadata() {
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('writing metadata');
const metadata = _class_private_field_loose_base(this, _providersMetadata)[_providersMetadata].source;
if (metadata) {
await new Promise((resolve)=>{
const outStream = _class_private_field_loose_base(this, _getMetadataStream)[_getMetadataStream]();
const data = JSON.stringify(metadata, null, 2);
stream.Readable.from(data).pipe(outStream).on('close', resolve);
});
}
}
function getMetadataStream() {
const { stream } = _class_private_field_loose_base(this, _archive)[_archive];
if (!stream) {
throw new Error('Archive stream is unavailable');
}
return utils.createTarEntryStream(stream, ()=>'metadata.json');
}
exports.createLocalFileDestinationProvider = createLocalFileDestinationProvider;
//# sourceMappingURL=index.js.map