@lyra/export
Version:
Export Lyra documents and assets
187 lines (154 loc) • 6.29 kB
JavaScript
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
const os = require('os');
const path = require('path');
const zlib = require('zlib');
const fse = require('fs-extra');
const miss = require('mississippi');
const split = require('split2');
const archiver = require('archiver');
const debug = require('./debug');
const AssetHandler = require('./AssetHandler');
const stringifyStream = require('./stringifyStream');
const validateOptions = require('./validateOptions');
const rejectOnApiError = require('./rejectOnApiError');
const getDocumentsStream = require('./getDocumentsStream');
const filterSystemDocuments = require('./filterSystemDocuments');
const filterDocumentTypes = require('./filterDocumentTypes');
const filterDrafts = require('./filterDrafts');
const noop = () => null;
function exportDataset(opts) {
const options = validateOptions(opts);
const onProgress = options.onProgress || noop;
const archive = archiver('tar', {
gzip: true,
gzipOptions: {
level: options.compress ? zlib.Z_DEFAULT_COMPRESSION : zlib.Z_NO_COMPRESSION
}
});
const slugDate = new Date().toISOString().replace(/[^a-z0-9]/gi, '-').toLowerCase();
const prefix = `${opts.dataset}-export-${slugDate}`;
const tmpDir = path.join(os.tmpdir(), prefix);
const assetHandler = new AssetHandler({
client: options.client,
tmpDir,
prefix
});
debug('Outputting assets (temporarily) to %s', tmpDir);
debug('Outputting to %s', options.outputPath === '-' ? 'stdout' : options.outputPath);
const outputStream = options.outputPath === '-' ? process.stdout : fse.createWriteStream(options.outputPath);
let assetStreamHandler = assetHandler.noop;
if (!options.raw) {
assetStreamHandler = options.assets ? assetHandler.rewriteAssets : assetHandler.stripAssets;
}
return new Promise((() => {
var _ref = _asyncToGenerator(function* (resolve, reject) {
let onComplete = (() => {
var _ref3 = _asyncToGenerator(function* (err) {
onProgress({ step: 'Clearing temporary files...' });
yield fse.remove(tmpDir);
if (!err) {
resolve();
return;
}
debug('Error during streaming: %s', err.stack);
assetHandler.clear();
reject(err);
});
return function onComplete(_x4) {
return _ref3.apply(this, arguments);
};
})();
miss.finished(archive, function (archiveErr) {
if (archiveErr) {
debug('Archiving errored! %s', archiveErr.stack);
reject(archiveErr);
return;
}
debug('Archive finished!');
});
debug('Getting dataset export stream');
onProgress({ step: 'Exporting documents...' });
let documentCount = 0;
let lastReported = Date.now();
const reportDocumentCount = function reportDocumentCount(chunk, enc, cb) {
++documentCount;
const now = Date.now();
if (now - lastReported > 50) {
onProgress({
step: 'Exporting documents...',
current: documentCount,
total: '?',
update: true
});
lastReported = now;
}
cb(null, chunk);
};
const inputStream = yield getDocumentsStream(options.client, options.dataset);
const jsonStream = miss.pipeline(inputStream, split(JSON.parse), rejectOnApiError, filterSystemDocuments, assetStreamHandler, filterDocumentTypes(options.types), options.drafts ? miss.through.obj() : filterDrafts, stringifyStream, miss.through(reportDocumentCount));
miss.finished(jsonStream, (() => {
var _ref2 = _asyncToGenerator(function* (err) {
if (err) {
return;
}
onProgress({
step: 'Exporting documents...',
current: documentCount,
total: documentCount,
update: true
});
if (!options.raw && options.assets) {
onProgress({ step: 'Downloading assets...' });
}
let prevCompleted = 0;
const progressInterval = setInterval(function () {
const completed = assetHandler.queueSize - assetHandler.queue.size;
if (prevCompleted === completed) {
return;
}
prevCompleted = completed;
onProgress({
step: 'Downloading assets...',
current: completed,
total: assetHandler.queueSize,
update: true
});
}, 500);
debug('Waiting for asset handler to complete downloads');
try {
const assetMap = yield assetHandler.finish();
archive.append(JSON.stringify(assetMap), { name: 'assets.json', prefix });
clearInterval(progressInterval);
} catch (assetErr) {
clearInterval(progressInterval);
reject(assetErr);
return;
}
// Add all downloaded assets to archive
archive.directory(path.join(tmpDir, 'files'), `${prefix}/files`, {
store: true
});
archive.directory(path.join(tmpDir, 'images'), `${prefix}/images`, {
store: true
});
debug('Finalizing archive, flushing streams');
onProgress({ step: 'Adding assets to archive...' });
archive.finalize();
});
return function (_x3) {
return _ref2.apply(this, arguments);
};
})());
archive.on('warning', function (err) {
debug('Archive warning: %s', err.message);
});
archive.append(jsonStream, { name: 'data.ndjson', prefix });
miss.pipe(archive, outputStream, onComplete);
});
return function (_x, _x2) {
return _ref.apply(this, arguments);
};
})());
}
module.exports = exportDataset;
;