From d9de6dacba1036e7879875bc51b6bb9c0d053054 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Tue, 13 Mar 2018 01:23:36 -0400 Subject: [PATCH] Add `writeAttachmentData` module --- app/types/attachment/write_attachment_data.js | 45 ++++++++++++++ .../attachment/write_attachment_data_test.js | 58 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 app/types/attachment/write_attachment_data.js create mode 100644 test/app/types/attachment/write_attachment_data_test.js diff --git a/app/types/attachment/write_attachment_data.js b/app/types/attachment/write_attachment_data.js new file mode 100644 index 000000000..8f6f67872 --- /dev/null +++ b/app/types/attachment/write_attachment_data.js @@ -0,0 +1,45 @@ +const crypto = require('crypto'); +const FSE = require('fs-extra'); +const isArrayBuffer = require('lodash/isArrayBuffer'); +const isBuffer = require('lodash/isBuffer'); +const isString = require('lodash/isString'); +const Path = require('path'); + + +exports.writeAttachmentData = (root) => { + if (!isString(root)) { + throw new TypeError('`root` must be a path'); + } + + return async (arrayBuffer) => { + if (!isArrayBuffer(arrayBuffer)) { + throw new TypeError('`arrayBuffer` must be an array buffer'); + } + + const buffer = new Buffer(arrayBuffer); + const path = Path.join(root, exports._getAttachmentPath(buffer)); + await FSE.ensureFile(path); + await FSE.writeFile(path, buffer); + return path; + }; +}; + +exports._getAttachmentName = (buffer) => { + if (!isBuffer(buffer)) { + throw new TypeError('`buffer` must be a buffer'); + } + + const hash = crypto.createHash('sha256'); + hash.update(buffer); + return hash.digest('hex'); +}; + +exports._getAttachmentPath = (buffer) => { + if (!isBuffer(buffer)) { + throw new TypeError('`buffer` must be a buffer'); + } + + const name = exports._getAttachmentName(buffer); + const prefix = name.slice(0, 3); + return Path.join(prefix, name); +}; diff --git a/test/app/types/attachment/write_attachment_data_test.js b/test/app/types/attachment/write_attachment_data_test.js new file mode 100644 index 000000000..a3b406020 --- /dev/null +++ b/test/app/types/attachment/write_attachment_data_test.js @@ -0,0 +1,58 @@ +const FSE = require('fs-extra'); +const isEqual = require('lodash/isEqual'); +const Path = require('path'); +const stringToArrayBuffer = require('string-to-arraybuffer'); +const tempy = require('tempy'); +const { assert } = require('chai'); + +const { + writeAttachmentData, + _getAttachmentName, + _getAttachmentPath, +} = require('../../../../app/types/attachment/write_attachment_data'); + + +describe('writeAttachmentData', () => { + let TEMPORARY_DIRECTORY = null; + before(() => { + // Sync! + TEMPORARY_DIRECTORY = tempy.directory(); + }); + + after(async () => { + await FSE.remove(TEMPORARY_DIRECTORY); + }); + + it('should write file to disk and return path', async () => { + const input = stringToArrayBuffer('test string'); + const tempDirectory = Path.join(TEMPORARY_DIRECTORY, 'writeAttachmentData'); + const expectedPath = Path.join( + tempDirectory, + 'd55/d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b' + ); + + const outputPath = await writeAttachmentData(tempDirectory)(input); + const output = await FSE.readFile(outputPath); + + assert.strictEqual(outputPath, expectedPath); + + const inputBuffer = Buffer.from(input); + assert.isTrue(isEqual(inputBuffer, output)); + }); + + describe('_getAttachmentName', () => { + it('should return correct name', () => { + const input = Buffer.from('test string', 'utf8'); + const expected = 'd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b'; + assert.strictEqual(_getAttachmentName(input), expected); + }); + }); + + describe('_getAttachmentPath', () => { + it('should return correct path', () => { + const input = Buffer.from('test string', 'utf8'); + const expected = 'd55/d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b'; + assert.strictEqual(_getAttachmentPath(input), expected); + }); + }); +});