diff --git a/packages/component-mts-package/config/default.js b/packages/component-mts-package/config/default.js index 64fad090508eac085fabc26f4ca3cf026a028ecf..7b41e3827b47698ee0affbd05ca07970578c0b32 100644 --- a/packages/component-mts-package/config/default.js +++ b/packages/component-mts-package/config/default.js @@ -16,7 +16,15 @@ const defaultConfig = { prefix: 'RESEARCH-F-', } +const defaultS3Config = { + secretAccessKey: process.env.AWS_S3_SECRET_KEY, + accessKeyId: process.env.AWS_S3_ACCESS_KEY, + region: process.env.AWS_S3_REGION, + bucket: process.env.AWS_S3_BUCKET, +} + module.exports = { defaultConfig, defaultParseXmlOptions, + defaultS3Config, } diff --git a/packages/component-mts-package/package.json b/packages/component-mts-package/package.json index 2fe71737554a827b88fa8fde15d58d2313632cad..53f5f6dbf1a523dafda8d5bb10ee93321edd4a72 100644 --- a/packages/component-mts-package/package.json +++ b/packages/component-mts-package/package.json @@ -3,9 +3,7 @@ "version": "1.0.0", "description": "Create package for MTS integration", "main": "index.js", - "files": [ - "src" - ], + "files": ["src"], "scripts": { "test": "jest", "convert": "xml-js xml.xml --spaces 4 --out test.json" @@ -33,6 +31,8 @@ "access": "public" }, "dependencies": { + "archiver": "^2.1.1", + "aws-sdk": "^2.185.0", "lodash": "^4.17.10", "xml-js": "^1.6.7" } diff --git a/packages/component-mts-package/src/AWS.js b/packages/component-mts-package/src/AWS.js new file mode 100644 index 0000000000000000000000000000000000000000..f8c9262e7a750e935e7c64e36564a51d46b4d48a --- /dev/null +++ b/packages/component-mts-package/src/AWS.js @@ -0,0 +1,71 @@ +const fs = require('fs') +const AWS = require('aws-sdk') +const { get } = require('lodash') +const { promisify } = require('util') +const nodeArchiver = require('archiver') +const logger = require('@pubsweet/logger') + +const filterByType = (fileTypes = []) => ({ Metadata: { filetype } }) => + fileTypes.length > 0 ? fileTypes.includes(filetype) : true + +const zipAWSFiles = (s3Config, archiver = nodeArchiver) => { + AWS.config.update({ + secretAccessKey: s3Config.secretAccessKey, + accessKeyId: s3Config.accessKeyId, + region: s3Config.region, + }) + const s3 = new AWS.S3() + const asyncGetObject = promisify(s3.getObject.bind(s3)) + const asyncListObjects = promisify(s3.listObjects.bind(s3)) + + return async ({ fragment, fileTypes, xmlFile }) => { + const { id } = fragment + const manuscriptName = get(xmlFile, 'name', '').replace('.xml', '') + try { + const params = { + Bucket: s3Config.bucket, + Prefix: `${id}`, + } + const s3Items = await asyncListObjects(params) + if (s3Items) { + const s3Files = await Promise.all( + s3Items.Contents.map(content => + asyncGetObject({ + Bucket: s3Config.bucket, + Key: content.Key, + }), + ), + ) + + if (s3Files) { + const packageOutput = fs.createWriteStream(`${manuscriptName}.zip`) + const archive = archiver('zip') + archive.pipe(packageOutput) + + archive.append(xmlFile.content, { name: xmlFile.name }) + + s3Files.filter(filterByType(fileTypes)).forEach(f => { + const name = get(f, 'Metadata.filename', f.ETag) + const isManuscript = get(f, 'Metadata.filetype') === 'manuscripts' + const extension = name.split('.').reverse()[0] + archive.append(f.Body, { + name: isManuscript ? `${manuscriptName}.${extension}` : name, + }) + }) + archive.on('error', err => { + throw err + }) + archive.finalize() + } + } else { + logger.error('Failed to create package') + throw new Error('Failed to create a package') + } + } catch (err) { + logger.error(err.message) + return err.message + } + } +} + +module.exports = zipAWSFiles diff --git a/packages/component-mts-package/src/MTS.js b/packages/component-mts-package/src/MTS.js index 7449255e045e9a9fba0da7ce92f1ac154b2f1888..d86cdd34af53ebb262cca9b7d63de010e4a0b627 100644 --- a/packages/component-mts-package/src/MTS.js +++ b/packages/component-mts-package/src/MTS.js @@ -1,22 +1,37 @@ -const fs = require('fs') const convert = require('xml-js') const { set, get } = require('lodash') -const logger = require('@pubsweet/logger') +const zipAWSFiles = require('./AWS') const mts = require('./mts-json-template') -const { defaultConfig, defaultParseXmlOptions } = require('../config/default') +const { + defaultConfig, + defaultParseXmlOptions, + defaultS3Config, +} = require('../config/default') class MTS { - constructor(config = defaultConfig, options = defaultParseXmlOptions) { + constructor( + config = defaultConfig, + options = defaultParseXmlOptions, + s3Config = defaultS3Config, + ) { this.config = config this.options = options this.jsonTemplate = mts.getJsonTemplate(config) + this.s3Config = s3Config } createFileName(id = Date.now()) { return `${this.config.prefix}${id}` } + parseHtml(content = '') { + if (/<\/?[^>]*>/.test(content)) { + return convert.xml2js(content, this.options) + } + return content + } + convertToXML(json = {}) { const content = convert.json2xml(json, this.options) const customId = get( @@ -31,19 +46,10 @@ class MTS { } } - async createXMLFile(json = {}, defaultPath = '../files/') { - const { content, name } = this.convertToXML(json) - await fs.writeFile(`${defaultPath}${name}`, content, err => { - if (err) return logger.error(err) - logger.info('Created XML file') - }) - } - setMetadata(metadata, jsonTemplate) { const fileName = this.createFileName(metadata.customId) const titleGroup = { - 'article-title': - convert.xml2js(metadata.title, this.options) || 'Untitled', + 'article-title': this.parseHtml(metadata.title), } const articleId = [ { @@ -82,7 +88,7 @@ class MTS { set( jsonTemplate, 'article.front.article-meta.abstract', - convert.xml2js(metadata.abstract, this.options) || '', + this.parseHtml(metadata.title), ) return jsonTemplate @@ -196,13 +202,14 @@ class MTS { } } - createXMLFileFromFragment(fragment = {}, defaultPath) { - return this.createXMLFile(this.composeJson(fragment), defaultPath) - } - convertFragmentToXML(fragment = {}) { return this.convertToXML(this.composeJson(fragment)) } + + createMTSPackage(fragment = {}) { + const xmlFile = this.convertFragmentToXML(fragment) + zipAWSFiles(this.s3Config)({ fragment, xmlFile }) + } } module.exports = MTS diff --git a/packages/component-mts-package/tests/MTS.test.js b/packages/component-mts-package/tests/MTS.test.js index 0dc22cadabd7f1060b4936d9833d556e40408a9c..6655fbe07f3602b353cb89be4371bde679d4ddff 100644 --- a/packages/component-mts-package/tests/MTS.test.js +++ b/packages/component-mts-package/tests/MTS.test.js @@ -8,10 +8,6 @@ jest.mock('xml-js', () => ({ json2xml: jest.fn(), xml2js: jest.fn(), })) -jest.mock('fs', () => ({ - json2xml: jest.fn(), - xml2js: jest.fn(), -})) describe('MTS integration', () => { let MTS diff --git a/yarn.lock b/yarn.lock index 580f88dd02b7311bd99001b4a7271ef4be751fd8..9c6cec2c5d3d979294320476e8e4331f050e7eda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -844,6 +844,20 @@ aws-sdk@^2.185.0, aws-sdk@^2.197.0, aws-sdk@^2.2.36: xml2js "0.4.17" xmlbuilder "4.2.1" +aws-sdk@^2.281.1: + version "2.281.1" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.281.1.tgz#12ef82cf8a70a2c97c90e644038684a01cb8cc0c" + dependencies: + buffer "4.9.1" + events "1.1.1" + ieee754 "1.1.8" + jmespath "0.15.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + uuid "3.1.0" + xml2js "0.4.19" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -3644,7 +3658,7 @@ eventemitter2@0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" -events@^1.0.0, events@^1.1.1: +events@1.1.1, events@^1.0.0, events@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -4660,7 +4674,7 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" -ieee754@^1.1.4: +ieee754@1.1.8, ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" @@ -10309,12 +10323,23 @@ xml2js@0.4.17: sax ">=0.6.0" xmlbuilder "^4.1.0" +xml2js@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + xmlbuilder@4.2.1, xmlbuilder@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5" dependencies: lodash "^4.0.0" +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + xpub-connect@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/xpub-connect/-/xpub-connect-0.0.10.tgz#453fa33f6717c4b70afdd1248baee63c478facfc"