|
|
@@ -29,6 +29,29 @@ class ExportService {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * dump a collection into json
|
|
|
+ *
|
|
|
+ * @memberOf ExportService
|
|
|
+ * @return {object} cache info for exported zip files
|
|
|
+ */
|
|
|
+ getStatus() {
|
|
|
+ const status = {};
|
|
|
+ const collections = Object.keys(this.files);
|
|
|
+ collections.forEach((file) => {
|
|
|
+ status[path.basename(file, '.zip')] = null;
|
|
|
+ });
|
|
|
+
|
|
|
+ // extract ${collectionName}.zip
|
|
|
+ const files = fs.readdirSync(this.baseDir).filter((file) => { return path.extname(file) === '.zip' && collections.includes(path.basename(file, '.zip')) });
|
|
|
+
|
|
|
+ files.forEach((file) => {
|
|
|
+ status[path.basename(file, '.zip')] = file;
|
|
|
+ });
|
|
|
+
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* dump a collection into json
|
|
|
*
|
|
|
@@ -41,6 +64,9 @@ class ExportService {
|
|
|
let n = 0;
|
|
|
const ws = fs.createWriteStream(file, { encoding: this.encoding });
|
|
|
|
|
|
+ // open an array
|
|
|
+ ws.write('[');
|
|
|
+
|
|
|
readStream.on('data', (chunk) => {
|
|
|
if (n !== 0) ws.write(',');
|
|
|
ws.write(JSON.stringify(chunk));
|
|
|
@@ -54,12 +80,31 @@ class ExportService {
|
|
|
ws.close();
|
|
|
});
|
|
|
|
|
|
- // open an array
|
|
|
- ws.write('[');
|
|
|
-
|
|
|
await streamToPromise(readStream);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * dump a mongodb collection into json
|
|
|
+ *
|
|
|
+ * @memberOf ExportService
|
|
|
+ * @param {object} Model instance of mongoose model
|
|
|
+ * @return {string} path to zip file
|
|
|
+ */
|
|
|
+ async exportCollection(Model) {
|
|
|
+ const modelName = Model.collection.collectionName;
|
|
|
+ const file = this.files[modelName];
|
|
|
+ const total = await Model.countDocuments();
|
|
|
+ const readStream = Model.find().cursor();
|
|
|
+
|
|
|
+ await this.export(file, readStream, total);
|
|
|
+
|
|
|
+ const { file: zipFile, size } = await this.zipSingleFile(file);
|
|
|
+
|
|
|
+ logger.info(`exported ${modelName} collection into ${zipFile} (${size} bytes)`);
|
|
|
+
|
|
|
+ return zipFile;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* log export progress
|
|
|
*
|
|
|
@@ -89,9 +134,10 @@ class ExportService {
|
|
|
* @param {string} from path to input file
|
|
|
* @param {string} [to=`${path.join(path.dirname(from), `${path.basename(from, path.extname(from))}.zip`)}`] path to output file
|
|
|
* @param {string} [as=path.basename(from)] file name after unzipped
|
|
|
+ * @return {object} file path and file size
|
|
|
* @see https://www.archiverjs.com/#quick-start
|
|
|
*/
|
|
|
- async zipSingleFile(from, to = `${path.join(path.dirname(from), `${path.basename(from, path.extname(from))}.zip`)}`, as = path.basename(from)) {
|
|
|
+ async zipSingleFile(from, to = this.replaceExtension(from, 'zip'), as = path.basename(from)) {
|
|
|
const archive = archiver('zip', {
|
|
|
zlib: { level: this.zlibLevel },
|
|
|
});
|
|
|
@@ -126,22 +172,32 @@ class ExportService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * dump a mongodb collection into json
|
|
|
+ * replace a file extension
|
|
|
*
|
|
|
* @memberOf ExportService
|
|
|
- * @param {object} Model instance of mongoose model
|
|
|
+ * @param {string} file file path
|
|
|
+ * @param {string} extension new extension
|
|
|
+ * @return {string} path to file with new extension
|
|
|
*/
|
|
|
- async exportCollection(Model) {
|
|
|
- const modelName = Model.collection.collectionName;
|
|
|
- const file = this.files[modelName];
|
|
|
- const total = await Model.countDocuments();
|
|
|
- const readStream = Model.find().cursor();
|
|
|
-
|
|
|
- await this.export(file, readStream, total);
|
|
|
+ replaceExtension(file, extension) {
|
|
|
+ return `${path.join(path.dirname(file), `${path.basename(file, path.extname(file))}.${extension}`)}`;
|
|
|
+ }
|
|
|
|
|
|
- const { file: zipFile, size } = await this.zipSingleFile(file);
|
|
|
+ /**
|
|
|
+ * get the path to the zipped file for a collection
|
|
|
+ *
|
|
|
+ * @memberOf ExportService
|
|
|
+ * @param {object} Model instance of mongoose model
|
|
|
+ * @return {string} path to zip file
|
|
|
+ */
|
|
|
+ getZipFile(Model) {
|
|
|
+ const json = this.files[Model.collection.collectionName];
|
|
|
+ const zip = this.replaceExtension(json, 'zip');
|
|
|
+ if (!fs.existsSync(zip)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
- logger.info(`exported ${modelName} collection into ${zipFile} (${size} bytes)`);
|
|
|
+ return zip;
|
|
|
}
|
|
|
|
|
|
}
|