'use strcit'; const assert = require('assert'); const Transform = require('stream').Transform; class Feed { constructor(push, done) { this.push = push; this.done = done; } write(something) { if (something !== undefined) { this.push(something); } } end() { this.done(); } send(something) { this.write(something); this.end(); } close() { this.write(null); this.end(); } } class Engine extends Transform { constructor(func, params) { super( { objectMode: true }) let self = this; self.func = func; self.index = 0; self.params = params || {}; self.scope = {}; } _transform(chunk, encoding, done) { this.index++; this.execWith(chunk, done); } _flush(done) { this.execWith(null, done); } execWith(chunk, done) { let self = this; let push = function(data) { if (data instanceof Error) { data = self.createError(data); } self.push(data); } let feed = new Feed(push, done); self.scope.isFirst = function() { return (self.index === 1); }; self.scope.getIndex = function() { return self.index; }; self.scope.isLast = function() { return (chunk === null); }; self.scope.getParams = function() { return self.params; }; self.scope.getParam = function(name, defval) { return self.params[name] ? self.params[name] : defval; }; try { self.func.call(self.scope, chunk, feed) } catch(e) { self.push(self.createError(e)); } } createError(e) { let self = this; e.index = self.index; e.scope = self.scope; e.errmsg = '\nAt index #' + self.index + '\n' + e.stack; // e.chunk = chunk; mmmm it's bad idea... e.toString = function() { return e.errmsg; } return e; } } function isStatement(name) { return typeof name === 'function'; } function ezs(name, opts) { if (isStatement(name)) { return new Engine(name, opts); } else if (typeof name === 'string' && ezs.plugins[name]) { return new Engine(ezs.plugins[name], opts); } else { throw new Error('`' + name +'` unknown'); } } ezs.plugins = {}; ezs.use = function(module) { let self = this; assert.equal(typeof module, 'object'); Object.keys(module).forEach(moduleName => { if (isStatement(module[moduleName])) { ezs.plugins[moduleName] = module[moduleName]; } else { throw new Error('`' + moduleName + '` is not loaded. It\'s not a valid statement.') } }); return ezs; }; module.exports = ezs;