2
0

growi-bridge.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. const logger = require('@alias/logger')('growi:services:GrowiBridgeService'); // eslint-disable-line no-unused-vars
  2. const fs = require('fs');
  3. const path = require('path');
  4. const streamToPromise = require('stream-to-promise');
  5. const unzipper = require('unzipper');
  6. /**
  7. * the service class for bridging GROWIs (export and import)
  8. * common properties and methods between export service and import service are defined in this service
  9. */
  10. class GrowiBridgeService {
  11. constructor(crowi) {
  12. this.encoding = 'utf-8';
  13. this.metaFileName = 'meta.json';
  14. // { pages: Page, users: User, ... }
  15. this.collectionMap = {};
  16. this.initCollectionMap(crowi.models);
  17. }
  18. /**
  19. * initialize collection map
  20. *
  21. * @memberOf GrowiBridgeService
  22. * @param {object} models from models/index.js
  23. */
  24. initCollectionMap(models) {
  25. for (const model of Object.values(models)) {
  26. if (model.collection != null) {
  27. this.collectionMap[model.collection.name] = model;
  28. }
  29. }
  30. }
  31. /**
  32. * getter for encoding
  33. *
  34. * @memberOf GrowiBridgeService
  35. * @return {string} encoding
  36. */
  37. getEncoding() {
  38. return this.encoding;
  39. }
  40. /**
  41. * getter for metaFileName
  42. *
  43. * @memberOf GrowiBridgeService
  44. * @return {string} base name of meta file
  45. */
  46. getMetaFileName() {
  47. return this.metaFileName;
  48. }
  49. /**
  50. * get a model from collection name
  51. *
  52. * @memberOf GrowiBridgeService
  53. * @param {string} collectionName collection name
  54. * @return {object} instance of mongoose model
  55. */
  56. getModelFromCollectionName(collectionName) {
  57. const Model = this.collectionMap[collectionName];
  58. if (Model == null) {
  59. throw new Error(`cannot find a model for collection name "${collectionName}"`);
  60. }
  61. return Model;
  62. }
  63. /**
  64. * get the absolute path to a file
  65. * this method must must be bound to the caller (this.baseDir is undefined in this service)
  66. *
  67. * @memberOf GrowiBridgeService
  68. * @param {string} fileName base name of file
  69. * @return {string} absolute path to the file
  70. */
  71. getFile(fileName) {
  72. if (this.baseDir == null) {
  73. throw new Error('baseDir is not defined');
  74. }
  75. const jsonFile = path.join(this.baseDir, fileName);
  76. // throws err if the file does not exist
  77. fs.accessSync(jsonFile);
  78. return jsonFile;
  79. }
  80. /**
  81. * parse a zip file
  82. *
  83. * @memberOf GrowiBridgeService
  84. * @param {string} zipFile path to zip file
  85. * @return {object} meta{object} and files{Array.<object>}
  86. */
  87. async parseZipFile(zipFile) {
  88. const fileStat = fs.statSync(zipFile);
  89. const innerFileStats = [];
  90. let meta = {};
  91. const readStream = fs.createReadStream(zipFile);
  92. const unzipStream = readStream.pipe(unzipper.Parse());
  93. unzipStream.on('entry', async(entry) => {
  94. const fileName = entry.path;
  95. const size = entry.vars.uncompressedSize; // There is also compressedSize;
  96. if (fileName === this.getMetaFileName()) {
  97. meta = JSON.parse((await entry.buffer()).toString());
  98. }
  99. else {
  100. innerFileStats.push({
  101. fileName,
  102. collectionName: path.basename(fileName, '.json'),
  103. size,
  104. });
  105. }
  106. entry.autodrain();
  107. });
  108. try {
  109. await streamToPromise(unzipStream);
  110. }
  111. // if zip is broken
  112. catch (err) {
  113. logger.error(err);
  114. return null;
  115. }
  116. return {
  117. meta,
  118. fileName: path.basename(zipFile),
  119. fileStat,
  120. innerFileStats,
  121. };
  122. }
  123. }
  124. module.exports = GrowiBridgeService;