Skip to content

Commit 9acbcc7

Browse files
committed
Adds Streams plugins
Also now only one plugin is available per action.
1 parent 8ef1098 commit 9acbcc7

File tree

3 files changed

+80
-28
lines changed

3 files changed

+80
-28
lines changed

lib/index.js

+25-13
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
*/
9090

9191
const {UnifileError} = require('./error.js');
92-
92+
const {Transform} = require('stream');
9393
/**
9494
* Tells if a method needs authentification
9595
* @param {string} methodName - Name of the method to test
@@ -104,10 +104,14 @@ function isAuthentifiedFunction(methodName) {
104104

105105
const HOOKS = {
106106
ON_READ: 'onRead',
107-
ON_WRITE: 'onWrite'
107+
ON_READSTREAM: 'onReadStream',
108+
ON_WRITE: 'onWrite',
109+
ON_WRITESTREAM: 'onWriteStream'
108110
};
109111

110-
const applyPlugins = (plugins, content) => plugins.reduce((data, action) => action(data), content);
112+
const applyPlugin = (plugin, content) => {
113+
return plugin ? plugin(content) : content;
114+
};
111115

112116
const connectors = Symbol('connectors');
113117

@@ -126,10 +130,7 @@ class Unifile {
126130
*/
127131
constructor() {
128132
this[connectors] = new Map();
129-
this.plugins = Object.keys(HOOKS).reduce((memo, key) => {
130-
memo[HOOKS[key]] = [];
131-
return memo;
132-
}, {});
133+
this.plugins = {};
133134
}
134135

135136
/**
@@ -149,8 +150,8 @@ class Unifile {
149150
* @param {Plugin} plugin - A plugin with at least one hook implemented
150151
*/
151152
ext(plugin) {
152-
Object.keys(HOOKS).map((key) => HOOKS[key]).forEach((hook) => {
153-
if(plugin.hasOwnProperty(hook)) this.plugins[hook].push(plugin[hook]);
153+
Object.values(HOOKS).forEach((hook) => {
154+
if(plugin.hasOwnProperty(hook)) this.plugins[hook] = plugin[hook];
154155
});
155156
}
156157

@@ -272,7 +273,7 @@ class Unifile {
272273
* @return {external:Promise<null>} an empty promise.
273274
*/
274275
writeFile(session, connectorName, path, content) {
275-
const input = applyPlugins(this.plugins[HOOKS.ON_WRITE], content);
276+
const input = applyPlugin(this.plugins[HOOKS.ON_WRITE], content);
276277
return this.callMethod(connectorName, session, 'writeFile', path, input);
277278
}
278279

@@ -284,7 +285,13 @@ class Unifile {
284285
* @return {external:WritableStream} a writable stream into the file
285286
*/
286287
createWriteStream(session, connectorName, path) {
287-
return this.callMethod(connectorName, session, 'createWriteStream', path);
288+
const content = this.callMethod(connectorName, session, 'createWriteStream', path);
289+
const plugin = this.plugins[HOOKS.ON_WRITESTREAM];
290+
if(plugin instanceof Transform) {
291+
plugin.pipe(content);
292+
return plugin;
293+
}
294+
return content;
288295
}
289296

290297
/**
@@ -296,7 +303,7 @@ class Unifile {
296303
*/
297304
readFile(session, connectorName, path) {
298305
return this.callMethod(connectorName, session, 'readFile', path)
299-
.then((content) => applyPlugins(this.plugins[HOOKS.ON_READ], content));
306+
.then((content) => applyPlugin(this.plugins[HOOKS.ON_READ], content));
300307
}
301308

302309
/**
@@ -307,7 +314,12 @@ class Unifile {
307314
* @return {external:ReadableStream} a readable stream from the file
308315
*/
309316
createReadStream(session, connectorName, path) {
310-
return this.callMethod(connectorName, session, 'createReadStream', path);
317+
const content = this.callMethod(connectorName, session, 'createReadStream', path);
318+
const plugin = this.plugins[HOOKS.ON_READSTREAM];
319+
if(plugin instanceof Transform) {
320+
return content.pipe(plugin);
321+
}
322+
return content;
311323
}
312324

313325
/**

samples/extensions.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ const crypto = require('crypto');
66
const Unifile = require('../lib/');
77
const unifile = new Unifile();
88

9-
const cipher = crypto.createCipher('aes192', 'a password');
10-
const decipher = crypto.createDecipher('aes192', 'a password');
9+
const PWD = 'a password';
10+
11+
const cipher = crypto.createCipher('aes192', PWD);
12+
const decipher = crypto.createDecipher('aes192', PWD);
1113

1214
// Configure connectors
1315
const dbxconnector = new Unifile.DropboxConnector({

test/index.js

+51-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const PassThrough = require('stream').PassThrough;
3+
const {Readable, Writable, Transform, PassThrough} = require('stream');
44
const chai = require('chai');
55
const Promise = require('bluebird');
66

@@ -86,6 +86,7 @@ describe('Unifile class', function() {
8686
let unifile;
8787
let inMemoryFile = '';
8888
beforeEach('Instanciation', function() {
89+
inMemoryFile = '';
8990
unifile = new Unifile();
9091
unifile.use({
9192
name: 'memory',
@@ -94,6 +95,23 @@ describe('Unifile class', function() {
9495
writeFile: (session, path, content) => {
9596
inMemoryFile = content;
9697
return Promise.resolve();
98+
},
99+
createReadStream: (session, path) => {
100+
return new Readable({
101+
read(size) {
102+
this.push('hello');
103+
this.push(null);
104+
}
105+
});
106+
},
107+
createWriteStream: (session, path) => {
108+
//return require('fs').createWriteStream('./test.log');
109+
return new Writable({
110+
write(chunk, encoding, callback) {
111+
inMemoryFile += chunk.toString();
112+
callback(null);
113+
}
114+
});
97115
}
98116
});
99117
});
@@ -103,10 +121,8 @@ describe('Unifile class', function() {
103121
onWrite: console.log,
104122
onRead: console.log
105123
});
106-
expect(unifile.plugins.onRead).to.have.lengthOf(1);
107-
expect(unifile.plugins.onWrite).to.have.lengthOf(1);
108-
expect(unifile.plugins.onRead[0]).to.equal(console.log);
109-
expect(unifile.plugins.onWrite[0]).to.equal(console.log);
124+
expect(unifile.plugins.onRead).to.equal(console.log);
125+
expect(unifile.plugins.onWrite).to.equal(console.log);
110126
});
111127

112128
it('can modify the input on write action', function() {
@@ -126,18 +142,40 @@ describe('Unifile class', function() {
126142
.should.eventually.equal('aa');
127143
});
128144

129-
it('follow a chain of action in order', function() {
145+
it('can modify the input on write stream', function(done) {
130146
unifile.ext({
131-
onRead: (input) => input.replace('b', 'a'),
132-
onWrite: (input) => input.replace('a', 'b')
147+
onWriteStream: new Transform({
148+
transform(chunk, encoding, callback) {
149+
callback(null, chunk.toString().toUpperCase());
150+
}
151+
})
152+
});
153+
const stream = unifile.createWriteStream({}, 'memory', '');
154+
stream.on('end', () => {
155+
expect(inMemoryFile).to.equal('HELLO');
156+
done();
133157
});
158+
stream.end('hello');
159+
});
160+
161+
it('can modify the input on read stream', function(done) {
162+
inMemoryFile = 'hello';
134163
unifile.ext({
135-
onRead: (input) => input.replace('a', 'c'),
136-
onWrite: (input) => input.replace('b', 'd')
164+
onReadStream: new Transform({
165+
transform(chunk, encoding, callback) {
166+
callback(null, chunk.toString().toUpperCase());
167+
}
168+
})
169+
});
170+
const stream = unifile.createReadStream({}, 'memory', '');
171+
const chunks = [];
172+
stream.on('data', (chunk) => {
173+
chunks.push(chunk);
174+
});
175+
stream.on('end', () => {
176+
expect(Buffer.concat(chunks).toString()).to.equal('HELLO');
177+
done();
137178
});
138-
return unifile.writeFile({}, 'memory', '', 'ab')
139-
.then(() => expect(inMemoryFile).to.equal('db'))
140-
.then(() => unifile.readFile({}, 'memory', '').should.eventually.equal('dc'));
141179
});
142180
});
143181

0 commit comments

Comments
 (0)