diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..930de05 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "standard" + } \ No newline at end of file diff --git a/ber.js b/ber.js index 47a0b74..51e14e9 100755 --- a/ber.js +++ b/ber.js @@ -12,7 +12,7 @@ * integer types. Unfortunately, most of the implementations of BER out * there are for doing PKI stuff, so I've been able to find few real-world * examples of real value encoding/decoding for BER. These routines are - * inspired heavily by libember, which works with the bits of an IEEE + * inspired heavily by libember, which works with the bits of an IEEE * double. Note that this is *not* a complete implementation of X.690, * but only the subset required by EmBER (only base 2 for the exponent, and * only binary encoding). @@ -21,308 +21,295 @@ * structures encountered in EmBER. ***************************************************************************/ -const BER = require('asn1').Ber; -const errors = require('./errors.js'); -const util = require('util'); -const Long = require('long'); - -var APPLICATION = function(x) { return x | 0x60; }; -var CONTEXT = function(x) { return x | 0xa0; }; -var UNIVERSAL = function(x) { return x; }; - - -const EMBER_BOOLEAN = 1; -const EMBER_INTEGER = 2; -const EMBER_BITSTRING = 3; -const EMBER_OCTETSTRING = 4; -const EMBER_NULL = 5; -const EMBER_OBJECTIDENTIFIER = 6; -const EMBER_OBJECTDESCRIPTOR = 7; -const EMBER_EXTERNAL = 8; -const EMBER_REAL = 9; -const EMBER_ENUMERATED = 10; -const EMBER_EMBEDDED = 11; -const EMBER_STRING = 12; -const EMBER_RELATIVE_OID = 13; - -const EMBER_SEQUENCE = 0x20 | 16; -const EMBER_SET = 0x20 | 17; - -module.exports.APPLICATION = APPLICATION; -module.exports.CONTEXT = CONTEXT; -module.exports.UNIVERSAL = UNIVERSAL; -module.exports.EMBER_SET = EMBER_SET; -module.exports.EMBER_SEQUENCE = EMBER_SEQUENCE; -module.exports.EMBER_BOOLEAN = EMBER_BOOLEAN; -module.exports.EMBER_INTEGER = EMBER_INTEGER; -module.exports.EMBER_BITSTRING = EMBER_BITSTRING; -module.exports.EMBER_OCTETSTRING = EMBER_OCTETSTRING; -module.exports.EMBER_NULL = EMBER_NULL; -module.exports.EMBER_OBJECTIDENTIFIER = EMBER_OBJECTIDENTIFIER; -module.exports.EMBER_OBJECTDESCRIPTOR = EMBER_OBJECTDESCRIPTOR; -module.exports.EMBER_EXTERNAL = EMBER_EXTERNAL; -module.exports.EMBER_REAL = EMBER_REAL; -module.exports.EMBER_ENUMERATED = EMBER_ENUMERATED; -module.exports.EMBER_EMBEDDED = EMBER_EMBEDDED; -module.exports.EMBER_STRING = EMBER_STRING; -module.exports.EMBER_RELATIVE_OID = EMBER_RELATIVE_OID; - -function ExtendedReader(data) { - ExtendedReader.super_.call(this, data); +const BER = require('asn1').Ber +const errors = require('./errors.js') +const util = require('util') +const Long = require('long') + +var APPLICATION = function (x) { return x | 0x60 } +var CONTEXT = function (x) { return x | 0xa0 } +var UNIVERSAL = function (x) { return x } + +const EMBER_BOOLEAN = 1 +const EMBER_INTEGER = 2 +const EMBER_BITSTRING = 3 +const EMBER_OCTETSTRING = 4 +const EMBER_NULL = 5 +const EMBER_OBJECTIDENTIFIER = 6 +const EMBER_OBJECTDESCRIPTOR = 7 +const EMBER_EXTERNAL = 8 +const EMBER_REAL = 9 +const EMBER_ENUMERATED = 10 +const EMBER_EMBEDDED = 11 +const EMBER_STRING = 12 +const EMBER_RELATIVE_OID = 13 + +const EMBER_SEQUENCE = 0x20 | 16 +const EMBER_SET = 0x20 | 17 + +module.exports.APPLICATION = APPLICATION +module.exports.CONTEXT = CONTEXT +module.exports.UNIVERSAL = UNIVERSAL +module.exports.EMBER_SET = EMBER_SET +module.exports.EMBER_SEQUENCE = EMBER_SEQUENCE +module.exports.EMBER_BOOLEAN = EMBER_BOOLEAN +module.exports.EMBER_INTEGER = EMBER_INTEGER +module.exports.EMBER_BITSTRING = EMBER_BITSTRING +module.exports.EMBER_OCTETSTRING = EMBER_OCTETSTRING +module.exports.EMBER_NULL = EMBER_NULL +module.exports.EMBER_OBJECTIDENTIFIER = EMBER_OBJECTIDENTIFIER +module.exports.EMBER_OBJECTDESCRIPTOR = EMBER_OBJECTDESCRIPTOR +module.exports.EMBER_EXTERNAL = EMBER_EXTERNAL +module.exports.EMBER_REAL = EMBER_REAL +module.exports.EMBER_ENUMERATED = EMBER_ENUMERATED +module.exports.EMBER_EMBEDDED = EMBER_EMBEDDED +module.exports.EMBER_STRING = EMBER_STRING +module.exports.EMBER_RELATIVE_OID = EMBER_RELATIVE_OID + +function ExtendedReader (data) { + ExtendedReader.super_.call(this, data) } -util.inherits(ExtendedReader, BER.Reader); -module.exports.Reader = ExtendedReader; - - -readBlock = function(ber) { +util.inherits(ExtendedReader, BER.Reader) +module.exports.Reader = ExtendedReader +ExtendedReader.prototype.getSequence = function (tag) { + var buf = this.readString(tag, true) + return new ExtendedReader(buf) } - -ExtendedReader.prototype.getSequence = function(tag) { - var buf = this.readString(tag, true); - return new ExtendedReader(buf); +ExtendedReader.prototype.readValue = function () { + var tag = this.peek() + + if (tag === EMBER_STRING) { + return this.readString(EMBER_STRING) + } else if (tag === EMBER_INTEGER) { + return this.readInt() + } else if (tag === EMBER_REAL) { + return this.readReal() + } else if (tag === EMBER_BOOLEAN) { + return this.readBoolean() + } else if (tag === EMBER_OCTETSTRING) { + return this.readString(UNIVERSAL(4), true) + } else if (tag === EMBER_RELATIVE_OID) { + return this.readOID(EMBER_RELATIVE_OID) + } else { + throw new errors.UnimplementedEmberTypeError(tag) + } } -ExtendedReader.prototype.readValue = function() { - var tag = this.peek(); - - if(tag == EMBER_STRING) { - return this.readString(EMBER_STRING); - } else if(tag == EMBER_INTEGER) { - return this.readInt(); - } else if(tag == EMBER_REAL) { - return this.readReal(); - } else if(tag == EMBER_BOOLEAN) { - return this.readBoolean(); - } else if(tag == EMBER_OCTETSTRING) { - return this.readString(UNIVERSAL(4), true); - } else if (tag === EMBER_RELATIVE_OID) { - return this.readOID(EMBER_RELATIVE_OID); - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } -} +ExtendedReader.prototype.readReal = function (tag) { + if (tag !== undefined) { + tag = UNIVERSAL(9) + } + var b = this.peek() + if (b === null) { + return null + } -ExtendedReader.prototype.readReal = function(tag) { - if(tag !== undefined) { - tag = UNIVERSAL(9); - } + var buf = this.readString(b, true) - var b = this.peek(); - if(b === null) { - return null; - } + if (buf.length === 0) { + return 0 + } - var buf = this.readString(b, true); + // console.log(buf); - if(buf.length == 0) { - return 0; - } + var preamble = buf.readUInt8(0) + var o = 1 - //console.log(buf); + if (buf.length === 1 && preamble === 0x40) { + return Infinity + } else if (buf.length === 1 && preamble === 0x41) { + return -Infinity + } else if (buf.length === 1 && preamble === 0x42) { + return NaN + } - var preamble = buf.readUInt8(0); - var o = 1; + var sign = (preamble & 0x40) ? -1 : 1 + var exponentLength = 1 + (preamble & 3) + var significandShift = (preamble >> 2) & 3 - if(buf.length == 1 && preamble == 0x40) { - return Infinity; - } else if(buf.length == 1 && preamble == 0x41) { - return -Infinity; - } else if(buf.length == 1 && preamble == 0x42) { - return NaN; - } + var exponent = 0 - var sign = (preamble & 0x40)? -1 : 1; - var exponentLength = 1 + (preamble & 3); - var significandShift = (preamble >> 2) & 3; + if (buf.readUInt8(o) & 0x80) { + exponent = -1 + } - var exponent = 0; - - if(buf.readUInt8(o) & 0x80) { - exponent = -1; - } - - if(buf.length - o < exponentLength) { - throw new errors.ASN1Error('Invalid ASN.1; not enough length to contain exponent'); - } + if (buf.length - o < exponentLength) { + throw new errors.ASN1Error('Invalid ASN.1; not enough length to contain exponent') + } - for(var i=0; i> 0)) && +ExtendedWriter._shorten = function (value) { + var size = 4 + while ((((value & 0xff800000) === 0) || ((value & 0xff800000) === 0xff800000 >> 0)) && (size > 1)) { - size--; - value <<= 8; - } - - return {size, value} + size-- + value <<= 8 + } + + return {size, value} } -ExtendedWriter._shortenLong = function(value) { - var mask = Long.fromBits(0x00000000, 0xff800000, true); - value = value.toUnsigned(); +ExtendedWriter._shortenLong = function (value) { + var mask = Long.fromBits(0x00000000, 0xff800000, true) + value = value.toUnsigned() - var size = 8; - while(value.and(mask).eq(0) || (value.and(mask).eq(mask) && (size > 1))) { - size--; - value = value.shl(8); - } + var size = 8 + while (value.and(mask).eq(0) || (value.and(mask).eq(mask) && (size > 1))) { + size-- + value = value.shl(8) + } - return {size, value}; + return {size, value} } -ExtendedWriter.prototype.writeReal = function(value, tag) { - if(tag === undefined) { - tag = UNIVERSAL(9); - } +ExtendedWriter.prototype.writeReal = function (value, tag) { + if (tag === undefined) { + tag = UNIVERSAL(9) + } + + this.writeByte(tag) + if (value === 0) { + this.writeLength(0) + return + } else if (value === Infinity) { + this.writeLength(1) + this.writeByte(0x40) + return + } else if (value === -Infinity) { + this.writeLength(1) + this.writeByte(0x41) + return + } else if (isNaN(value)) { + this.writeLength(1) + this.writeByte(0x42) + return + } + + var fbuf = Buffer.alloc(8) + fbuf.writeDoubleLE(value, 0) + + var bits = Long.fromBits(fbuf.readUInt32LE(0), fbuf.readUInt32LE(4), true) + // console.log(bits); + var significand = bits.and(Long.fromBits(0xFFFFFFFF, 0x000FFFFF, true)).or( + Long.fromBits(0x00000000, 0x00100000, true)) + var exponent = bits.and(Long.fromBits(0x00000000, 0x7FF00000, true)).shru(52) + .sub(1023).toSigned() + while (significand.and(0xFF) === 0) { significand = significand.shru(8) } + while (significand.and(0x01) === 0) { significand = significand.shru(1) } + + // console.log(significand, exponent); + exponent = exponent.toNumber() + // console.log(significand.toNumber(), exponent); + + exponent = ExtendedWriter._shorten(exponent) + significand = ExtendedWriter._shortenLong(significand) + + this.writeLength(1 + exponent.size + significand.size) + var preamble = 0x80 + if (value < 0) preamble |= 0x40 + this.writeByte(preamble) + + for (var i = 0; i < exponent.size; i++) { + this.writeByte((exponent.value & 0xFF000000) >> 24) + exponent.value <<= 8 + } + + var mask = Long.fromBits(0x00000000, 0xFF000000, true) + for (let i = 0; i < significand.size; i++) { // eslint-disable-line no-redeclare + significand.value.and(mask) + this.writeByte(significand.value.and(mask).shru(56).toNumber()) + significand.value = significand.value.shl(8) + } +} - this.writeByte(tag); - if(value == 0) { - this.writeLength(0); - return; - } else if(value == Infinity) { - this.writeLength(1); - this.writeByte(0x40); - return; - } else if(value == -Infinity) { - this.writeLength(1); - this.writeByte(0x41); - return; - } else if(isNaN(value)) { - this.writeLength(1); - this.writeByte(0x42); - return; +ExtendedWriter.prototype.writeValue = function (value, tag) { + if (Number.isInteger(value)) { + if (tag === undefined) { + tag = EMBER_INTEGER } - - var fbuf = Buffer.alloc(8); - fbuf.writeDoubleLE(value, 0); - - - var bits = Long.fromBits(fbuf.readUInt32LE(0), fbuf.readUInt32LE(4), true); - //console.log(bits); - var significand = bits.and(Long.fromBits(0xFFFFFFFF, 0x000FFFFF, true)).or( - Long.fromBits(0x00000000, 0x00100000, true)); - var exponent = bits.and(Long.fromBits(0x00000000, 0x7FF00000, true)).shru(52) - .sub(1023).toSigned(); - while(significand.and(0xFF) == 0) - significand = significand.shru(8); - while(significand.and(0x01) == 0) - significand = significand.shru(1); - - //console.log(significand, exponent); - exponent = exponent.toNumber(); - //console.log(significand.toNumber(), exponent); - - exponent = ExtendedWriter._shorten(exponent); - significand = ExtendedWriter._shortenLong(significand); - - this.writeLength(1 + exponent.size + significand.size); - var preamble = 0x80; - if(value < 0) preamble |= 0x40; - this.writeByte(preamble); - - for(var i=0; i> 24); - exponent.value <<= 8; + this.writeInt(value, tag) + } else if (typeof value === 'boolean') { + if (tag === undefined) { + tag = EMBER_BOOLEAN } - - var mask = Long.fromBits(0x00000000, 0xFF000000, true); - for(var i=0; i { + self.sendKeepaliveResponse() + }) - self.codec.on('keepaliveReq', () => { - self.sendKeepaliveResponse(); - }); + self.codec.on('emberPacket', (packet) => { + self.emit('emberPacket', packet) - self.codec.on('emberPacket', (packet) => { - self.emit('emberPacket', packet); - - var ber = new BER.Reader(packet); - try { - var root = ember.Root.decode(ber); - if (root !== undefined) { - self.emit('emberTree', root); - } - } catch(e) { - self.emit("error", e); - } - }); - - if (socket !== undefined) { - self.socket.on('data', (data) => { - self.codec.dataIn(data); - }); - - self.socket.on('close', () => { - self.emit('disconnected'); - self.status = "disconnected"; - self.socket = null; - }); - - self.socket.on('error', (e) => { - self.emit("error", e); - }); + var ber = new BER.Reader(packet) + try { + var root = ember.Root.decode(ber) + if (root !== undefined) { + self.emit('emberTree', root) + } + } catch (e) { + self.emit('error', e) } -} + }) + + if (socket !== undefined) { + self.socket.on('data', (data) => { + self.codec.dataIn(data) + }) -util.inherits(S101Client, S101Socket); + self.socket.on('close', () => { + self.emit('disconnected') + self.status = 'disconnected' + self.socket = null + }) + + self.socket.on('error', (e) => { + self.emit('error', e) + }) + } +} +util.inherits(S101Client, S101Socket) /********************************************** * SERVER **********************************************/ -function S101Server(address, port) { - var self = this; - S101Server.super_.call(this); +function S101Server (address, port) { + var self = this + S101Server.super_.call(this) - self.address = address; - self.port = port; - self.server = null; - self.status = "disconnected"; + self.address = address + self.port = port + self.server = null + self.status = 'disconnected' } -util.inherits(S101Server, EventEmitter); +util.inherits(S101Server, EventEmitter) -S101Server.prototype.listen = function() { - var self = this; - if (self.status !== "disconnected") { - return; - } - - self.server = net.createServer((socket) => { - self.addClient(socket); - }); - - self.server.on("error", (e) => { - self.emit("error", e); - }); - - self.server.on("listening", () => { - self.emit("listening"); - self.status = "listening"; - }); - - self.server.listen(self.port, self.address); -} +S101Server.prototype.listen = function () { + var self = this + if (self.status !== 'disconnected') { + return + } + + self.server = net.createServer((socket) => { + self.addClient(socket) + }) + + self.server.on('error', (e) => { + self.emit('error', e) + }) + self.server.on('listening', () => { + self.emit('listening') + self.status = 'listening' + }) -S101Server.prototype.addClient = function(socket) { - var client = new S101Client(socket, this); - this.emit("connection", client); + self.server.listen(self.port, self.address) } +S101Server.prototype.addClient = function (socket) { + var client = new S101Client(socket, this) + this.emit('connection', client) +} /***************************************************** * Client *****************************************************/ -S101Client.prototype.remoteAddress = function() { - if (this.socket === undefined) { - return; - } - return `${this.socket.remoteAddress}:${this.socket.remotePort}` +S101Client.prototype.remoteAddress = function () { + if (this.socket === undefined) { + return + } + return `${this.socket.remoteAddress}:${this.socket.remotePort}` } -S101Client.prototype.queueMessage = function(node) { - const self = this; - this.addRequest(() => { - self.sendBERNode(node); - }); +S101Client.prototype.queueMessage = function (node) { + const self = this + this.addRequest(() => { + self.sendBERNode(node) + }) } -S101Client.prototype.makeRequest = function() { - if(this.activeRequest === null && this.pendingRequests.length > 0) { - this.activeRequest = this.pendingRequests.shift(); - this.activeRequest(); - this.activeRequest = null; - } -}; - -S101Client.prototype.addRequest = function(cb) { - this.pendingRequests.push(cb); - this.makeRequest(); +S101Client.prototype.makeRequest = function () { + if (this.activeRequest === null && this.pendingRequests.length > 0) { + this.activeRequest = this.pendingRequests.shift() + this.activeRequest() + this.activeRequest = null + } } +S101Client.prototype.addRequest = function (cb) { + this.pendingRequests.push(cb) + this.makeRequest() +} /***************************************************** * Socket *****************************************************/ -S101Socket.prototype.connect = function(timeout = 2) { - var self = this; - if (self.status !== "disconnected") { - return; - } - - self.emit('connecting'); - - if (timeout > 0) { - self._timeout = timeout; - self._timer = setTimeout(() => { - self.socket = undefined; - self.emit("error", new Error("connection timeout")); - }, 1000 * timeout); - } - - self.socket = net.createConnection(self.port, self.address, () => { - winston.debug('socket connected'); +S101Socket.prototype.connect = function (timeout = 2) { + var self = this + if (self.status !== 'disconnected') { + return + } - if (self._timer) { - clearTimeout(self._timer); - } + self.emit('connecting') + if (timeout > 0) { + self._timeout = timeout + self._timer = setTimeout(() => { + self.socket = undefined + self.emit('error', new Error('connection timeout')) + }, 1000 * timeout) + } - setInterval(() => { - self.sendKeepaliveRequest(); - }, 1000 * self.keepaliveInterval ); + self.socket = net.createConnection(self.port, self.address, () => { + winston.debug('socket connected') - self.codec.on('keepaliveReq', () => { - self.sendKeepaliveResponse(); - }); - - self.codec.on('emberPacket', (packet) => { - self.emit('emberPacket', packet); - - var ber = new BER.Reader(packet); - try { - var root = ember.Root.decode(ber); - if (root !== undefined) { - self.emit('emberTree', root); - } - } catch(e) { - self.emit("error", e); - } - }); - - self.emit('connected'); - }).on('error', (e) => { - self.emit("error", e); - }); + if (self._timer) { + clearTimeout(self._timer) + } - self.socket.on('data', (data) => { - self.codec.dataIn(data); - }); + setInterval(() => { + self.sendKeepaliveRequest() + }, 1000 * self.keepaliveInterval) - self.socket.on('close', () => { - self.emit('disconnected'); - self.status = "disconnected"; - self.socket = null; - }); + self.codec.on('keepaliveReq', () => { + self.sendKeepaliveResponse() + }) + self.codec.on('emberPacket', (packet) => { + self.emit('emberPacket', packet) + var ber = new BER.Reader(packet) + try { + var root = ember.Root.decode(ber) + if (root !== undefined) { + self.emit('emberTree', root) + } + } catch (e) { + self.emit('error', e) + } + }) + + self.emit('connected') + }).on('error', (e) => { + self.emit('error', e) + }) + + self.socket.on('data', (data) => { + self.codec.dataIn(data) + }) + + self.socket.on('close', () => { + self.emit('disconnected') + self.status = 'disconnected' + self.socket = null + }) } -S101Socket.prototype.isConnected = function() { - return ((this.socket !== null) && (this.socket !== undefined)); +S101Socket.prototype.isConnected = function () { + return ((this.socket !== null) && (this.socket !== undefined)) } -S101Socket.prototype.disconnect = function() { - var self = this; - if (self.isConnected()) { - self.socket.destroy(); - self.socket = null; - self.status = "disconnected"; - } +S101Socket.prototype.disconnect = function () { + var self = this + if (self.isConnected()) { + self.socket.destroy() + self.socket = null + self.status = 'disconnected' + } } -S101Socket.prototype.sendKeepaliveRequest = function() { - var self = this; - if (self.isConnected()) { - self.socket.write(self.codec.keepAliveRequest()); - winston.debug('sent keepalive request'); - } +S101Socket.prototype.sendKeepaliveRequest = function () { + var self = this + if (self.isConnected()) { + self.socket.write(self.codec.keepAliveRequest()) + winston.debug('sent keepalive request') + } } -S101Socket.prototype.sendKeepaliveResponse = function() { - var self = this; - if (self.isConnected()) { - self.socket.write(self.codec.keepAliveResponse()); - winston.debug('sent keepalive response'); - } +S101Socket.prototype.sendKeepaliveResponse = function () { + var self = this + if (self.isConnected()) { + self.socket.write(self.codec.keepAliveResponse()) + winston.debug('sent keepalive response') + } } -S101Socket.prototype.sendBER = function(data) { - var self = this; - if (self.isConnected()) { - var frames = self.codec.encodeBER(data); - for (var i = 0; i < frames.length; i++) { - self.socket.write(frames[i]); - } +S101Socket.prototype.sendBER = function (data) { + var self = this + if (self.isConnected()) { + var frames = self.codec.encodeBER(data) + for (var i = 0; i < frames.length; i++) { + self.socket.write(frames[i]) } + } } -S101Socket.prototype.sendBERNode = function(node) { - var self=this; - if (!node) return; - var writer = new BER.Writer(); - node.encode(writer); - self.sendBER(writer.buffer); +S101Socket.prototype.sendBERNode = function (node) { + var self = this + if (!node) return + var writer = new BER.Writer() + node.encode(writer) + self.sendBER(writer.buffer) } - - -module.exports = { S101Socket, S101Server, S101Client }; - +module.exports = { S101Socket, S101Server, S101Client } diff --git a/device.js b/device.js index 2a741ba..c271018 100755 --- a/device.js +++ b/device.js @@ -1,383 +1,379 @@ -const EventEmitter = require('events').EventEmitter; -const util = require('util'); -const S101Client = require('./client.js').S101Socket; -const ember = require('./ember.js'); -const BER = require('./ber.js'); -const errors = require('./errors.js'); - -const DEBUG = false; - -function DeviceTree(host, port) { - DeviceTree.super_.call(this); - var self = this; - self._debug = false; - self.timeoutValue = 3000; - self.client = new S101Client(host, port); - self.root = new ember.Root(); - self.pendingRequests = []; - self.activeRequest = null; - self.timeout = null; - self.callback = undefined; - self.requestID = 0; - - self.client.on('connecting', () => { - self.emit('connecting'); - }); - - self.client.on('connected', () => { - self.emit('connected'); - if (self.callback !== undefined) { - self.callback(); - } - }); +const EventEmitter = require('events').EventEmitter +const util = require('util') +const S101Client = require('./client.js').S101Socket +const ember = require('./ember.js') +const BER = require('./ber.js') +const errors = require('./errors.js') + +const DEBUG = false + +function DeviceTree (host, port) { + DeviceTree.super_.call(this) + var self = this + self._debug = false + self.timeoutValue = 3000 + self.client = new S101Client(host, port) + self.root = new ember.Root() + self.pendingRequests = [] + self.activeRequest = null + self.timeout = null + self.callback = undefined + self.requestID = 0 + + self.client.on('connecting', () => { + self.emit('connecting') + }) + + self.client.on('connected', () => { + self.emit('connected') + if (self.callback !== undefined) { + self.callback() + } + }) - self.client.on('disconnected', () => { - self.emit('disconnected'); - }); + self.client.on('disconnected', () => { + self.emit('disconnected') + }) - self.client.on("error", (e) => { - if (self.callback !== undefined) { - self.callback(e); - } - self.emit("error", e); - }); - - self.client.on('emberTree', (root) => { - self.handleRoot(root); - if (self._debug) {console.log("Received root", root);} - if (self.callback) { - self.callback(undefined, root); - } - }); + self.client.on('error', (e) => { + if (self.callback !== undefined) { + self.callback(e) + } + self.emit('error', e) + }) + + self.client.on('emberTree', (root) => { + self.handleRoot(root) + if (self._debug) { console.log('Received root', root) } + if (self.callback) { + self.callback(undefined, root) + } + }) } -util.inherits(DeviceTree, EventEmitter); +util.inherits(DeviceTree, EventEmitter) - -DecodeBuffer = function(packet) { - var ber = new BER.Reader(packet); - return ember.Root.decode(ber); +var DecodeBuffer = function (packet) { + var ber = new BER.Reader(packet) + return ember.Root.decode(ber) } -DeviceTree.prototype.saveTree = function(f) { - var writer = new BER.Writer(); - this.root.encode(writer); - f(writer.buffer); +DeviceTree.prototype.saveTree = function (f) { + var writer = new BER.Writer() + this.root.encode(writer) + f(writer.buffer) } -DeviceTree.prototype.isConnected = function() { - return ((this.client !== undefined) && (this.client.isConnected())); +DeviceTree.prototype.isConnected = function () { + return ((this.client !== undefined) && (this.client.isConnected())) } -DeviceTree.prototype.connect = function(timeout = 2) { - return new Promise((resolve, reject) => { - this.callback = (e) => { - if (e === undefined) { - return resolve(); - } - return reject(e); - }; - if ((this.client !== undefined) && (this.client.isConnected())) { - this.client.disconnect(); - } - this.client.connect(timeout); - }); +DeviceTree.prototype.connect = function (timeout = 2) { + return new Promise((resolve, reject) => { + this.callback = (e) => { + if (e === undefined) { + return resolve() + } + return reject(e) + } + if ((this.client !== undefined) && (this.client.isConnected())) { + this.client.disconnect() + } + this.client.connect(timeout) + }) } -DeviceTree.prototype.expand = function(node) -{ - let self = this; - return self.getDirectory(node).then((res) => { - let children = node.getChildren(); - if ((res === undefined) || (children === undefined) || (children === null)) { - if (DEBUG) {console.log("No more children for ", node);} - return; - } - let p = []; - for (let child of children) { - if (DEBUG) {console.log("Expanding child", child);} - p.push( - self.expand(child).catch((e) => { - // We had an error on some expansion - // let's save it on the child itself - child.error = e; - }) - ); - } - return Promise.all(p); - }); +DeviceTree.prototype.expand = function (node) { + // let self = this + return new Promise((resolve, reject) => { + this.getDirectory(node).then((res) => { + let children = node.getChildren() + if ((res === undefined) || (children === undefined) || (children === null)) { + if (DEBUG) { console.log('No more children for ', node) } + resolve(res) + return + } + let p = [] + for (let child of children) { + if (DEBUG) { console.log('Expanding child', child) } + p.push( + this.expand(child).catch((e) => { + // We had an error on some expansion + // let's save it on the child itself + child.error = e + }) + ) + } + Promise.all(p) + .then((res) => { + resolve(res) + }) + .catch((e) => { + reject(e) + }) + }) + }) } -DeviceTree.prototype.getDirectory = function(qnode) { - var self = this; - if (qnode === undefined) { - self.root.clear(); - qnode = self.root; - } - return new Promise((resolve, reject) => { - self.addRequest((error) => { - if (error) { - reject(error); - self.finishRequest(); - return; - } - - let cb = (error, node) => { - self.clearTimeout(); // clear the timeout now. The resolve below may take a while. - if (error) { - reject(error); - } - else { - if (DEBUG) {console.log("Received getDirectory response", node);} - resolve(node); // make sure the info is treated before going to next request. - } - self.finishRequest(); - }; - - if (self._debug) {console.log("Sending getDirectory", qnode);} - self.callback = cb; - self.client.sendBERNode(qnode.getDirectory()); - }); - }); +DeviceTree.prototype.getDirectory = function (qnode) { + var self = this + if (qnode === undefined) { + self.root.clear() + qnode = self.root + } + return new Promise((resolve, reject) => { + self.addRequest((error) => { + if (error) { + reject(error) + self.finishRequest() + return + } + + let cb = (error, node) => { + self.clearTimeout() // clear the timeout now. The resolve below may take a while. + if (error) { + reject(error) + } else { + if (DEBUG) { console.log('Received getDirectory response', node) } + resolve(node) // make sure the info is treated before going to next request. + } + self.finishRequest() + } + + if (self._debug) { console.log('Sending getDirectory', qnode) } + self.callback = cb + self.client.sendBERNode(qnode.getDirectory()) + }) + }) } -DeviceTree.prototype.disconnect = function() { - if (this.client !== undefined) { - return this.client.disconnect(); - } +DeviceTree.prototype.disconnect = function () { + if (this.client !== undefined) { + return this.client.disconnect() + } } -DeviceTree.prototype.makeRequest = function() { - var self=this; - if(self.activeRequest === null && self.pendingRequests.length > 0) { - self.activeRequest = self.pendingRequests.shift(); - - const t = function(id) { - if (DEBUG) {console.log(`Making request ${id}`,Date.now());} - self.timeout = setTimeout(() => { - self.timeoutRequest(id); - }, self.timeoutValue); - }; +DeviceTree.prototype.makeRequest = function () { + var self = this + if (self.activeRequest === null && self.pendingRequests.length > 0) { + self.activeRequest = self.pendingRequests.shift() - t(self.requestID++); - self.activeRequest(); + const t = function (id) { + if (DEBUG) { console.log(`Making request ${id}`, Date.now()) } + self.timeout = setTimeout(() => { + self.timeoutRequest(id) + }, self.timeoutValue) } -}; -DeviceTree.prototype.addRequest = function(cb) { - var self=this; - self.pendingRequests.push(cb); - self.makeRequest(); + t(self.requestID++) + self.activeRequest() + } } -DeviceTree.prototype.clearTimeout = function() { - if(this.timeout != null) { - clearTimeout(this.timeout); - this.timeout = null; - } +DeviceTree.prototype.addRequest = function (cb) { + var self = this + self.pendingRequests.push(cb) + self.makeRequest() } -DeviceTree.prototype.finishRequest = function() { - var self=this; - self.callback = undefined; - self.clearTimeout(); - self.activeRequest = null; - self.makeRequest(); +DeviceTree.prototype.clearTimeout = function () { + if (this.timeout !== null) { + clearTimeout(this.timeout) + this.timeout = null + } } -DeviceTree.prototype.timeoutRequest = function(id) { - var self = this; - self.root.cancelCallbacks(); - self.activeRequest(new errors.EmberTimeoutError(`Request ${id !== undefined ? id : ""} timed out`)); +DeviceTree.prototype.finishRequest = function () { + var self = this + self.callback = undefined + self.clearTimeout() + self.activeRequest = null + self.makeRequest() } -DeviceTree.prototype.handleRoot = function(root) { - var self=this; - - if (self._debug) {console.log("handling root", JSON.stringify(root));} - var callbacks = self.root.update(root); - if(root.elements !== undefined) { - for(var i=0; i { - self.addRequest((error) => { - if(error) { - reject(error); - self.finishRequest(); - return; - } - self.root.getNodeByPath(self.client, path, (error, node) => { - if(error) { - reject(error); - } else { - resolve(node); - } - self.finishRequest(); - }); - }); - }); + // console.log('handleNode: ', callbacks); + return callbacks } -DeviceTree.prototype.subscribe = function(node, callback) { - if(node instanceof ember.Parameter && node.isStream()) { - // TODO: implement - } else { - node.addCallback(callback); - } +DeviceTree.prototype.getNodeByPath = function (path) { + var self = this + if (typeof path === 'string') { + path = path.split('/') + } + + return new Promise((resolve, reject) => { + self.addRequest((error) => { + if (error) { + reject(error) + self.finishRequest() + return + } + self.root.getNodeByPath(self.client, path, (error, node) => { + if (error) { + reject(error) + } else { + resolve(node) + } + self.finishRequest() + }) + }) + }) } -DeviceTree.prototype.unsubscribe = function(node, callback) { - if(node instanceof ember.Parameter && node.isStream()) { - // TODO: implement - } else { - node.addCallback(callback); - } +DeviceTree.prototype.subscribe = function (node, callback) { + if (node instanceof ember.Parameter && node.isStream()) { + // TODO: implement + } else { + node.addCallback(callback) + } } -DeviceTree.prototype.setValue = function(node, value) { - var self=this; - return new Promise((resolve, reject) => { - if((!(node instanceof ember.Parameter)) && - (!(node instanceof ember.QualifiedParameter))) - { - reject(new errors.EmberAccessError('not a property')); - } - else { - // if (this._debug) { console.log('setValue', node.getPath(), value); } - self.addRequest((error) => { - if(error) { - self.finishRequest(); - reject(error); - return; - } - - let cb = (error, node) => { - //console.log('setValue complete...', node.getPath(), value); - self.finishRequest(); - if (error) { - reject(error); - } - else { - resolve(node); - } - }; - - self.callback = cb; - if (this._debug) { console.log('setValue sending ...', node.getPath(), value); } - self.client.sendBERNode(node.setValue(value)); - }); - } - }); +DeviceTree.prototype.unsubscribe = function (node, callback) { + if (node instanceof ember.Parameter && node.isStream()) { + // TODO: implement + } else { + node.addCallback(callback) + } } -function TreePath(path) { - this.identifiers = []; - this.numbers = []; - - if(path !== undefined) { - for(var i=0; i { + if ((!(node instanceof ember.Parameter)) && + (!(node instanceof ember.QualifiedParameter))) { + reject(new errors.EmberAccessError('not a property')) + } else { + // if (this._debug) { console.log('setValue', node.getPath(), value); } + self.addRequest((error) => { + if (error) { + self.finishRequest() + reject(error) + return + } + + let cb = (error, node) => { + // console.log('setValue complete...', node.getPath(), value); + self.finishRequest() + if (error) { + reject(error) + } else { + resolve(node) + } } + + self.callback = cb + if (this._debug) { console.log('setValue sending ...', node.getPath(), value) } + self.client.sendBERNode(node.setValue(value)) + }) } + }) } - -module.exports = {DeviceTree, DecodeBuffer}; +// function TreePath (path) { +// this.identifiers = [] +// this.numbers = [] + +// if (path !== undefined) { +// for (var i = 0; i < path.length; i++) { +// if (Number.isInteger(path[i])) { +// this.numbers.push(path[i]) +// this.identifiers.push(null) +// } else { +// this.identifiers.push(path[i]) +// this.numbers.push(null) +// } +// } +// } +// } + +module.exports = {DeviceTree, DecodeBuffer} diff --git a/ember.js b/ember.js index 9e0d420..907dbea 100755 --- a/ember.js +++ b/ember.js @@ -1,994 +1,963 @@ -const BER = require('./ber.js'); -const errors = require('./errors.js'); -const util = require('util'); -const Enum = require('enum'); - -const COMMAND_SUBSCRIBE = 30; -const COMMAND_UNSUBSCRIBE = 31; -const COMMAND_GETDIRECTORY = 32; -module.exports.Subscribe = COMMAND_SUBSCRIBE; -module.exports.Unsubscribe = COMMAND_UNSUBSCRIBE; -module.exports.GetDirectory = COMMAND_GETDIRECTORY; - -DEBUG = false; - -module.exports.DEBUG = function(d) { - DEBUG = d; -}; +const BER = require('./ber.js') +const errors = require('./errors.js') +const util = require('util') +const Enum = require('enum') + +const COMMAND_SUBSCRIBE = 30 +const COMMAND_UNSUBSCRIBE = 31 +const COMMAND_GETDIRECTORY = 32 +module.exports.Subscribe = COMMAND_SUBSCRIBE +module.exports.Unsubscribe = COMMAND_UNSUBSCRIBE +module.exports.GetDirectory = COMMAND_GETDIRECTORY + +var DEBUG = false + +module.exports.DEBUG = function (d) { + DEBUG = d +} /**************************************************************************** * Root ***************************************************************************/ -function Root() { - Root.super_.call(this); +function Root () { + Root.super_.call(this) - //Object.defineProperty(this, '_parent', {value: null, enumerable: false}); + // Object.defineProperty(this, '_parent', {value: null, enumerable: false}); }; -util.inherits(Root, TreeNode); - - -Root.decode = function(ber) { - let r = new Root(); - let tag = undefined; - - while(ber.remain > 0) { - if (DEBUG) { console.log("Reading root"); } - ber = ber.getSequence(BER.APPLICATION(0)); - tag = ber.peek(); - if (DEBUG) { console.log("Application 0 start"); } - - if (tag == BER.APPLICATION(11)) { - if (DEBUG) { console.log("Application 11 start"); } - var seq = ber.getSequence(BER.APPLICATION(11)); - r.elements = []; - while (seq.remain > 0) { - try { - var rootReader = seq.getSequence(BER.CONTEXT(0)); - while (rootReader.remain > 0) { - r.addElement(RootElement.decode(rootReader)); - } - } - catch (e) { - console.log(e.stack); - return r; - } - } - } else { - // StreamCollection BER.APPLICATION(6) - // InvocationResult BER.APPLICATION(23) - throw new errors.UnimplementedEmberTypeError(tag); - } +util.inherits(Root, TreeNode) + +Root.decode = function (ber) { + let r = new Root() + let tag + + while (ber.remain > 0) { + if (DEBUG) { console.log('Reading root') } + ber = ber.getSequence(BER.APPLICATION(0)) + tag = ber.peek() + if (DEBUG) { console.log('Application 0 start') } + + if (tag === BER.APPLICATION(11)) { + if (DEBUG) { console.log('Application 11 start') } + var seq = ber.getSequence(BER.APPLICATION(11)) + r.elements = [] + while (seq.remain > 0) { + try { + var rootReader = seq.getSequence(BER.CONTEXT(0)) + while (rootReader.remain > 0) { + r.addElement(RootElement.decode(rootReader)) + } + } catch (e) { + console.log(e.stack) + return r + } + } + } else { + // StreamCollection BER.APPLICATION(6) + // InvocationResult BER.APPLICATION(23) + throw new errors.UnimplementedEmberTypeError(tag) } - return r; + } + return r } -Root.prototype.addElement = function(ele) { - ele._parent = this; - if(this.elements === undefined) { - this.elements = []; - } - this.elements.push(ele); +Root.prototype.addElement = function (ele) { + ele._parent = this + if (this.elements === undefined) { + this.elements = [] + } + this.elements.push(ele) } - - -Root.prototype.addChild = function(child) { - this.addElement(child); +Root.prototype.addChild = function (child) { + this.addElement(child) } -Root.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(0)); +Root.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(0)) - if(this.elements !== undefined) { - ber.startSequence(BER.APPLICATION(11)); - ber.startSequence(BER.CONTEXT(0)); - for(var i=0; i { callback(error, node) }); - } - return this.getTreeBranch(new Command(COMMAND_GETDIRECTORY)); -} - -TreeNode.prototype.subscribe = function(callback) { - if(callback !== undefined) { - this._directoryCallbacks.push((error, node) => { callback(error, node) }); - } - return this.getTreeBranch(new Command(COMMAND_SUBSCRIBE)); -} - -TreeNode.prototype.unsubscribe = function(callback) { - if(callback !== undefined) { - this._directoryCallbacks.push((error, node) => { callback(error, node) }); - } - return this.getTreeBranch(new Command(COMMAND_UNSUBSCRIBE)); -} - -TreeNode.prototype.getChildren = function() { - if(this.children !== undefined) { - return this.children; - } - return null; -} - - -_getElementByPath = function(children, pathArray, path) { - if ((children === null)||(children === undefined)||(pathArray.length < 1)) { - return null; - } - var currPath = pathArray.join("."); - var number = pathArray[pathArray.length - 1]; - //console.log(`looking for path ${currPath} or number ${number}`); - +TreeNode.prototype.cancelCallbacks = function () { + var self = this + self._directoryCallbacks = [] + var children = self.getChildren() + if (children !== null) { for (var i = 0; i < children.length; i++) { - //console.log("looking at child", JSON.stringify(children[i])); - - if ((children[i].path == currPath)|| - (children[i].number == number)){ - if (path.length === 0) { - return children[i]; - } - pathArray.push(path.splice(0,1)); - return _getElementByPath(children[i].getChildren(), pathArray, path); - } + children[i].cancelCallbacks() } - - return null; + } } -TreeNode.prototype.getElementByPath = function(path) { - var children = this.getChildren(); - if ((children === null)||(children === undefined)) { - return null; - } +TreeNode.prototype.getMinimal = function () { + if (this.isQualified()) { + return new this.constructor(this.path) + } else { + return new this.constructor(this.number) + } +} + +TreeNode.prototype.getTreeBranch = function (child, modifier) { + var m = this.getMinimal() + if (child !== undefined) { + m.addChild(child) + } - var myPath = this.getPath(); - if (path == myPath) { - return this; - } - var myPathArray = []; - if (this._parent) { - myPathArray = myPath.split("."); - } - path = path.split("."); - - if (path.length > myPathArray.length) { - pathArray = path.splice(0, myPath.length + 1); - for(var i = 0; i < pathArray.length - 1; i++) { - if (pathArray[i] != myPathArray[i]) { - return null; - } - } - } - else { - return null; - } - return _getElementByPath(children, pathArray, path); -} + if (modifier !== undefined) { + modifier(m) + } -TreeNode.prototype.getElementByNumber = function(index) { - var children = this.getChildren(); - if(children === null) return null; - for(var i=0; i { callback(error, node) }) + } + return this.getTreeBranch(new Command(COMMAND_GETDIRECTORY)) } -TreeNode.prototype.update = function(other) { - var self=this; - var callbacks = []; - - //if(this.getChildren !== null) { - while(self._directoryCallbacks.length > 0) { - (function(cb) { - callbacks.push(() => { - //console.log(this.constructor.name, "dir cb", self.getPath()); - cb(null, self) - }); - })(self._directoryCallbacks.shift()); - } - //} - - for(var i=0; i { - //console.log(self.constructor.name, "cb", self.getPath()); - cb(self) - }); - })(self._callbacks[i]); - } - - return callbacks; +TreeNode.prototype.subscribe = function (callback) { + if (callback !== undefined) { + this._directoryCallbacks.push((error, node) => { callback(error, node) }) + } + return this.getTreeBranch(new Command(COMMAND_SUBSCRIBE)) } -TreeNode.prototype.getNodeByPath = function(client, path, callback) { - var self=this; - - if(path.length == 0) { - callback(null, self); - return; - } - - - var child = self.getElement(path[0]); - if(child !== null) { - child.getNodeByPath(client, path.slice(1), callback); - } else { - var cmd = self.getDirectory((error, node) => { - if(error) { - callback(error); - } - child = node.getElement(path[0]); - if(child === null) { - //console.log("inv:", path[0], self); - callback('invalid path'); - return; - } else { - child.getNodeByPath(client, path.slice(1), callback); - } - }); - if(cmd !== null) { - client.sendBERNode(cmd); - } - } +TreeNode.prototype.unsubscribe = function (callback) { + if (callback !== undefined) { + this._directoryCallbacks.push((error, node) => { callback(error, node) }) + } + return this.getTreeBranch(new Command(COMMAND_UNSUBSCRIBE)) } - -TreeNode.prototype.getPath = function() { - if (this.path !== undefined) { - return this.path; - } - if(this._parent === null) { - if(this.number === undefined) { - return ""; - } else { - return this.number.toString(); - } + +TreeNode.prototype.getChildren = function () { + if (this.children !== undefined) { + return this.children + } + return null +} + +var _getElementByPath = function (children, pathArray, path) { + if ((children === null) || (children === undefined) || (pathArray.length < 1)) { + return null + } + var currPath = pathArray.join('.') + var number = pathArray[pathArray.length - 1] + // console.log(`looking for path ${currPath} or number ${number}`); + + for (var i = 0; i < children.length; i++) { + // console.log("looking at child", JSON.stringify(children[i])); + + if ((children[i].path === currPath) || + (children[i].number === number)) { + if (path.length === 0) { + return children[i] + } + pathArray.push(path.splice(0, 1)) + return _getElementByPath(children[i].getChildren(), pathArray, path) + } + } + + return null +} + +TreeNode.prototype.getElementByPath = function (path) { + var children = this.getChildren() + if ((children === null) || (children === undefined)) { + return null + } + + var myPath = this.getPath() + if (path === myPath) { + return this + } + var myPathArray = [] + if (this._parent) { + myPathArray = myPath.split('.') + } + path = path.split('.') + + if (path.length > myPathArray.length) { + var pathArray = path.splice(0, myPath.length + 1) + for (var i = 0; i < pathArray.length - 1; i++) { + if (pathArray[i] !== myPathArray[i]) { + return null + } + } + } else { + return null + } + return _getElementByPath(children, pathArray, path) +} + +TreeNode.prototype.getElementByNumber = function (index) { + var children = this.getChildren() + if (children === null) return null + for (var i = 0; i < children.length; i++) { + if (children[i].number === index) { + return children[i] + } + } + return null +} + +TreeNode.prototype.getElementByIdentifier = function (identifier) { + var children = this.getChildren() + if (children === null) return null + for (var i = 0; i < children.length; i++) { + if (children[i].contents !== undefined && + children[i].contents.identifier === identifier) { + return children[i] + } + } + return null +} + +TreeNode.prototype.getElement = function (id) { + if (Number.isInteger(id)) { + return this.getElementByNumber(id) + } else { + return this.getElementByIdentifier(id) + } +} + +TreeNode.prototype.update = function (other) { + var self = this + var callbacks = [] + + // if(this.getChildren !== null) { + while (self._directoryCallbacks.length > 0) { + (function (cb) { + callbacks.push(() => { + // console.log(this.constructor.name, "dir cb", self.getPath()); + cb(null, self) + }) + })(self._directoryCallbacks.shift()) + } + // } + + for (var i = 0; i < self._callbacks.length; i++) { + (function (cb) { + callbacks.push(() => { + // console.log(self.constructor.name, "cb", self.getPath()); + cb(self) + }) + })(self._callbacks[i]) + } + + return callbacks +} + +TreeNode.prototype.getNodeByPath = function (client, path, callback) { + var self = this + + if (path.length === 0) { + callback(null, self) + return + } + + var child = self.getElement(path[0]) + if (child !== null) { + child.getNodeByPath(client, path.slice(1), callback) + } else { + var cmd = self.getDirectory((error, node) => { + if (error) { + callback(error) + } + child = node.getElement(path[0]) + if (child === null) { + // console.log("inv:", path[0], self); + callback(new Error('invalid path')) + } else { + child.getNodeByPath(client, path.slice(1), callback) + } + }) + if (cmd !== null) { + client.sendBERNode(cmd) + } + } +} + +TreeNode.prototype.getPath = function () { + if (this.path !== undefined) { + return this.path + } + if (this._parent === null) { + if (this.number === undefined) { + return '' } else { - var path = this._parent.getPath(); - if(path.length > 0) { - path = path + "."; - } - return path + this.number; + return this.number.toString() } + } else { + var path = this._parent.getPath() + if (path.length > 0) { + path = path + '.' + } + return path + this.number + } } /**************************************************************************** * RootElement ***************************************************************************/ -function RootElement() {}; +function RootElement () {}; -RootElement.decode = function(ber) { - return Element.decode(ber); +RootElement.decode = function (ber) { + return Element.decode(ber) - // TODO: handle qualified types + // TODO: handle qualified types } /**************************************************************************** * Element ***************************************************************************/ -function Element() {}; - -Element.decode = function(ber) { - var tag = ber.peek(); - if(tag == BER.APPLICATION(1)) { - if (DEBUG) { console.log("Parameter decode");} - return Parameter.decode(ber); - } else if(tag == BER.APPLICATION(3)) { - if (DEBUG) { console.log("Node decode");} - return Node.decode(ber); - } else if(tag == BER.APPLICATION(2)) { - if (DEBUG) { console.log("Command decode");} - return Command.decode(ber); - } else if(tag == BER.APPLICATION(9)) { - if (DEBUG) { console.log("QualifiedParameter decode");} - return QualifiedParameter.decode(ber); - } else if(tag == BER.APPLICATION(10)) { - if (DEBUG) { console.log("QualifiedNode decode");} - return QualifiedNode.decode(ber); - } else if(tag == BER.APPLICATION(13)) { - if (DEBUG) { console.log("MatrixNode decode");} - return MatrixNode.decode(ber); - } - else if(tag == BER.APPLICATION(17)) { - if (DEBUG) { console.log("QualifiedMatrix decode");} - return QualifiedMatrix.decode(ber); - } - else if(tag == BER.APPLICATION(19)) { - // Function - throw new errors.UnimplementedEmberTypeError(tag); - } else if (tag == BER.APPLICATION(20)) { - return QualifiedFunction.decode(ber); - } - else if(tag == BER.APPLICATION(24)) { - // Template - throw new errors.UnimplementedEmberTypeError(tag); - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } +function Element () {}; + +Element.decode = function (ber) { + var tag = ber.peek() + if (tag === BER.APPLICATION(1)) { + if (DEBUG) { console.log('Parameter decode') } + return Parameter.decode(ber) + } else if (tag === BER.APPLICATION(3)) { + if (DEBUG) { console.log('Node decode') } + return Node.decode(ber) + } else if (tag === BER.APPLICATION(2)) { + if (DEBUG) { console.log('Command decode') } + return Command.decode(ber) + } else if (tag === BER.APPLICATION(9)) { + if (DEBUG) { console.log('QualifiedParameter decode') } + return QualifiedParameter.decode(ber) + } else if (tag === BER.APPLICATION(10)) { + if (DEBUG) { console.log('QualifiedNode decode') } + return QualifiedNode.decode(ber) + } else if (tag === BER.APPLICATION(13)) { + if (DEBUG) { console.log('MatrixNode decode') } + return MatrixNode.decode(ber) + } else if (tag === BER.APPLICATION(17)) { + if (DEBUG) { console.log('QualifiedMatrix decode') } + return QualifiedMatrix.decode(ber) + } else if (tag === BER.APPLICATION(19)) { + // Function + throw new errors.UnimplementedEmberTypeError(tag) + } else if (tag === BER.APPLICATION(20)) { + return QualifiedFunction.decode(ber) + } else if (tag === BER.APPLICATION(24)) { + // Template + throw new errors.UnimplementedEmberTypeError(tag) + } else { + throw new errors.UnimplementedEmberTypeError(tag) + } } /**************************************************************************** * ElementCollection ***************************************************************************/ - - /**************************************************************************** * QualifiedNode ***************************************************************************/ -function QualifiedNode(path) { - QualifiedNode.super_.call(this); - if (path != undefined) { - this.path = path; +function QualifiedNode (path) { + QualifiedNode.super_.call(this) + if (path !== undefined) { + this.path = path + } +} + +util.inherits(QualifiedNode, TreeNode) + +QualifiedNode.decode = function (ber) { + var qn = new QualifiedNode() + ber = ber.getSequence(BER.APPLICATION(10)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + qn.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) // 13 => relative OID + } else if (tag === BER.CONTEXT(1)) { + qn.contents = NodeContents.decode(seq) + } else if (tag === BER.CONTEXT(2)) { + qn.children = [] + seq = seq.getSequence(BER.APPLICATION(4)) + while (seq.remain > 0) { + var nodeSeq = seq.getSequence(BER.CONTEXT(0)) + qn.addChild(Element.decode(nodeSeq)) + } + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } + if (DEBUG) { console.log('QualifiedNode', qn) } + return qn } -util.inherits(QualifiedNode, TreeNode); - - -QualifiedNode.decode = function(ber) { - var qn = new QualifiedNode(); - ber = ber.getSequence(BER.APPLICATION(10)); - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - qn.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); // 13 => relative OID - } - else if(tag == BER.CONTEXT(1)) { - qn.contents = NodeContents.decode(seq); - } else if(tag == BER.CONTEXT(2)) { - qn.children = []; - seq = seq.getSequence(BER.APPLICATION(4)); - while(seq.remain > 0) { - var nodeSeq = seq.getSequence(BER.CONTEXT(0)); - qn.addChild(Element.decode(nodeSeq)); - } - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } +QualifiedNode.prototype.update = function (other) { + var callbacks = QualifiedNode.super_.prototype.update.apply(this) + if ((other === undefined) && (other.contents !== undefined)) { + // console.log("other: ", other.contents); + for (var key in other.contents) { + // console.log(key, other.contents.hasOwnProperty(key)); + if (other.contents.hasOwnProperty(key)) { + this.contents[key] = other.contents[key] + } } - if (DEBUG) { console.log("QualifiedNode", qn); } - return qn; -} - -QualifiedNode.prototype.update = function(other) { - callbacks = QualifiedNode.super_.prototype.update.apply(this); - if((other === undefined) && (other.contents !== undefined)) { - //console.log("other: ", other.contents); - for(var key in other.contents) { - //console.log(key, other.contents.hasOwnProperty(key)); - if(other.contents.hasOwnProperty(key)) { - this.contents[key] = other.contents[key]; - } - } - } - return callbacks; + } + return callbacks } -function QualifiedNodeCommand(self, cmd, callback) { - var r = new Root(); - var qn = new QualifiedNode(); - qn.path = self.path; - r.addElement(qn); - qn.addChild(new Command(cmd)); - if(callback !== undefined) { - self._directoryCallbacks.push((error, node) => { callback(error, node) }); - } - return r; +function QualifiedNodeCommand (self, cmd, callback) { + var r = new Root() + var qn = new QualifiedNode() + qn.path = self.path + r.addElement(qn) + qn.addChild(new Command(cmd)) + if (callback !== undefined) { + self._directoryCallbacks.push((error, node) => { callback(error, node) }) + } + return r } -QualifiedNode.prototype.getDirectory = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedNodeCommand(this, COMMAND_GETDIRECTORY, callback) +QualifiedNode.prototype.getDirectory = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedNodeCommand(this, COMMAND_GETDIRECTORY, callback) } -QualifiedNode.prototype.subscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedNodeCommand(this, COMMAND_SUBSCRIBE, callback) +QualifiedNode.prototype.subscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedNodeCommand(this, COMMAND_SUBSCRIBE, callback) } -QualifiedNode.prototype.unsubscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedNodeCommand(this, COMMAND_UNSUBSCRIBE, callback) +QualifiedNode.prototype.unsubscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedNodeCommand(this, COMMAND_UNSUBSCRIBE, callback) } -QualifiedNode.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(10)); +QualifiedNode.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(10)) - ber.startSequence(BER.CONTEXT(0)); - ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID); - ber.endSequence(); // BER.CONTEXT(0) + ber.startSequence(BER.CONTEXT(0)) + ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID) + ber.endSequence() // BER.CONTEXT(0) - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); // BER.CONTEXT(1) - } + if (this.contents !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + this.contents.encode(ber) + ber.endSequence() // BER.CONTEXT(1) + } - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - n.number = seq.readInt(); - } else if(tag == BER.CONTEXT(1)) { - n.contents = NodeContents.decode(seq); - } else if(tag == BER.CONTEXT(2)) { - seq = seq.getSequence(BER.APPLICATION(4)); - n.children = []; - while(seq.remain > 0) { - var nodeSeq = seq.getSequence(BER.CONTEXT(0)); - n.addChild(Element.decode(nodeSeq)); - } - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } +util.inherits(Node, TreeNode) + +Node.decode = function (ber) { + var n = new Node() + ber = ber.getSequence(BER.APPLICATION(3)) + + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + n.number = seq.readInt() + } else if (tag === BER.CONTEXT(1)) { + n.contents = NodeContents.decode(seq) + } else if (tag === BER.CONTEXT(2)) { + seq = seq.getSequence(BER.APPLICATION(4)) + n.children = [] + while (seq.remain > 0) { + var nodeSeq = seq.getSequence(BER.CONTEXT(0)) + n.addChild(Element.decode(nodeSeq)) + } + } else { + throw new errors.UnimplementedEmberTypeError(tag) } - if (DEBUG) { console.log("Node", n); } - return n; + } + if (DEBUG) { console.log('Node', n) } + return n } -Node.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(3)); - - ber.startSequence(BER.CONTEXT(0)); - ber.writeInt(this.number); - ber.endSequence(); // BER.CONTEXT(0) +Node.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(3)) - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); // BER.CONTEXT(1) - } + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(this.number) + ber.endSequence() // BER.CONTEXT(0) - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if (tag == BER.CONTEXT(0)) { - m.number = seq.readInt(); - } - else if (tag == BER.CONTEXT(1)) { - m.contents = MatrixContents.decode(seq); - - } else if (tag == BER.CONTEXT(2)) { - m.children = []; - seq = seq.getSequence(BER.APPLICATION(4)); - while (seq.remain > 0) { - var childSeq = seq.getSequence(BER.CONTEXT(0)); - m.addChild(Element.decode(childSeq)); - } - } else if (tag == BER.CONTEXT(3)) { - m.targets = decodeTargets(seq); - } else if (tag == BER.CONTEXT(4)) { - m.sources = decodeSources(seq); - } else if (tag == BER.CONTEXT(5)) { - m.connections = {}; - seq = seq.getSequence(BER.EMBER_SEQUENCE); - while(seq.remain > 0) { - var conSeq = seq.getSequence(BER.CONTEXT(0)); - var con = MatrixConnection.decode(conSeq); - if (con.target !== undefined) { - m.connections[con.target] = (con); - } - } - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } - } - if (DEBUG) { console.log("MatrixNode", m); } - return m; -}; - -MatrixNode.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(13)); - - ber.startSequence(BER.CONTEXT(0)); - ber.writeInt(this.number); - ber.endSequence(); // BER.CONTEXT(0) - - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); // BER.CONTEXT(1) - } - - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i 0) { - var tag = ber.peek(); - //console.log("Next tag", tag, ber.buffer); - var seq = ber.getSequence(tag); - - if(tag == BER.CONTEXT(0)) { - mc.identifier = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(1)) { - mc.description = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(2)) { - mc.type = MatrixType.get(seq.readInt()); - } else if(tag == BER.CONTEXT(3)) { - mc.mode = MatrixMode.get(seq.readInt()); - } else if(tag == BER.CONTEXT(4)) { - mc.targetCount = seq.readInt(); - } else if(tag == BER.CONTEXT(5)) { - mc.sourceCount = seq.readInt(); - } else if(tag == BER.CONTEXT(6)) { - mc.maximumTotalConnects = seq.readInt(); - } else if(tag == BER.CONTEXT(7)) { - mc.maximumConnectsPerTarget = seq.readInt(); - } else if(tag == BER.CONTEXT(8)) { - mc.parametersLocation = seq.readInt(); - } else if(tag == BER.CONTEXT(9)) { - mc.gainParameterNumber = seq.readInt(); - } else if(tag == BER.CONTEXT(10)) { - mc.labels = []; - //console.log("\n\nLABEL\n\n",seq.buffer); - seq = seq.getSequence(BER.EMBER_SEQUENCE); - while(seq.remain > 0) { - var lSeq = seq.getSequence(BER.CONTEXT(0)); - mc.labels.push(Label.decode(lSeq)); - } - //console.log(mc); - } else if(tag == BER.CONTEXT(11)) { - mc.schemaIdentifiers = seq.readInt(); - } else if(tag == BER.CONTEXT(12)) { - mc.templateReference = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } - } - //console.log("end of matrix contents"); - return mc; -}; - -MatrixContents.prototype.encode = function(ber) { - ber.startSequence(BER.EMBER_SET); - if (this.identifier !== undefined) { - ber.startSequence(BER.CONTEXT(0)); - ber.writeString(this.identifier, BER.EMBER_STRING); - ber.endSequence(); - } - if (this.description !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeString(this.description, BER.EMBER_STRING); - ber.endSequence(); - } - if (this.type !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.writeInt(this.type.value); - ber.endSequence(); - } - if (this.mode !== undefined) { - ber.startSequence(BER.CONTEXT(3)); - ber.writeInt(this.mode.value); - ber.endSequence(); - } - if (this.targetCount !== undefined) { - ber.startSequence(BER.CONTEXT(4)); - ber.writeInt(this.targetCount); - ber.endSequence(); - } - if (this.sourceCount !== undefined) { - ber.startSequence(BER.CONTEXT(5)); - ber.writeInt(this.sourceCount); - ber.endSequence(); - } - if (this.maximumTotalConnects !== undefined) { - ber.startSequence(BER.CONTEXT(6)); - ber.writeInt(this.maximumTotalConnects); - ber.endSequence(); - } - if (this.maximumConnectsPerTarget !== undefined) { - ber.startSequence(BER.CONTEXT(7)); - ber.writeInt(this.maximumConnectsPerTarget); - ber.endSequence(); - } - if (this.parametersLocation !== undefined) { - ber.startSequence(BER.CONTEXT(8)); - ber.writeInt(this.parametersLocation); - ber.endSequence(); - } - if (this.gainParameterNumber !== undefined) { - ber.startSequence(BER.CONTEXT(9)); - ber.writeInt(this.gainParameterNumber); - ber.endSequence(); - } - if (this.labels !== undefined) { - ber.startSequence(BER.CONTEXT(10)); - ber.startSequence(BER.EMBER_SEQUENCE); - for(var i =0; i < this.labels.length; i++) { - ber.startSequence(BER.CONTEXT(0)); - this.labels[i].encode(ber); - ber.endSequence(); - } - ber.endSequence(); - ber.endSequence(); - } - if (this.schemaIdentifiers !== undefined) { - ber.startSequence(BER.CONTEXT(11)); - ber.writeInt(this.schemaIdentifiers, BER.EMBER_STRING); - ber.endSequence(); - } - if (this.templateReference !== undefined) { - ber.startSequence(BER.CONTEXT(12)); - ber.writeRelativeOID(this.templateReference, BER.EMBER_RELATIVE_OID); - ber.endSequence(); - } - ber.endSequence(); -} - -decodeTargets = function(ber) { - let targets = []; - - ber = ber.getSequence(BER.EMBER_SEQUENCE); - - - while(ber.remain > 0) { - var seq = ber.getSequence(BER.CONTEXT(0)); - seq = seq.getSequence(BER.APPLICATION(14)); - seq = seq.getSequence(BER.CONTEXT(0)); - targets.push(seq.readInt()); +function MatrixNode (number) { + MatrixNode.super_.call(this) + if (number !== undefined) { this.number = number } +} + +MatrixNode.decode = function (ber) { + var m = new MatrixNode() + ber = ber.getSequence(BER.APPLICATION(13)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + m.number = seq.readInt() + } else if (tag === BER.CONTEXT(1)) { + m.contents = MatrixContents.decode(seq) + } else if (tag === BER.CONTEXT(2)) { + m.children = [] + seq = seq.getSequence(BER.APPLICATION(4)) + while (seq.remain > 0) { + var childSeq = seq.getSequence(BER.CONTEXT(0)) + m.addChild(Element.decode(childSeq)) + } + } else if (tag === BER.CONTEXT(3)) { + m.targets = decodeTargets(seq) + } else if (tag === BER.CONTEXT(4)) { + m.sources = decodeSources(seq) + } else if (tag === BER.CONTEXT(5)) { + m.connections = {} + seq = seq.getSequence(BER.EMBER_SEQUENCE) + while (seq.remain > 0) { + var conSeq = seq.getSequence(BER.CONTEXT(0)) + var con = MatrixConnection.decode(conSeq) + if (con.target !== undefined) { + m.connections[con.target] = (con) + } + } + } else { + throw new errors.UnimplementedEmberTypeError(tag) } - - return targets; + } + if (DEBUG) { console.log('MatrixNode', m) } + return m } -decodeSources = function(ber) { - let sources = []; - - ber = ber.getSequence(BER.EMBER_SEQUENCE); - - while(ber.remain > 0) { - var seq = ber.getSequence(BER.CONTEXT(0)); - seq = seq.getSequence(BER.APPLICATION(15)); - seq = seq.getSequence(BER.CONTEXT(0)); - sources.push(seq.readInt()); - } - - return sources; -}; +MatrixNode.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(13)) + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(this.number) + ber.endSequence() // BER.CONTEXT(0) -module.exports.MatrixContents = MatrixContents; + if (this.contents !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + this.contents.encode(ber) + ber.endSequence() // BER.CONTEXT(1) + } - - -function MatrixConnection(target) { - if (target) { - target = Number(target); - if (isNaN(target)) { target = 0; } - this.target = target; - } - else { - this.target = 0; - } + if (this.children !== undefined) { + ber.startSequence(BER.CONTEXT(2)) + ber.startSequence(BER.APPLICATION(4)) + for (var i = 0; i < this.children.length; i++) { + ber.startSequence(BER.CONTEXT(0)) + this.children[i].encode(ber) + ber.endSequence() + } + ber.endSequence() + ber.endSequence() + } + + if (this.targets !== undefined) { + ber.startSequence(BER.CONTEXT(3)) + ber.startSequence(BER.EMBER_SEQUENCE) + + for (var i = 0; i < this.targets.length; i++) { // eslint-disable-line no-redeclare + ber.startSequence(BER.CONTEXT(0)) + ber.startSequence(BER.APPLICATION(14)) + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(this.targets[i]) + ber.endSequence() + ber.endSequence() + ber.endSequence() + } + + ber.endSequence() + ber.endSequence() + } + + if (this.sources !== undefined) { + ber.startSequence(BER.CONTEXT(4)) + ber.startSequence(BER.EMBER_SEQUENCE) + + for (var i = 0; i < this.sources.length; i++) { // eslint-disable-line no-redeclare + ber.startSequence(BER.CONTEXT(0)) + ber.startSequence(BER.APPLICATION(15)) + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(this.sources[i]) + ber.endSequence() + ber.endSequence() + ber.endSequence() + } + + ber.endSequence() + ber.endSequence() + } + + if (this.connections !== undefined) { + ber.startSequence(BER.CONTEXT(5)) + for (var id in this.connections) { + if (this.connections.hasOwnProperty(id)) { + ber.startSequence(BER.CONTEXT(0)) + this.connections[id].encode(ber) + ber.endSequence() + } + } + ber.endSequence() + } + + ber.endSequence() // BER.APPLICATION(3) +} + +MatrixNode.prototype.update = function (other) { + var callbacks = MatrixNode.super_.prototype.update.apply(this) + MatrixUpdate(this, other) + return callbacks +} + +MatrixNode.prototype.connect = function (connections) { + let r = this.getTreeBranch() + let m = r.getElementByPath(this.getPath()) + m.connections = connections + return r +} + +util.inherits(MatrixNode, TreeNode) + +module.exports.MatrixNode = MatrixNode + +function MatrixContents () { + this.type = MatrixType.oneToOne + this.mode = MatrixMode.linear +} + +MatrixContents.decode = function (ber) { + var mc = new MatrixContents() + + // console.log("\n\n Matrix Content\n\n", ber.buffer); + ber = ber.getSequence(BER.EMBER_SET) + + while (ber.remain > 0) { + var tag = ber.peek() + // console.log("Next tag", tag, ber.buffer); + var seq = ber.getSequence(tag) + + if (tag === BER.CONTEXT(0)) { + mc.identifier = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(1)) { + mc.description = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(2)) { + mc.type = MatrixType.get(seq.readInt()) + } else if (tag === BER.CONTEXT(3)) { + mc.mode = MatrixMode.get(seq.readInt()) + } else if (tag === BER.CONTEXT(4)) { + mc.targetCount = seq.readInt() + } else if (tag === BER.CONTEXT(5)) { + mc.sourceCount = seq.readInt() + } else if (tag === BER.CONTEXT(6)) { + mc.maximumTotalConnects = seq.readInt() + } else if (tag === BER.CONTEXT(7)) { + mc.maximumConnectsPerTarget = seq.readInt() + } else if (tag === BER.CONTEXT(8)) { + mc.parametersLocation = seq.readInt() + } else if (tag === BER.CONTEXT(9)) { + mc.gainParameterNumber = seq.readInt() + } else if (tag === BER.CONTEXT(10)) { + mc.labels = [] + // console.log("\n\nLABEL\n\n",seq.buffer); + seq = seq.getSequence(BER.EMBER_SEQUENCE) + while (seq.remain > 0) { + var lSeq = seq.getSequence(BER.CONTEXT(0)) + mc.labels.push(Label.decode(lSeq)) + } + // console.log(mc); + } else if (tag === BER.CONTEXT(11)) { + mc.schemaIdentifiers = seq.readInt() + } else if (tag === BER.CONTEXT(12)) { + mc.templateReference = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) + } else { + throw new errors.UnimplementedEmberTypeError(tag) + } + } + // console.log("end of matrix contents"); + return mc +} + +MatrixContents.prototype.encode = function (ber) { + ber.startSequence(BER.EMBER_SET) + if (this.identifier !== undefined) { + ber.startSequence(BER.CONTEXT(0)) + ber.writeString(this.identifier, BER.EMBER_STRING) + ber.endSequence() + } + if (this.description !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeString(this.description, BER.EMBER_STRING) + ber.endSequence() + } + if (this.type !== undefined) { + ber.startSequence(BER.CONTEXT(2)) + ber.writeInt(this.type.value) + ber.endSequence() + } + if (this.mode !== undefined) { + ber.startSequence(BER.CONTEXT(3)) + ber.writeInt(this.mode.value) + ber.endSequence() + } + if (this.targetCount !== undefined) { + ber.startSequence(BER.CONTEXT(4)) + ber.writeInt(this.targetCount) + ber.endSequence() + } + if (this.sourceCount !== undefined) { + ber.startSequence(BER.CONTEXT(5)) + ber.writeInt(this.sourceCount) + ber.endSequence() + } + if (this.maximumTotalConnects !== undefined) { + ber.startSequence(BER.CONTEXT(6)) + ber.writeInt(this.maximumTotalConnects) + ber.endSequence() + } + if (this.maximumConnectsPerTarget !== undefined) { + ber.startSequence(BER.CONTEXT(7)) + ber.writeInt(this.maximumConnectsPerTarget) + ber.endSequence() + } + if (this.parametersLocation !== undefined) { + ber.startSequence(BER.CONTEXT(8)) + ber.writeInt(this.parametersLocation) + ber.endSequence() + } + if (this.gainParameterNumber !== undefined) { + ber.startSequence(BER.CONTEXT(9)) + ber.writeInt(this.gainParameterNumber) + ber.endSequence() + } + if (this.labels !== undefined) { + ber.startSequence(BER.CONTEXT(10)) + ber.startSequence(BER.EMBER_SEQUENCE) + for (var i = 0; i < this.labels.length; i++) { + ber.startSequence(BER.CONTEXT(0)) + this.labels[i].encode(ber) + ber.endSequence() + } + ber.endSequence() + ber.endSequence() + } + if (this.schemaIdentifiers !== undefined) { + ber.startSequence(BER.CONTEXT(11)) + ber.writeInt(this.schemaIdentifiers, BER.EMBER_STRING) + ber.endSequence() + } + if (this.templateReference !== undefined) { + ber.startSequence(BER.CONTEXT(12)) + ber.writeRelativeOID(this.templateReference, BER.EMBER_RELATIVE_OID) + ber.endSequence() + } + ber.endSequence() +} + +var decodeTargets = function (ber) { + let targets = [] + + ber = ber.getSequence(BER.EMBER_SEQUENCE) + + while (ber.remain > 0) { + var seq = ber.getSequence(BER.CONTEXT(0)) + seq = seq.getSequence(BER.APPLICATION(14)) + seq = seq.getSequence(BER.CONTEXT(0)) + targets.push(seq.readInt()) + } + + return targets +} + +var decodeSources = function (ber) { + let sources = [] + + ber = ber.getSequence(BER.EMBER_SEQUENCE) + + while (ber.remain > 0) { + var seq = ber.getSequence(BER.CONTEXT(0)) + seq = seq.getSequence(BER.APPLICATION(15)) + seq = seq.getSequence(BER.CONTEXT(0)) + sources.push(seq.readInt()) + } + + return sources +} + +module.exports.MatrixContents = MatrixContents + +function MatrixConnection (target) { + if (target) { + target = Number(target) + if (isNaN(target)) { target = 0 } + this.target = target + } else { + this.target = 0 + } } // ConnectionOperation ::= @@ -999,10 +968,10 @@ function MatrixConnection(target) { // connection // } var MatrixOperation = new Enum({ - absolute: 0, - connect: 1, - disconnect: 2 -}); + absolute: 0, + connect: 1, + disconnect: 2 +}) // ConnectionDisposition ::= // INTEGER { @@ -1013,1162 +982,1130 @@ var MatrixOperation = new Enum({ // -- more tbd. // } var MatrixDisposition = new Enum({ - tally: 0, - modified: 1, - pending: 2, - locked: 3 -}); - -module.exports.MatrixOperation = MatrixOperation; -module.exports.MatrixDisposition = MatrixDisposition; - -MatrixConnection.prototype.setSources = function(sources) { - if (sources === undefined) { - delete this.sources; - return; - } - let s = new Set(sources); - this.sources = [...s].sort(); // sources should be an array -} - -MatrixConnection.prototype.connectSources = function(sources) { - if (sources === undefined) { - return; - } - let s = new Set(this.sources); - for(let item of sources) { - s.add(item); - } - this.sources = [...s].sort(); -} - -MatrixConnection.prototype.disconnectSources = function(sources) { - if (sources === undefined) { - return; - } - let s = new Set(this.sources); - for(let item of sources) { - s.delete(item); - } - this.sources = [...s].sort(); -} - -MatrixConnection.decode = function(ber) { - var c = new MatrixConnection(); - ber = ber.getSequence(BER.APPLICATION(16)); - while (ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if (tag == BER.CONTEXT(0)) { - c.target = seq.readInt(); - } - else if (tag == BER.CONTEXT(1)) { - //sources - var sources = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); - c.sources = sources.split("."); - } else if (tag == BER.CONTEXT(2)) { - c.operation = MatrixOperation.get(seq.readInt()); - - } else if (tag == BER.CONTEXT(3)) { - c.disposition = MatrixDisposition.get(seq.readInt()); - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } + tally: 0, + modified: 1, + pending: 2, + locked: 3 +}) + +module.exports.MatrixOperation = MatrixOperation +module.exports.MatrixDisposition = MatrixDisposition + +MatrixConnection.prototype.setSources = function (sources) { + if (sources === undefined) { + delete this.sources + return + } + let s = new Set(sources) + this.sources = [...s].sort() // sources should be an array +} + +MatrixConnection.prototype.connectSources = function (sources) { + if (sources === undefined) { + return + } + let s = new Set(this.sources) + for (let item of sources) { + s.add(item) + } + this.sources = [...s].sort() +} + +MatrixConnection.prototype.disconnectSources = function (sources) { + if (sources === undefined) { + return + } + let s = new Set(this.sources) + for (let item of sources) { + s.delete(item) + } + this.sources = [...s].sort() +} + +MatrixConnection.decode = function (ber) { + var c = new MatrixConnection() + ber = ber.getSequence(BER.APPLICATION(16)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + c.target = seq.readInt() + } else if (tag === BER.CONTEXT(1)) { + // sources + var sources = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) + c.sources = sources.split('.') + } else if (tag === BER.CONTEXT(2)) { + c.operation = MatrixOperation.get(seq.readInt()) + } else if (tag === BER.CONTEXT(3)) { + c.disposition = MatrixDisposition.get(seq.readInt()) + } else { + throw new errors.UnimplementedEmberTypeError(tag) } - return c; + } + return c } -MatrixConnection.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(16)); +MatrixConnection.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(16)) - ber.startSequence(BER.CONTEXT(0)); - ber.writeInt(this.target); - ber.endSequence(); + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(this.target) + ber.endSequence() - if ((this.sources !== undefined)&& (this.sources.length > 0)) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeRelativeOID(this.sources.join("."), BER.EMBER_RELATIVE_OID); - ber.endSequence(); - } - if (this.operation !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.writeInt(this.operation.value); - ber.endSequence(); - } - if (this.disposition !== undefined) { - ber.startSequence(BER.CONTEXT(3)); - ber.writeInt(this.disposition.value); - ber.endSequence(); - } - ber.endSequence(); + if ((this.sources !== undefined) && (this.sources.length > 0)) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeRelativeOID(this.sources.join('.'), BER.EMBER_RELATIVE_OID) + ber.endSequence() + } + if (this.operation !== undefined) { + ber.startSequence(BER.CONTEXT(2)) + ber.writeInt(this.operation.value) + ber.endSequence() + } + if (this.disposition !== undefined) { + ber.startSequence(BER.CONTEXT(3)) + ber.writeInt(this.disposition.value) + ber.endSequence() + } + ber.endSequence() } -module.exports.MatrixConnection = MatrixConnection; +module.exports.MatrixConnection = MatrixConnection -function Label(path) { - if (path) { - this.basePath = path; - } +function Label (path) { + if (path) { + this.basePath = path + } } -Label.decode = function(ber) { - var l = new Label(); +Label.decode = function (ber) { + var l = new Label() - ber = ber.getSequence(BER.APPLICATION(18)); + ber = ber.getSequence(BER.APPLICATION(18)) - while (ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if (tag == BER.CONTEXT(0)) { - l.basePath = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); - } else if (tag == BER.CONTEXT(1)) { - l.description = seq.readString(BER.EMBER_STRING); - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } - } - return l; -}; - -Label.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(18)); - if (this.basePath !== undefined) { - ber.startSequence(BER.CONTEXT(0)); - ber.writeRelativeOID(this.basePath, BER.EMBER_RELATIVE_OID); - ber.endSequence(); - } - if (this.description !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeString(this.description, BER.EMBER_STRING); - ber.endSequence(); + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + l.basePath = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) + } else if (tag === BER.CONTEXT(1)) { + l.description = seq.readString(BER.EMBER_STRING) + } else { + throw new errors.UnimplementedEmberTypeError(tag) } - ber.endSequence(); + } + return l } -module.exports.Label = Label; +Label.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(18)) + if (this.basePath !== undefined) { + ber.startSequence(BER.CONTEXT(0)) + ber.writeRelativeOID(this.basePath, BER.EMBER_RELATIVE_OID) + ber.endSequence() + } + if (this.description !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeString(this.description, BER.EMBER_STRING) + ber.endSequence() + } + ber.endSequence() +} +module.exports.Label = Label -function ParametersLocation() { +function ParametersLocation () { } -ParametersLocation.decode = function(ber) { - var tag = ber.peek(); - ber = ber.getSequence(tag); - this.value = ber.readValue(); +ParametersLocation.decode = function (ber) { + var tag = ber.peek() + ber = ber.getSequence(tag) + this.value = ber.readValue() } -module.exports.ParametersLocation = ParametersLocation; - - +module.exports.ParametersLocation = ParametersLocation var MatrixType = new Enum({ - oneToN: 0, - oneToOne: 1, - nToN: 2 -}); - - -module.exports.MatrixType = MatrixType; + oneToN: 0, + oneToOne: 1, + nToN: 2 +}) +module.exports.MatrixType = MatrixType var MatrixMode = new Enum({ - linear: 0, - nonLinear: 1 -}); - - -module.exports.MatrixMode = MatrixMode; + linear: 0, + nonLinear: 1 +}) +module.exports.MatrixMode = MatrixMode /**************************************************************************** * QualifiedMatrix ***************************************************************************/ -function QualifiedMatrix(path) { - QualifiedMatrix.super_.call(this); - if (path != undefined) { - this.path = path; +function QualifiedMatrix (path) { + QualifiedMatrix.super_.call(this) + if (path !== undefined) { + this.path = path + } +} + +util.inherits(QualifiedMatrix, TreeNode) + +QualifiedMatrix.decode = function (ber) { + var qm = new QualifiedMatrix() + ber = ber.getSequence(BER.APPLICATION(17)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + qm.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) // 13 => relative OID + } else if (tag === BER.CONTEXT(1)) { + qm.contents = MatrixContents.decode(seq) + } else if (tag === BER.CONTEXT(2)) { + qm.children = [] + seq = seq.getSequence(BER.APPLICATION(4)) + while (seq.remain > 0) { + var nodeSeq = seq.getSequence(BER.CONTEXT(0)) + qm.addChild(Element.decode(nodeSeq)) + } + } else if (tag === BER.CONTEXT(3)) { + qm.targets = decodeTargets(seq) + } else if (tag === BER.CONTEXT(4)) { + qm.sources = decodeSources(seq) + } else if (tag === BER.CONTEXT(5)) { + qm.connections = {} + seq = seq.getSequence(BER.EMBER_SEQUENCE) + while (seq.remain > 0) { + var conSeq = seq.getSequence(BER.CONTEXT(0)) + var con = MatrixConnection.decode(conSeq) + if (con.target !== undefined) { + qm.connections[con.target] = con + } + } + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } + if (DEBUG) { console.log('QualifiedMatrix', qm) } + return qm } -util.inherits(QualifiedMatrix, TreeNode); - - -QualifiedMatrix.decode = function(ber) { - var qm = new QualifiedMatrix(); - ber = ber.getSequence(BER.APPLICATION(17)); - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - qm.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); // 13 => relative OID - } - else if(tag == BER.CONTEXT(1)) { - qm.contents = MatrixContents.decode(seq); - } else if(tag == BER.CONTEXT(2)) { - qm.children = []; - seq = seq.getSequence(BER.APPLICATION(4)); - while(seq.remain > 0) { - var nodeSeq = seq.getSequence(BER.CONTEXT(0)); - qm.addChild(Element.decode(nodeSeq)); - } - } else if (tag == BER.CONTEXT(3)) { - qm.targets = decodeTargets(seq); - } else if (tag == BER.CONTEXT(4)) { - qm.sources = decodeSources(seq); - } else if (tag == BER.CONTEXT(5)) { - qm.connections = {}; - seq = seq.getSequence(BER.EMBER_SEQUENCE); - while(seq.remain > 0) { - var conSeq = seq.getSequence(BER.CONTEXT(0)); - var con = MatrixConnection.decode(conSeq); - if (con.target !== undefined) { - qm.connections[con.target] = con; - } - } - } - else { - throw new errors.UnimplementedEmberTypeError(tag); +function MatrixUpdate (matrix, newMatrix) { + if (newMatrix !== undefined) { + if (newMatrix.contents !== undefined) { + for (var key in newMatrix.contents) { + // console.log(key, other.contents.hasOwnProperty(key)); + if (newMatrix.contents.hasOwnProperty(key)) { + matrix.contents[key] = newMatrix.contents[key] } + } } - if (DEBUG) { console.log("QualifiedMatrix", qm); } - return qm; -} - -function MatrixUpdate(matrix, newMatrix) { - if (newMatrix !== undefined) { - if (newMatrix.contents !== undefined) { - for(var key in newMatrix.contents) { - //console.log(key, other.contents.hasOwnProperty(key)); - if (newMatrix.contents.hasOwnProperty(key)) { - matrix.contents[key] = newMatrix.contents[key]; - } - } - } - if (newMatrix.targets !== undefined) { - matrix.targets = newMatrix.targets; - } - if (newMatrix.sources !== undefined) { - matrix.sources = newMatrix.sources; - } - if (newMatrix.connections !== undefined) { - if (matrix.connections === undefined) { - matrix.connections = {}; - } - for(let id in newMatrix.connections) { - if (newMatrix.connections.hasOwnProperty(id)) { - let connection = newMatrix.connections[id]; - if ((connection.target < matrix.contents.targetCount) && + if (newMatrix.targets !== undefined) { + matrix.targets = newMatrix.targets + } + if (newMatrix.sources !== undefined) { + matrix.sources = newMatrix.sources + } + if (newMatrix.connections !== undefined) { + if (matrix.connections === undefined) { + matrix.connections = {} + } + for (let id in newMatrix.connections) { + if (newMatrix.connections.hasOwnProperty(id)) { + let connection = newMatrix.connections[id] + if ((connection.target < matrix.contents.targetCount) && (connection.target >= 0)) { - matrix.connections[connection.target].setSources(connection.sources); - } - } - } + matrix.connections[connection.target].setSources(connection.sources) + } } + } } + } } - -QualifiedMatrix.prototype.update = function(other) { - callbacks = QualifiedMatrix.super_.prototype.update.apply(this); - MatrixUpdate(this, other); - return callbacks; + +QualifiedMatrix.prototype.update = function (other) { + var callbacks = QualifiedMatrix.super_.prototype.update.apply(this) + MatrixUpdate(this, other) + return callbacks } -function QualifiedMatrixCommand(self, cmd, callback) { - var r = new Root(); - var qn = new QualifiedMatrix(); - qn.path = self.path; - r.addElement(qn); - qn.addChild(new Command(cmd)); - if(callback !== undefined) { - self._directoryCallbacks.push((error, node) => { callback(error, node) }); - } - return r; -} +function QualifiedMatrixCommand (self, cmd, callback) { + var r = new Root() + var qn = new QualifiedMatrix() + qn.path = self.path + r.addElement(qn) + qn.addChild(new Command(cmd)) + if (callback !== undefined) { + self._directoryCallbacks.push((error, node) => { callback(error, node) }) + } + return r +} + +QualifiedMatrix.prototype.getDirectory = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedMatrixCommand(this, COMMAND_GETDIRECTORY, callback) +} -QualifiedMatrix.prototype.getDirectory = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedMatrixCommand(this, COMMAND_GETDIRECTORY, callback); +QualifiedMatrix.prototype.subscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedMatrixCommand(this, COMMAND_SUBSCRIBE, callback) } -QualifiedMatrix.prototype.subscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedMatrixCommand(this, COMMAND_SUBSCRIBE, callback); +QualifiedMatrix.prototype.unsubscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedMatrixCommand(this, COMMAND_UNSUBSCRIBE, callback) } -QualifiedMatrix.prototype.unsubscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedMatrixCommand(this, COMMAND_UNSUBSCRIBE, callback); +QualifiedMatrix.prototype.connect = function (connections) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + var r = new Root() + var qn = new QualifiedMatrix() + qn.path = this.path + r.addElement(qn) + qn.connections = connections + return r } -QualifiedMatrix.prototype.connect = function(connections) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - var r = new Root(); - var qn = new QualifiedMatrix(); - qn.path = this.path; - r.addElement(qn); - qn.connections = connections; - return r; -} +QualifiedMatrix.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(17)) -QualifiedMatrix.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(17)); + ber.startSequence(BER.CONTEXT(0)) + ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID) + ber.endSequence() // BER.CONTEXT(0) - ber.startSequence(BER.CONTEXT(0)); - ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID); - ber.endSequence(); // BER.CONTEXT(0) - - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); // BER.CONTEXT(1) - } + if (this.contents !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + this.contents.encode(ber) + ber.endSequence() // BER.CONTEXT(1) + } - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i 0) { - tag = ber.peek(); - var seq = ber.getSequence(tag); +function FunctionContent () { +} + +var decodeTupleDescription = function (ber) { + var tuple = {} + ber = ber.getSequence(BER.APPLICATION(21)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + tuple.type = seq.readInt() + } else if (tag === BER.CONTEXT(1)) { + tuple.name = seq.readString(BER.EMBER_STRING) + } + } + return tuple +} + +var encodeTupleDescription = function (tuple, ber) { + ber.startSequence(BER.APPLICATION(21)) + if (tuple.type !== undefined) { + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(tuple.type) + ber.endSequence() + } + if (tuple.name !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeString(tuple.name) + ber.endSequence() + } + ber.endSequence() +} + +FunctionContent.decode = function (ber) { + var fc = new FunctionContent() + ber = ber.getSequence(BER.EMBER_SET) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + fc.identifier = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(1)) { + fc.description = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(2)) { + fc.arguments = [] + seq = seq.getSequence(BER.EMBER_SEQUENCE) + while (seq.remain > 0) { + tag = seq.peek() + var dataSeq = seq.getSequence(BER.CONTEXT(0)) if (tag === BER.CONTEXT(0)) { - tuple.type = seq.readInt(); - } - else if (tag === BER.CONTEXT(1)) { - tuple.name = seq.readString(BER.EMBER_STRING); - } - } - return tuple; -}; - -encodeTupleDescription = function(tuple, ber) { - ber.startSequence(BER.APPLICATION(21)); - if (tuple.type !== undefined) { - ber.startSequence(BER.CONTEXT(0)); - ber.writeInt(tuple.type); - ber.endSequence(); - } - if (tuple.name !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeString(tuple.name); - ber.endSequence(); - } - ber.endSequence(); -} - -FunctionContent.decode = function(ber) { - var fc = new FunctionContent(); - ber = ber.getSequence(BER.EMBER_SET); - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - fc.identifier = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(1)) { - fc.description = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(2)) { - fc.arguments = []; - seq = seq.getSequence(BER.EMBER_SEQUENCE); - while(seq.remain > 0) { - tag = seq.peek(); - var dataSeq = seq.getSequence(BER.CONTEXT(0)); - if (tag === BER.CONTEXT(0)) { - fc.arguments.push(decodeTupleDescription(dataSeq)); - } - } - } else if(tag == BER.CONTEXT(3)) { - fc.result = []; - while(seq.remain > 0) { - tag = seq.peek(); - var dataSeq = seq.getSequence(tag); - if (tag === BER.CONTEXT(0)) { - fc.result.push(decodeTupleDescription(dataSeq)); - } - } - } else if(tag == BER.CONTEXT(4)) { - fc.templateReference = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); - } else { - throw new errors.UnimplementedEmberTypeError(tag); + fc.arguments.push(decodeTupleDescription(dataSeq)) + } + } + } else if (tag === BER.CONTEXT(3)) { + fc.result = [] + while (seq.remain > 0) { + tag = seq.peek() + var dataSeq = seq.getSequence(tag) // eslint-disable-line no-redeclare + if (tag === BER.CONTEXT(0)) { + fc.result.push(decodeTupleDescription(dataSeq)) } + } + } else if (tag === BER.CONTEXT(4)) { + fc.templateReference = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } - return fc; + return fc } -FunctionContent.prototype.encode = function(ber) { - ber.startSequence(BER.EMBER_SET); +FunctionContent.prototype.encode = function (ber) { + ber.startSequence(BER.EMBER_SET) - if(this.identifier !== undefined) { - ber.startSequence(BER.CONTEXT(0)); - ber.writeString(this.identifier, BER.EMBER_STRING); - ber.endSequence(); // BER.CONTEXT(0) - } + if (this.identifier !== undefined) { + ber.startSequence(BER.CONTEXT(0)) + ber.writeString(this.identifier, BER.EMBER_STRING) + ber.endSequence() // BER.CONTEXT(0) + } - if(this.description !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeString(this.description, BER.EMBER_STRING); - ber.endSequence(); // BER.CONTEXT(1) - } + if (this.description !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeString(this.description, BER.EMBER_STRING) + ber.endSequence() // BER.CONTEXT(1) + } - if(this.arguments !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.EMBER_SEQUENCE); - for(var i =0; i < this.arguments; i++) { - ber.startSequence(BER.CONTEXT(0)); - encodeTupleDescription(this.arguments[i], ber); - ber.endSequence(); - } - ber.endSequence(); - ber.endSequence(); // BER.CONTEXT(2) + if (this.arguments !== undefined) { + ber.startSequence(BER.CONTEXT(2)) + ber.startSequence(BER.EMBER_SEQUENCE) + for (var i = 0; i < this.arguments; i++) { + ber.startSequence(BER.CONTEXT(0)) + encodeTupleDescription(this.arguments[i], ber) + ber.endSequence() } + ber.endSequence() + ber.endSequence() // BER.CONTEXT(2) + } - if(this.result !== undefined) { - ber.startSequence(BER.CONTEXT(3)); - ber.startSequence(BER.EMBER_SEQUENCE); - for(var i =0; i < this.result; i++) { - ber.startSequence(BER.CONTEXT(0)); - encodeTupleDescription(this.result[i], ber); - ber.endSequence(); - } - ber.endSequence(); - ber.endSequence(); // BER.CONTEXT(3) + if (this.result !== undefined) { + ber.startSequence(BER.CONTEXT(3)) + ber.startSequence(BER.EMBER_SEQUENCE) + for (var i = 0; i < this.result; i++) { // eslint-disable-line no-redeclare + ber.startSequence(BER.CONTEXT(0)) + encodeTupleDescription(this.result[i], ber) + ber.endSequence() } + ber.endSequence() + ber.endSequence() // BER.CONTEXT(3) + } - ber.endSequence(); // BER.EMBER_SET + ber.endSequence() // BER.EMBER_SET } -module.exports.FunctionContent = FunctionContent; +module.exports.FunctionContent = FunctionContent /**************************************************************************** * QualifiedFunction ***************************************************************************/ -function QualifiedFunction(path) { - QualifiedFunction.super_.call(this); - if (path != undefined) { - this.path = path; +function QualifiedFunction (path) { + QualifiedFunction.super_.call(this) + if (path !== undefined) { + this.path = path + } +} + +util.inherits(QualifiedFunction, TreeNode) + +QualifiedFunction.decode = function (ber) { + var qf = new QualifiedFunction() + ber = ber.getSequence(BER.APPLICATION(20)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + qf.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) // 13 => relative OID + } else if (tag === BER.CONTEXT(1)) { + qf.contents = FunctionContent.decode(seq) + } else if (tag === BER.CONTEXT(2)) { + qf.children = [] + seq = seq.getSequence(BER.APPLICATION(4)) + while (seq.remain > 0) { + var nodeSeq = seq.getSequence(BER.CONTEXT(0)) + qf.addChild(Element.decode(nodeSeq)) + } + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } + return qf } -util.inherits(QualifiedFunction, TreeNode); - - -QualifiedFunction.decode = function(ber) { - var qf = new QualifiedFunction(); - ber = ber.getSequence(BER.APPLICATION(20)); - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - qf.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); // 13 => relative OID - } - else if(tag == BER.CONTEXT(1)) { - qf.contents = FunctionContent.decode(seq); - } else if(tag == BER.CONTEXT(2)) { - qf.children = []; - seq = seq.getSequence(BER.APPLICATION(4)); - while(seq.remain > 0) { - var nodeSeq = seq.getSequence(BER.CONTEXT(0)); - qf.addChild(Element.decode(nodeSeq)); - } - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } - } - return qf; -} - -QualifiedFunction.prototype.update = function(other) { - callbacks = QualifiedFunction.super_.prototype.update.apply(this); - if ((other !== undefined) && (other.contents !== undefined)) { - //console.log("other: ", other.contents); - for(var key in other.contents) { - //console.log(key, other.contents.hasOwnProperty(key)); - if(other.contents.hasOwnProperty(key)) { - this.contents[key] = other.contents[key]; - } - } +QualifiedFunction.prototype.update = function (other) { + var callbacks = QualifiedFunction.super_.prototype.update.apply(this) + if ((other !== undefined) && (other.contents !== undefined)) { + // console.log("other: ", other.contents); + for (var key in other.contents) { + // console.log(key, other.contents.hasOwnProperty(key)); + if (other.contents.hasOwnProperty(key)) { + this.contents[key] = other.contents[key] + } } - return callbacks; + } + return callbacks } -function QualifiedFunctionCommand(self, cmd, callback) { - var r = new Root(); - var qf = new QualifiedFunction(); - qf.path = self.path; - r.addElement(qf); - qf.addChild(new Command(cmd)); - if(callback !== undefined) { - self._directoryCallbacks.push((error, node) => { callback(error, node) }); - } - return r; +function QualifiedFunctionCommand (self, cmd, callback) { + var r = new Root() + var qf = new QualifiedFunction() + qf.path = self.path + r.addElement(qf) + qf.addChild(new Command(cmd)) + if (callback !== undefined) { + self._directoryCallbacks.push((error, node) => { callback(error, node) }) + } + return r } -QualifiedFunction.prototype.getDirectory = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedFunctionCommand(this, COMMAND_GETDIRECTORY, callback); +QualifiedFunction.prototype.getDirectory = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedFunctionCommand(this, COMMAND_GETDIRECTORY, callback) } -QualifiedFunction.prototype.subscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedFunctionCommand(this, COMMAND_SUBSCRIBE, callback); +QualifiedFunction.prototype.subscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedFunctionCommand(this, COMMAND_SUBSCRIBE, callback) } -QualifiedFunction.prototype.unsubscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedFunctionCommand(this, COMMAND_UNSUBSCRIBE, callback); +QualifiedFunction.prototype.unsubscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedFunctionCommand(this, COMMAND_UNSUBSCRIBE, callback) } -QualifiedFunction.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(20)); +QualifiedFunction.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(20)) - ber.startSequence(BER.CONTEXT(0)); - ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID); - ber.endSequence(); // BER.CONTEXT(0) + ber.startSequence(BER.CONTEXT(0)) + ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID) + ber.endSequence() // BER.CONTEXT(0) - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); // BER.CONTEXT(1) - } + if (this.contents !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + this.contents.encode(ber) + ber.endSequence() // BER.CONTEXT(1) + } - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - nc.identifier = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(1)) { - nc.description = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(2)) { - nc.isRoot = seq.readBoolean(); - } else if(tag == BER.CONTEXT(3)) { - nc.isOnline = seq.readBoolean(); - } else if(tag == BER.CONTEXT(4)) { - nc.schemaIdentifiers = seq.readString(BER.EMBER_STRING); - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } +NodeContents.decode = function (ber) { + var nc = new NodeContents() + ber = ber.getSequence(BER.EMBER_SET) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + nc.identifier = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(1)) { + nc.description = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(2)) { + nc.isRoot = seq.readBoolean() + } else if (tag === BER.CONTEXT(3)) { + nc.isOnline = seq.readBoolean() + } else if (tag === BER.CONTEXT(4)) { + nc.schemaIdentifiers = seq.readString(BER.EMBER_STRING) + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } - return nc; + return nc } -NodeContents.prototype.encode = function(ber) { - ber.startSequence(BER.EMBER_SET); - - if(this.identifier !== undefined) { - ber.startSequence(BER.CONTEXT(0)); - ber.writeString(this.identifier, BER.EMBER_STRING); - ber.endSequence(); // BER.CONTEXT(0) - } - - if(this.description !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeString(this.description, BER.EMBER_STRING); - ber.endSequence(); // BER.CONTEXT(1) - } - - if(this.isRoot !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.writeBoolean(this.isRoot); - ber.endSequence(); // BER.CONTEXT(2) - } - - if(this.isOnline !== undefined) { - ber.startSequence(BER.CONTEXT(3)); - ber.writeBoolean(this.isOnline); - ber.endSequence(); // BER.CONTEXT(3) - } - - if(this.schemaIdentifiers !== undefined) { - ber.startSequence(BER.CONTEXT(4)); - ber.writeString(this.schemaIdentifiers, BER.EMBER_STRING); - ber.endSequence(); // BER.CONTEXT(4) - } +NodeContents.prototype.encode = function (ber) { + ber.startSequence(BER.EMBER_SET) + + if (this.identifier !== undefined) { + ber.startSequence(BER.CONTEXT(0)) + ber.writeString(this.identifier, BER.EMBER_STRING) + ber.endSequence() // BER.CONTEXT(0) + } + + if (this.description !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeString(this.description, BER.EMBER_STRING) + ber.endSequence() // BER.CONTEXT(1) + } - ber.endSequence(); // BER.EMBER_SET + if (this.isRoot !== undefined) { + ber.startSequence(BER.CONTEXT(2)) + ber.writeBoolean(this.isRoot) + ber.endSequence() // BER.CONTEXT(2) + } + + if (this.isOnline !== undefined) { + ber.startSequence(BER.CONTEXT(3)) + ber.writeBoolean(this.isOnline) + ber.endSequence() // BER.CONTEXT(3) + } + + if (this.schemaIdentifiers !== undefined) { + ber.startSequence(BER.CONTEXT(4)) + ber.writeString(this.schemaIdentifiers, BER.EMBER_STRING) + ber.endSequence() // BER.CONTEXT(4) + } + + ber.endSequence() // BER.EMBER_SET } -module.exports.NodeContents = NodeContents; +module.exports.NodeContents = NodeContents /**************************************************************************** * Command ***************************************************************************/ -function Command(number) { - if(number !== undefined) - this.number = number; - this.fieldFlags = FieldFlags.all; +function Command (number) { + if (number !== undefined) { this.number = number } + this.fieldFlags = FieldFlags.all } var FieldFlags = new Enum({ - sparse: -2, - all: -1, - default: 0, - identifier: 1, - description: 2, - tree: 3, - value: 4, - connections: 5 -}); - -Command.decode = function(ber) { - var c = new Command(); - ber = ber.getSequence(BER.APPLICATION(2)); - - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - c.number = seq.readInt(); - } - else if(tag == BER.CONTEXT(1)) { - c.fieldFlags = FieldFlags.get(seq.readInt()); - } - else if(tag == BER.CONTEXT(2)) { - c.invocation = Invocation.decode(ber); - } - else { - // TODO: options - throw new errors.UnimplementedEmberTypeError(tag); - } + sparse: -2, + all: -1, + default: 0, + identifier: 1, + description: 2, + tree: 3, + value: 4, + connections: 5 +}) + +Command.decode = function (ber) { + var c = new Command() + ber = ber.getSequence(BER.APPLICATION(2)) + + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + c.number = seq.readInt() + } else if (tag === BER.CONTEXT(1)) { + c.fieldFlags = FieldFlags.get(seq.readInt()) + } else if (tag === BER.CONTEXT(2)) { + c.invocation = Invocation.decode(ber) + } else { + // TODO: options + throw new errors.UnimplementedEmberTypeError(tag) } + } - return c; + return c } -Command.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(2)); - - ber.startSequence(BER.CONTEXT(0)); - ber.writeInt(this.number); - ber.endSequence(); // BER.CONTEXT(0) +Command.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(2)) - if (this.fieldFlags) { - ber.startSequence(BER.CONTEXT(1)); - ber.writeInt(this.fieldFlags.value); - ber.endSequence(); - } + ber.startSequence(BER.CONTEXT(0)) + ber.writeInt(this.number) + ber.endSequence() // BER.CONTEXT(0) - if (this.invocation) { - ber.startSequence(BER.CONTEXT(2)); - this.invocation.encode(ber); - ber.endSequence(); - } - // TODO: options + if (this.fieldFlags) { + ber.startSequence(BER.CONTEXT(1)) + ber.writeInt(this.fieldFlags.value) + ber.endSequence() + } - ber.endSequence(); // BER.APPLICATION(2) + if (this.invocation) { + ber.startSequence(BER.CONTEXT(2)) + this.invocation.encode(ber) + ber.endSequence() + } + // TODO: options + + ber.endSequence() // BER.APPLICATION(2) } -module.exports.Command = Command; +module.exports.Command = Command /**************************************************************************** * Invocation ***************************************************************************/ -function Invocation() { - Invocation.super_.call(this); -} - -Invocation.decode = function(ber) { - let invocation = new Invocation(); - ber = ber.getSequence(BER.APPLICATION(22)); - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - invocation.invocationId = seq.readInt(); - } - if(tag == BER.CONTEXT(1)) { - invocation.arguments = []; - let seq = ber.getSequence(BER.EMBER_SEQUENCE); - while(seq.remain > 0) { - tag = seq.peek(); - var dataSeq = seq.getSequence(BER.CONTEXT(0)); - if (tag === BER.CONTEXT(0)) { - invocation.arguments.push(dataSeq.readValue()); - } - } - } - else { - // TODO: options - throw new errors.UnimplementedEmberTypeError(tag); +function Invocation () { + Invocation.super_.call(this) +} + +Invocation.decode = function (ber) { + let invocation = new Invocation() + ber = ber.getSequence(BER.APPLICATION(22)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + invocation.invocationId = seq.readInt() + } + if (tag === BER.CONTEXT(1)) { + invocation.arguments = [] + let seq = ber.getSequence(BER.EMBER_SEQUENCE) + while (seq.remain > 0) { + tag = seq.peek() + var dataSeq = seq.getSequence(BER.CONTEXT(0)) + if (tag === BER.CONTEXT(0)) { + invocation.arguments.push(dataSeq.readValue()) } + } + } else { + // TODO: options + throw new errors.UnimplementedEmberTypeError(tag) } + } - return invocation; + return invocation } -Invocation.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(22)); - ber.startSequence(BER.EMBER_SEQUENCE); +Invocation.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(22)) + ber.startSequence(BER.EMBER_SEQUENCE) - for(var i =0; i < this.arguments; i++) { - ber.startSequence(BER.CONTEXT(0)); - ber.writeValue(this.arguments[i]); - ber.endSequence(); - } + for (var i = 0; i < this.arguments; i++) { + ber.startSequence(BER.CONTEXT(0)) + ber.writeValue(this.arguments[i]) + ber.endSequence() + } - ber.endSequence(); + ber.endSequence() - ber.endSequence(); // BER.APPLICATION(22) + ber.endSequence() // BER.APPLICATION(22) } /**************************************************************************** * QualifiedParameter ***************************************************************************/ -function QualifiedParameter(path) { - QualifiedParameter.super_.call(this); - if(path !== undefined) - this.path = path; -} - -util.inherits(QualifiedParameter, TreeNode); -module.exports.QualifiedParameter = QualifiedParameter; - - -QualifiedParameter.decode = function(ber) { - //console.log("Decoding QualifiedParameter"); - var qp = new QualifiedParameter(); - ber = ber.getSequence(BER.APPLICATION(9)); - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - qp.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID); // 13 => relative OID - //console.log("Decoded path",qp.path); - } - else if(tag == BER.CONTEXT(1)) { - //console.log("Decoding content"); - qp.contents = ParameterContents.decode(seq); - //console.log("Decoded content",qp.contents); - } else if(tag == BER.CONTEXT(2)) { - qp.children = []; - //console.log("Decoding children"); - seq = seq.getSequence(BER.APPLICATION(4)); - while(seq.remain > 0) { - var nodeSeq = seq.getSequence(BER.CONTEXT(0)); - qp.addChild(Element.decode(nodeSeq)); - } - } else { - return qp; - //throw new errors.UnimplementedEmberTypeError(tag); - } +function QualifiedParameter (path) { + QualifiedParameter.super_.call(this) + if (path !== undefined) { this.path = path } +} + +util.inherits(QualifiedParameter, TreeNode) +module.exports.QualifiedParameter = QualifiedParameter + +QualifiedParameter.decode = function (ber) { + // console.log("Decoding QualifiedParameter"); + var qp = new QualifiedParameter() + ber = ber.getSequence(BER.APPLICATION(9)) + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + qp.path = seq.readRelativeOID(BER.EMBER_RELATIVE_OID) // 13 => relative OID + // console.log("Decoded path",qp.path); + } else if (tag === BER.CONTEXT(1)) { + // console.log("Decoding content"); + qp.contents = ParameterContents.decode(seq) + // console.log("Decoded content",qp.contents); + } else if (tag === BER.CONTEXT(2)) { + qp.children = [] + // console.log("Decoding children"); + seq = seq.getSequence(BER.APPLICATION(4)) + while (seq.remain > 0) { + var nodeSeq = seq.getSequence(BER.CONTEXT(0)) + qp.addChild(Element.decode(nodeSeq)) + } + } else { + return qp + // throw new errors.UnimplementedEmberTypeError(tag); } - if (DEBUG) { console.log("QualifiedParameter", qp); } - return qp; + } + if (DEBUG) { console.log('QualifiedParameter', qp) } + return qp } -QualifiedParameter.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(9)); +QualifiedParameter.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(9)) - ber.startSequence(BER.CONTEXT(0)); - ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID); - ber.endSequence(); // BER.CONTEXT(0) + ber.startSequence(BER.CONTEXT(0)) + ber.writeRelativeOID(this.path, BER.EMBER_RELATIVE_OID) + ber.endSequence() // BER.CONTEXT(0) - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); // BER.CONTEXT(1) - } + if (this.contents !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + this.contents.encode(ber) + ber.endSequence() // BER.CONTEXT(1) + } - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i { callback(error, node) }); - } - return r; +function QualifiedParameterCommand (self, cmd, callback) { + let r = new Root() + let qp = new QualifiedParameter() + qp.path = self.path + r.addElement(qp) + qp.addChild(new Command(cmd)) + if (callback !== undefined) { + self._directoryCallbacks.push((error, node) => { callback(error, node) }) + } + return r } -QualifiedParameter.prototype.getDirectory = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedParameterCommand(this, COMMAND_GETDIRECTORY, callback); +QualifiedParameter.prototype.getDirectory = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedParameterCommand(this, COMMAND_GETDIRECTORY, callback) } -QualifiedParameter.prototype.subscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedParameterCommand(this, COMMAND_SUBSCRIBE, callback); +QualifiedParameter.prototype.subscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedParameterCommand(this, COMMAND_SUBSCRIBE, callback) } -QualifiedParameter.prototype.unsubscribe = function(callback) { - if (this.path === undefined) { - throw new Error("Invalid path"); - } - return QualifiedParameterCommand(this, COMMAND_UNSUBSCRIBE, callback); +QualifiedParameter.prototype.unsubscribe = function (callback) { + if (this.path === undefined) { + throw new Error('Invalid path') + } + return QualifiedParameterCommand(this, COMMAND_UNSUBSCRIBE, callback) } -QualifiedParameter.prototype.setValue = function(value, callback) { - if(callback !== undefined) { - this._directoryCallbacks.push(callback); - } +QualifiedParameter.prototype.setValue = function (value, callback) { + if (callback !== undefined) { + this._directoryCallbacks.push(callback) + } - let r = new Root(); - let qp = new QualifiedParameter(this.path); - r.addElement(qp); - qp.contents = new ParameterContents(value); - return r; + let r = new Root() + let qp = new QualifiedParameter(this.path) + r.addElement(qp) + qp.contents = new ParameterContents(value) + return r } /**************************************************************************** * Parameter ***************************************************************************/ -function Parameter(number) { - Parameter.super_.call(this); - if(number !== undefined) - this.number = number; -} - -util.inherits(Parameter, TreeNode); -module.exports.Parameter = Parameter; - -Parameter.decode = function(ber) { - var p = new Parameter(); - ber = ber.getSequence(BER.APPLICATION(1)); - - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - p.number = seq.readInt(); - - } else if(tag == BER.CONTEXT(1)) { - p.contents = ParameterContents.decode(seq); - } else if(tag == BER.CONTEXT(2)) { - seq = seq.getSequence(BER.APPLICATION(4)); - p.children = []; - while(seq.remain > 0) { - var paramSeq = seq.getSequence(BER.CONTEXT(0)); - p.addChild(Element.decode(paramSeq)); - } - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } +function Parameter (number) { + Parameter.super_.call(this) + if (number !== undefined) { this.number = number } +} + +util.inherits(Parameter, TreeNode) +module.exports.Parameter = Parameter + +Parameter.decode = function (ber) { + var p = new Parameter() + ber = ber.getSequence(BER.APPLICATION(1)) + + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + p.number = seq.readInt() + } else if (tag === BER.CONTEXT(1)) { + p.contents = ParameterContents.decode(seq) + } else if (tag === BER.CONTEXT(2)) { + seq = seq.getSequence(BER.APPLICATION(4)) + p.children = [] + while (seq.remain > 0) { + var paramSeq = seq.getSequence(BER.CONTEXT(0)) + p.addChild(Element.decode(paramSeq)) + } + } else { + throw new errors.UnimplementedEmberTypeError(tag) } - if (DEBUG) { console.log("Parameter", p); } - return p; + } + if (DEBUG) { console.log('Parameter', p) } + return p } -Parameter.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(1)); +Parameter.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(1)) - ber.writeIfDefined(this.number, ber.writeInt, 0); + ber.writeIfDefined(this.number, ber.writeInt, 0) - if(this.contents !== undefined) { - ber.startSequence(BER.CONTEXT(1)); - this.contents.encode(ber); - ber.endSequence(); - } + if (this.contents !== undefined) { + ber.startSequence(BER.CONTEXT(1)) + this.contents.encode(ber) + ber.endSequence() + } - if(this.children !== undefined) { - ber.startSequence(BER.CONTEXT(2)); - ber.startSequence(BER.APPLICATION(4)); - for(var i=0; i { - m.contents = new ParameterContents(value); - }); -} - -Parameter.prototype.update = function(other) { - callbacks = Parameter.super_.prototype.update.apply(this); - //console.log('update', this.getPath()); - //console.log(callbacks); - if ((other !== undefined) && (other.contents !== undefined)) { - //console.log("other: ", other.contents); - for(var key in other.contents) { - //console.log(key, other.contents.hasOwnProperty(key)); - if(other.contents.hasOwnProperty(key)) { - this.contents[key] = other.contents[key]; - } - } - } - return callbacks; +Parameter.prototype.setValue = function (value, callback) { + if (callback !== undefined) { + this._directoryCallbacks.push(callback) + } + + return this.getTreeBranch(undefined, (m) => { + m.contents = new ParameterContents(value) + }) } +Parameter.prototype.update = function (other) { + var callbacks = Parameter.super_.prototype.update.apply(this) + // console.log('update', this.getPath()); + // console.log(callbacks); + if ((other !== undefined) && (other.contents !== undefined)) { + // console.log("other: ", other.contents); + for (var key in other.contents) { + // console.log(key, other.contents.hasOwnProperty(key)); + if (other.contents.hasOwnProperty(key)) { + this.contents[key] = other.contents[key] + } + } + } + return callbacks +} var ParameterAccess = new Enum({ - none: 0, - read: 1, - write: 2, - readWrite: 3 -}); + none: 0, + read: 1, + write: 2, + readWrite: 3 +}) var ParameterType = new Enum({ - integer: 1, - real: 2, - string: 3, - boolean: 4, - trigger: 5, - enum: 6, - octets: 7 -}); - -module.exports.ParameterAccess = ParameterAccess; -module.exports.ParameterType = ParameterType; - -function ParameterContents(value) { - if(value !== undefined) { - this.value = value; - } + integer: 1, + real: 2, + string: 3, + boolean: 4, + trigger: 5, + enum: 6, + octets: 7 +}) + +module.exports.ParameterAccess = ParameterAccess +module.exports.ParameterType = ParameterType + +function ParameterContents (value) { + if (value !== undefined) { + this.value = value + } }; -module.exports.ParameterContents = ParameterContents; - -ParameterContents.decode = function(ber) { - var pc = new ParameterContents(); - ber = ber.getSequence(BER.EMBER_SET); - - while(ber.remain > 0) { - var tag = ber.peek(); - var seq = ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - pc.identifier = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(1)) { - pc.description = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(2)) { - pc.value = seq.readValue(); - } else if(tag == BER.CONTEXT(3)) { - pc.minimum = seq.readValue(); - } else if(tag == BER.CONTEXT(4)) { - pc.maximum = seq.readValue(); - } else if(tag == BER.CONTEXT(5)) { - pc.access = ParameterAccess.get(seq.readInt()); - } else if(tag == BER.CONTEXT(6)) { - pc.format = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(7)) { - pc.enumeration = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(8)) { - pc.factor = seq.readInt(); - } else if(tag == BER.CONTEXT(9)) { - pc.isOnline = seq.readBoolean(); - } else if(tag == BER.CONTEXT(10)) { - pc.formula = seq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(11)) { - pc.step = seq.readInt(); - } else if(tag == BER.CONTEXT(12)) { - pc.default = seq.readValue(); - } else if(tag == BER.CONTEXT(13)) { - pc.type = ParameterType.get(seq.readInt()); - } else if(tag == BER.CONTEXT(14)) { - pc.streamIdentifier = seq.readInt(); - } else if(tag == BER.CONTEXT(15)) { - pc.enumMap = StringIntegerCollection.decode(seq); - } else if(tag == BER.CONTEXT(16)) { - pc.streamDescriptor = StreamDescription.decode(seq); - } else if(tag == BER.CONTEXT(17)) { - pc.schemaIdentifiers = seq.readString(BER.EMBER_STRING); - } else if (tag == null) { - break; - } - else { - throw new errors.UnimplementedEmberTypeError(tag); - } - } - return pc; -} - -ParameterContents.prototype.encode = function(ber) { - ber.startSequence(BER.EMBER_SET); - - ber.writeIfDefined(this.identifier, ber.writeString, 0, BER.EMBER_STRING); - ber.writeIfDefined(this.description, ber.writeString, 1, BER.EMBER_STRING); - ber.writeIfDefined(this.value, ber.writeValue, 2); - ber.writeIfDefined(this.minimum, ber.writeValue, 3); - ber.writeIfDefined(this.maximum, ber.writeValue, 4); - ber.writeIfDefinedEnum(this.access, ParameterAccess, ber.writeInt, 5); - ber.writeIfDefined(this.format, ber.writeString, 6, BER.EMBER_STRING); - ber.writeIfDefined(this.enumeration, ber.writeString, 7, BER.EMBER_STRING); - ber.writeIfDefined(this.factor, ber.writeInt, 8); - ber.writeIfDefined(this.isOnline, ber.writeBoolean, 9); - ber.writeIfDefined(this.formula, ber.writeString, 10, BER.EMBER_STRING); - ber.writeIfDefined(this.step, ber.writeInt, 11); - ber.writeIfDefined(this.default, ber.writeValue, 12); - ber.writeIfDefinedEnum(this.type, ParameterType, ber.writeInt, 13); - ber.writeIfDefined(this.streamIdentifier, ber.writeInt, 14); - - if(this.emumMap !== undefined) { - ber.startSequence(BER.CONTEXT(15)); - StringIntegerCollection.encode(ber, this.enumMap); - ber.endSequence(); +module.exports.ParameterContents = ParameterContents + +ParameterContents.decode = function (ber) { + var pc = new ParameterContents() + ber = ber.getSequence(BER.EMBER_SET) + + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + pc.identifier = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(1)) { + pc.description = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(2)) { + pc.value = seq.readValue() + } else if (tag === BER.CONTEXT(3)) { + pc.minimum = seq.readValue() + } else if (tag === BER.CONTEXT(4)) { + pc.maximum = seq.readValue() + } else if (tag === BER.CONTEXT(5)) { + pc.access = ParameterAccess.get(seq.readInt()) + } else if (tag === BER.CONTEXT(6)) { + pc.format = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(7)) { + pc.enumeration = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(8)) { + pc.factor = seq.readInt() + } else if (tag === BER.CONTEXT(9)) { + pc.isOnline = seq.readBoolean() + } else if (tag === BER.CONTEXT(10)) { + pc.formula = seq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(11)) { + pc.step = seq.readInt() + } else if (tag === BER.CONTEXT(12)) { + pc.default = seq.readValue() + } else if (tag === BER.CONTEXT(13)) { + pc.type = ParameterType.get(seq.readInt()) + } else if (tag === BER.CONTEXT(14)) { + pc.streamIdentifier = seq.readInt() + } else if (tag === BER.CONTEXT(15)) { + pc.enumMap = StringIntegerCollection.decode(seq) + } else if (tag === BER.CONTEXT(16)) { + pc.streamDescriptor = StreamDescription.decode(seq) + } else if (tag === BER.CONTEXT(17)) { + pc.schemaIdentifiers = seq.readString(BER.EMBER_STRING) + } else if (tag === null) { + break + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } + return pc +} - if(this.streamDescriptor !== undefined) { - ber.startSequence(BER.CONTEXT(16)); - this.streamDescriptor.encode(ber); - ber.endSequence(); - } +ParameterContents.prototype.encode = function (ber) { + ber.startSequence(BER.EMBER_SET) + + ber.writeIfDefined(this.identifier, ber.writeString, 0, BER.EMBER_STRING) + ber.writeIfDefined(this.description, ber.writeString, 1, BER.EMBER_STRING) + ber.writeIfDefined(this.value, ber.writeValue, 2) + ber.writeIfDefined(this.minimum, ber.writeValue, 3) + ber.writeIfDefined(this.maximum, ber.writeValue, 4) + ber.writeIfDefinedEnum(this.access, ParameterAccess, ber.writeInt, 5) + ber.writeIfDefined(this.format, ber.writeString, 6, BER.EMBER_STRING) + ber.writeIfDefined(this.enumeration, ber.writeString, 7, BER.EMBER_STRING) + ber.writeIfDefined(this.factor, ber.writeInt, 8) + ber.writeIfDefined(this.isOnline, ber.writeBoolean, 9) + ber.writeIfDefined(this.formula, ber.writeString, 10, BER.EMBER_STRING) + ber.writeIfDefined(this.step, ber.writeInt, 11) + ber.writeIfDefined(this.default, ber.writeValue, 12) + ber.writeIfDefinedEnum(this.type, ParameterType, ber.writeInt, 13) + ber.writeIfDefined(this.streamIdentifier, ber.writeInt, 14) + + if (this.emumMap !== undefined) { + ber.startSequence(BER.CONTEXT(15)) + StringIntegerCollection.encode(ber, this.enumMap) + ber.endSequence() + } + + if (this.streamDescriptor !== undefined) { + ber.startSequence(BER.CONTEXT(16)) + this.streamDescriptor.encode(ber) + ber.endSequence() + } - ber.writeIfDefined(this.schemaIdentifiers, ber.writeString, 17, BER.EMBER_STRING); + ber.writeIfDefined(this.schemaIdentifiers, ber.writeString, 17, BER.EMBER_STRING) - ber.endSequence(); + ber.endSequence() } /**************************************************************************** @@ -2177,48 +2114,48 @@ ParameterContents.prototype.encode = function(ber) { // This is untested, VPB doesn't seem to use this that I've seen so far -function StringIntegerCollection() {}; - -StringIntegerCollection.decode = function(ber) { - var enumMap = {}; - ber = ber.getSequence(BER.APPLICATION(8)); - while(ber.remain > 0) { - var seq = ber.getSequence(BER.CONTEXT(0)); - seq = seq.getSequence(BER.APPLICATION(7)); - var entryString, entryInteger; - while(seq.remain > 0) { - var tag = seq.peek(); - var dataSeq = seq.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - entryString = dataSeq.readString(BER.EMBER_STRING); - } else if(tag == BER.CONTEXT(1)) { - entryInteger = dataSeq.readInt(); - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } - } - - enumMap[entryString] = entryInteger; - } - - return new Enum(enumMap); -} - -StringIntegerCollection.encode = function(ber, e) { - ber.startSequence(BER.APPLICATION(8)); - ber.startSequence(BER.CONTEXT(0)); - e.enums.forEach((item) => { - ber.startSequence(BER.APPLICATION(7)); - ber.startSequence(BER.CONTEXT(0)); - ber.writeString(item.key, BER.EMBER_STRING); - ber.endSequence(); - ber.startSequence(BER.CONTEXT(1)); - ber.writeInt(item.value); - ber.endSequence(); - ber.endSequence(); - }); - ber.endSequence(); - ber.endSequence(); +function StringIntegerCollection () {}; + +StringIntegerCollection.decode = function (ber) { + var enumMap = {} + ber = ber.getSequence(BER.APPLICATION(8)) + while (ber.remain > 0) { + var seq = ber.getSequence(BER.CONTEXT(0)) + seq = seq.getSequence(BER.APPLICATION(7)) + var entryString, entryInteger + while (seq.remain > 0) { + var tag = seq.peek() + var dataSeq = seq.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + entryString = dataSeq.readString(BER.EMBER_STRING) + } else if (tag === BER.CONTEXT(1)) { + entryInteger = dataSeq.readInt() + } else { + throw new errors.UnimplementedEmberTypeError(tag) + } + } + + enumMap[entryString] = entryInteger + } + + return new Enum(enumMap) +} + +StringIntegerCollection.encode = function (ber, e) { + ber.startSequence(BER.APPLICATION(8)) + ber.startSequence(BER.CONTEXT(0)) + e.enums.forEach((item) => { + ber.startSequence(BER.APPLICATION(7)) + ber.startSequence(BER.CONTEXT(0)) + ber.writeString(item.key, BER.EMBER_STRING) + ber.endSequence() + ber.startSequence(BER.CONTEXT(1)) + ber.writeInt(item.value) + ber.endSequence() + ber.endSequence() + }) + ber.endSequence() + ber.endSequence() } /**************************************************************************** @@ -2226,54 +2163,52 @@ StringIntegerCollection.encode = function(ber, e) { ***************************************************************************/ var StreamFormat = new Enum({ - unsignedInt8: 0, - unsignedInt16BigEndian: 2, - unsignedInt16LittleEndian: 3, - unsignedInt32BigEndian: 4, - unsignedInt32LittleEndian: 5, - unsignedInt64BigEndian: 6, - unsignedInt64LittleENdian: 7, - signedInt8: 8, - signedInt16BigEndian: 10, - signedInt16LittleEndian: 11, - signedInt32BigEndian: 12, - signedInt32LittleEndian: 13, - signedInt64BigEndian: 14, - signedInt64LittleEndian: 15, - ieeeFloat32BigEndian: 20, - ieeeFloat32LittleEndian: 21, - ieeeFloat64BigEndian: 22, - ieeeFloat64LittleEndian: 23 -}); - -function StreamDescription() {}; - -StreamDescription.decode = function(ber) { - var sd = new StreamDescription(); - ber = ber.getSequence(BER.APPLICATION(12)); - - while(ber.remain > 0) { - var tag = ber.peek(); - var seq =ber.getSequence(tag); - if(tag == BER.CONTEXT(0)) { - sd.format = StreamFormat.get(seq.readInt()); - } else if(tag == BER.CONTEXT(1)) { - sd.offset = seq.readInt(); - } else { - throw new errors.UnimplementedEmberTypeError(tag); - } + unsignedInt8: 0, + unsignedInt16BigEndian: 2, + unsignedInt16LittleEndian: 3, + unsignedInt32BigEndian: 4, + unsignedInt32LittleEndian: 5, + unsignedInt64BigEndian: 6, + unsignedInt64LittleENdian: 7, + signedInt8: 8, + signedInt16BigEndian: 10, + signedInt16LittleEndian: 11, + signedInt32BigEndian: 12, + signedInt32LittleEndian: 13, + signedInt64BigEndian: 14, + signedInt64LittleEndian: 15, + ieeeFloat32BigEndian: 20, + ieeeFloat32LittleEndian: 21, + ieeeFloat64BigEndian: 22, + ieeeFloat64LittleEndian: 23 +}) + +function StreamDescription () {}; + +StreamDescription.decode = function (ber) { + var sd = new StreamDescription() + ber = ber.getSequence(BER.APPLICATION(12)) + + while (ber.remain > 0) { + var tag = ber.peek() + var seq = ber.getSequence(tag) + if (tag === BER.CONTEXT(0)) { + sd.format = StreamFormat.get(seq.readInt()) + } else if (tag === BER.CONTEXT(1)) { + sd.offset = seq.readInt() + } else { + throw new errors.UnimplementedEmberTypeError(tag) } + } - return sd; + return sd } -StreamDescription.prototype.encode = function(ber) { - ber.startSequence(BER.APPLICATION(12)); +StreamDescription.prototype.encode = function (ber) { + ber.startSequence(BER.APPLICATION(12)) - ber.writeIfDefinedEnum(this.format, StreamFormat, ber.writeInt, 0); - ber.writeIfDefined(this.offset, ber.writeInt, 1); + ber.writeIfDefinedEnum(this.format, StreamFormat, ber.writeInt, 0) + ber.writeIfDefined(this.offset, ber.writeInt, 1) - ber.endSequence(); + ber.endSequence() } - - diff --git a/errors.js b/errors.js index 9aad982..82c00ad 100644 --- a/errors.js +++ b/errors.js @@ -1,59 +1,57 @@ -const util = require('util'); +const util = require('util') /**************************************************************************** * UnimplementedEmberType error ***************************************************************************/ -function UnimplementedEmberTypeError(tag) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - var identifier = (tag & 0xC0) >> 6; - var value = (tag & 0x1F).toString(); - var tagStr = tag.toString(); - if(identifier == 0) { - tagStr = "[UNIVERSAL " + value + "]"; - } else if(identifier == 1) { - tagStr = "[APPLICATION " + value + "]"; - } else if(identifier == 2) { - tagStr = "[CONTEXT " + value + "]"; - } else { - tagStr = "[PRIVATE " + value + "]"; - } - this.message = "Unimplemented EmBER type " + tagStr; +function UnimplementedEmberTypeError (tag) { + Error.captureStackTrace(this, this.constructor) + this.name = this.constructor.name + var identifier = (tag & 0xC0) >> 6 + var value = (tag & 0x1F).toString() + var tagStr = tag.toString() + if (identifier === 0) { + tagStr = '[UNIVERSAL ' + value + ']' + } else if (identifier === 1) { + tagStr = '[APPLICATION ' + value + ']' + } else if (identifier === 2) { + tagStr = '[CONTEXT ' + value + ']' + } else { + tagStr = '[PRIVATE ' + value + ']' + } + this.message = 'Unimplemented EmBER type ' + tagStr } -util.inherits(UnimplementedEmberTypeError, Error); -module.exports.UnimplementedEmberTypeError = UnimplementedEmberTypeError; +util.inherits(UnimplementedEmberTypeError, Error) +module.exports.UnimplementedEmberTypeError = UnimplementedEmberTypeError - -function ASN1Error(message) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.message = message; +function ASN1Error (message) { + Error.captureStackTrace(this, this.constructor) + this.name = this.constructor.name + this.message = message } -util.inherits(ASN1Error, Error); -module.exports.ASN1Error = ASN1Error; - -function EmberAccessError(message) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - if(this.message !== undefined) { - this.message = message; - } else { - this.message("Parameter access error"); - } +util.inherits(ASN1Error, Error) +module.exports.ASN1Error = ASN1Error + +function EmberAccessError (message) { + Error.captureStackTrace(this, this.constructor) + this.name = this.constructor.name + if (this.message !== undefined) { + this.message = message + } else { + this.message('Parameter access error') + } } -util.inherits(EmberAccessError, Error); -module.exports.EmberAccessError = EmberAccessError; +util.inherits(EmberAccessError, Error) +module.exports.EmberAccessError = EmberAccessError -function EmberTimeoutError(message) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.message = message; +function EmberTimeoutError (message) { + Error.captureStackTrace(this, this.constructor) + this.name = this.constructor.name + this.message = message } -util.inherits(EmberTimeoutError, Error); -module.exports.EmberTimeoutError = EmberTimeoutError; - +util.inherits(EmberTimeoutError, Error) +module.exports.EmberTimeoutError = EmberTimeoutError diff --git a/index.js b/index.js index 8382e24..79738b3 100755 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ -const DeviceTree = require('./device.js').DeviceTree; -const Decoder = require('./device.js').DecodeBuffer; -const Ember = require("./ember.js"); -const S101 = require("./s101"); -const TreeServer = require("./server"); -module.exports = {DeviceTree, Decoder, Ember, TreeServer, S101}; +const DeviceTree = require('./device.js').DeviceTree +const Decoder = require('./device.js').DecodeBuffer +const Ember = require('./ember.js') +const S101 = require('./s101') +const TreeServer = require('./server') +module.exports = {DeviceTree, Decoder, Ember, TreeServer, S101} diff --git a/package.json b/package.json index e6f2cf9..7ec0a39 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "description": "Javascript implementation of the Ember+ automation protocol", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "eslint *.js", + "lint:fix": "yarn lint --fix" }, "author": "Brian Mayton (http://bdm.cc)", "contributors": [ @@ -16,7 +18,7 @@ "repository": { "type": "git", "url": "https://github.com/bmayton/node-emberplus" - }, + }, "license": "MIT", "dependencies": { "asn1": "evs-broadcast/node-asn1", @@ -24,5 +26,13 @@ "long": "^3.2.0", "smart-buffer": "^3.0.3", "winston-color": "^1.0.0" + }, + "devDependencies": { + "eslint": "^4.19.1", + "eslint-config-standard": "^11.0.0", + "eslint-plugin-import": "^2.11.0", + "eslint-plugin-node": "^6.0.1", + "eslint-plugin-promise": "^3.7.0", + "eslint-plugin-standard": "^3.0.1" } } diff --git a/s101.js b/s101.js index fa467ce..a5f8e61 100755 --- a/s101.js +++ b/s101.js @@ -1,310 +1,308 @@ -const EventEmitter = require('events').EventEmitter; -const util = require('util'); -const SmartBuffer = require('smart-buffer').SmartBuffer; -const winston = require('winston'); +const EventEmitter = require('events').EventEmitter +const util = require('util') +const SmartBuffer = require('smart-buffer').SmartBuffer +const winston = require('winston') -const S101_BOF = 0xFE; -const S101_EOF = 0xFF; -const S101_CE = 0xFD; -const S101_XOR = 0x20; -const S101_INV = 0xF8; +const S101_BOF = 0xFE +const S101_EOF = 0xFF +const S101_CE = 0xFD +const S101_XOR = 0x20 +const S101_INV = 0xF8 -const SLOT = 0x00; +const SLOT = 0x00 -const MSG_EMBER = 0x0E; +const MSG_EMBER = 0x0E -const CMD_EMBER = 0x00; -const CMD_KEEPALIVE_REQ = 0x01; -const CMD_KEEPALIVE_RESP = 0x02; +const CMD_EMBER = 0x00 +const CMD_KEEPALIVE_REQ = 0x01 +const CMD_KEEPALIVE_RESP = 0x02 -const VERSION = 0x01; +const VERSION = 0x01 -const FLAG_SINGLE_PACKET = 0xC0; -const FLAG_FIRST_MULTI_PACKET = 0x80; -const FLAG_LAST_MULTI_PACKET = 0x40; -const FLAG_EMPTY_PACKET = 0x20; -const FLAG_MULTI_PACKET = 0x00; +const FLAG_SINGLE_PACKET = 0xC0 +const FLAG_FIRST_MULTI_PACKET = 0x80 +const FLAG_LAST_MULTI_PACKET = 0x40 +// const FLAG_EMPTY_PACKET = 0x20 +const FLAG_MULTI_PACKET = 0x00 -const DTD_GLOW = 0x01; -const DTD_VERSION_MAJOR = 0x02; -const DTD_VERSION_MINOR = 0x1F; +const DTD_GLOW = 0x01 +const DTD_VERSION_MAJOR = 0x02 +const DTD_VERSION_MINOR = 0x1F const CRC_TABLE = [ - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -]; - -function S101Codec() { - var self = this; - S101Codec.super_.call(this); - self.inbuf = new SmartBuffer(); - self.emberbuf = new SmartBuffer(); - self.escaped = false; + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +] + +function S101Codec () { + var self = this + S101Codec.super_.call(this) + self.inbuf = new SmartBuffer() + self.emberbuf = new SmartBuffer() + self.escaped = false } -util.inherits(S101Codec, EventEmitter); - -S101Codec.prototype.dataIn = function(buf) { - var self = this; - for(var i=0; i 0) { - frame.skip(appBytes); - winston.warn('App bytes with unknown meaning left over'); - } - } - +S101Codec.prototype.handleFrame = function (frame) { + var self = this + // console.log(frame.toBuffer()); + if (!validateFrame(frame.toBuffer())) { + winston.error('dropping frame of length %d with invalid CRC', + frame.length) + return + } + + var slot = frame.readUInt8() + var message = frame.readUInt8() + if (slot !== SLOT || message !== MSG_EMBER) { + winston.error('dropping frame of length %d (not an ember frame; slot=%d, msg=%d)', + frame.length, slot, message) + return + } + + var command = frame.readUInt8() + if (command === CMD_KEEPALIVE_REQ) { + winston.debug('received keepalive request') + self.emit('keepaliveReq') + } else if (command === CMD_KEEPALIVE_RESP) { + winston.debug('received keepalive response') + self.emit('keepaliveResp') + } else if (command === CMD_EMBER) { + self.handleEmberFrame(frame) + } else { + winston.error('dropping frame of length %d with unknown command %d', + frame.length, command) + } +} - var payload = frame.readBuffer(); - payload = payload.slice(0, payload.length - 2); - if(flags === FLAG_SINGLE_PACKET) { - winston.debug('single ember packet'); - self.handleEmberPacket(SmartBuffer.fromBuffer(payload)); - self.emberbuf.clear(); - } else if(flags === FLAG_FIRST_MULTI_PACKET) { - winston.debug('multi ember packet start'); - self.emberbuf.clear(); - self.emberbuf.writeBuffer(payload); - } else if(flags === FLAG_LAST_MULTI_PACKET) { - winston.debug('multi ember packet end'); - self.emberbuf.writeBuffer(payload); - self.emberbuf.moveTo(0); - self.handleEmberPacket(self.emberbuf); - self.emberbuf.clear(); - } else { - winston.debug('multi ember packet'); - self.emberbuf.writeBuffer(payload); +S101Codec.prototype.handleEmberFrame = function (frame) { + var self = this + var version = frame.readUInt8() + var flags = frame.readUInt8() + var dtd = frame.readUInt8() + var appBytes = frame.readUInt8() + + if (version !== VERSION) { + winston.warn('Unknown ember frame version %d', version) + } + + if (dtd !== DTD_GLOW) { + winston.error('Dropping frame with non-Glow DTD') + return + } + + var glowMinor = 0 // eslint-disable-line no-unused-vars + var glowMajor = 0 // eslint-disable-line no-unused-vars + + if (appBytes < 2) { + winston.warn('Frame missing Glow DTD version') + frame.skip(appBytes) + } else { + glowMinor = frame.readUInt8() + glowMajor = frame.readUInt8() + appBytes -= 2 + if (appBytes > 0) { + frame.skip(appBytes) + winston.warn('App bytes with unknown meaning left over') } + } + + var payload = frame.readBuffer() + payload = payload.slice(0, payload.length - 2) + if (flags === FLAG_SINGLE_PACKET) { + winston.debug('single ember packet') + self.handleEmberPacket(SmartBuffer.fromBuffer(payload)) + self.emberbuf.clear() + } else if (flags === FLAG_FIRST_MULTI_PACKET) { + winston.debug('multi ember packet start') + self.emberbuf.clear() + self.emberbuf.writeBuffer(payload) + } else if (flags === FLAG_LAST_MULTI_PACKET) { + winston.debug('multi ember packet end') + self.emberbuf.writeBuffer(payload) + self.emberbuf.moveTo(0) + self.handleEmberPacket(self.emberbuf) + self.emberbuf.clear() + } else { + winston.debug('multi ember packet') + self.emberbuf.writeBuffer(payload) + } } -S101Codec.prototype.handleEmberPacket = function(packet) { - var self = this; +S101Codec.prototype.handleEmberPacket = function (packet) { + var self = this - winston.debug('ember packet'); - //console.log(packet); - self.emit('emberPacket', packet.toBuffer()); + winston.debug('ember packet') + // console.log(packet); + self.emit('emberPacket', packet.toBuffer()) } -var makeBERFrame = function(flags, data) { - var frame = new SmartBuffer(); - frame.writeUInt8(S101_BOF); - frame.writeUInt8(SLOT); - frame.writeUInt8(MSG_EMBER); - frame.writeUInt8(CMD_EMBER); - frame.writeUInt8(VERSION); - frame.writeUInt8(flags); - frame.writeUInt8(DTD_GLOW); - frame.writeUInt8(2); // number of app bytes - frame.writeUInt8(DTD_VERSION_MINOR); - frame.writeUInt8(DTD_VERSION_MAJOR); - frame.writeBuffer(data); - return finalizeBuffer(frame); +var makeBERFrame = function (flags, data) { + var frame = new SmartBuffer() + frame.writeUInt8(S101_BOF) + frame.writeUInt8(SLOT) + frame.writeUInt8(MSG_EMBER) + frame.writeUInt8(CMD_EMBER) + frame.writeUInt8(VERSION) + frame.writeUInt8(flags) + frame.writeUInt8(DTD_GLOW) + frame.writeUInt8(2) // number of app bytes + frame.writeUInt8(DTD_VERSION_MINOR) + frame.writeUInt8(DTD_VERSION_MAJOR) + frame.writeBuffer(data) + return finalizeBuffer(frame) } -S101Codec.prototype.encodeBER = function(data) { - var frames = []; - var encbuf = new SmartBuffer(); - for(var i=0; i= 1024 && i < data.length-1) { - if(frames.length == 0) { - frames.push(makeBERFrame(FLAG_FIRST_MULTI_PACKET, encbuf.toBuffer())); - } else { - frames.push(makeBERFrame(FLAG_MULTI_PACKET, encbuf.toBuffer())); - } - encbuf.clear(); - } +S101Codec.prototype.encodeBER = function (data) { + var frames = [] + var encbuf = new SmartBuffer() + for (var i = 0; i < data.length; i++) { + var b = data.readUInt8(i) + if (b < S101_INV) { + encbuf.writeUInt8(b) + } else { + encbuf.writeUInt8(S101_CE) + encbuf.writeUInt8(b ^ S101_XOR) } - if(frames.length == 0) { - frames.push(makeBERFrame(FLAG_SINGLE_PACKET, encbuf.toBuffer())); - } else { - frames.push(makeBERFrame(FLAG_LAST_MULTI_PACKET, encbuf.toBuffer())); + if (encbuf.length >= 1024 && i < data.length - 1) { + if (frames.length === 0) { + frames.push(makeBERFrame(FLAG_FIRST_MULTI_PACKET, encbuf.toBuffer())) + } else { + frames.push(makeBERFrame(FLAG_MULTI_PACKET, encbuf.toBuffer())) + } + encbuf.clear() } + } - return frames; -}; + if (frames.length === 0) { + frames.push(makeBERFrame(FLAG_SINGLE_PACKET, encbuf.toBuffer())) + } else { + frames.push(makeBERFrame(FLAG_LAST_MULTI_PACKET, encbuf.toBuffer())) + } -S101Codec.prototype.keepAliveRequest = function() { - var packet = new SmartBuffer(); - packet.writeUInt8(S101_BOF); - packet.writeUInt8(SLOT); - packet.writeUInt8(MSG_EMBER); - packet.writeUInt8(CMD_KEEPALIVE_REQ); - return finalizeBuffer(packet); + return frames } -S101Codec.prototype.keepAliveResponse = function() { - var packet = new SmartBuffer(); - packet.writeUInt8(S101_BOF); - packet.writeUInt8(SLOT); - packet.writeUInt8(MSG_EMBER); - packet.writeUInt8(CMD_KEEPALIVE_RESP); - return finalizeBuffer(packet); +S101Codec.prototype.keepAliveRequest = function () { + var packet = new SmartBuffer() + packet.writeUInt8(S101_BOF) + packet.writeUInt8(SLOT) + packet.writeUInt8(MSG_EMBER) + packet.writeUInt8(CMD_KEEPALIVE_REQ) + return finalizeBuffer(packet) } -var finalizeBuffer = function(smartbuf) { - var crc = (~calculateCRCCE(smartbuf.toBuffer().slice(1, smartbuf.length))) & 0xFFFF; - var crc_hi = crc >> 8; - var crc_lo = crc & 0xFF; +S101Codec.prototype.keepAliveResponse = function () { + var packet = new SmartBuffer() + packet.writeUInt8(S101_BOF) + packet.writeUInt8(SLOT) + packet.writeUInt8(MSG_EMBER) + packet.writeUInt8(CMD_KEEPALIVE_RESP) + return finalizeBuffer(packet) +} - if(crc_lo < S101_INV) { - smartbuf.writeUInt8(crc_lo); - } else { - smartbuf.writeUInt8(S101_CE); - smartbuf.writeUInt8(crc_lo ^ S101_XOR); - } - - if(crc_hi < S101_INV) { - smartbuf.writeUInt8(crc_hi); - } else { - smartbuf.writeUInt8(S101_CE); - smartbuf.writeUInt8(crc_hi ^ S101_XOR); - } - - smartbuf.writeUInt8(S101_EOF); - return smartbuf.toBuffer(); +var finalizeBuffer = function (smartbuf) { + var crc = (~calculateCRCCE(smartbuf.toBuffer().slice(1, smartbuf.length))) & 0xFFFF + var crcHi = crc >> 8 + var crcLo = crc & 0xFF + + if (crcLo < S101_INV) { + smartbuf.writeUInt8(crcLo) + } else { + smartbuf.writeUInt8(S101_CE) + smartbuf.writeUInt8(crcLo ^ S101_XOR) + } + + if (crcHi < S101_INV) { + smartbuf.writeUInt8(crcHi) + } else { + smartbuf.writeUInt8(S101_CE) + smartbuf.writeUInt8(crcHi ^ S101_XOR) + } + + smartbuf.writeUInt8(S101_EOF) + return smartbuf.toBuffer() } -var calculateCRC = function(buf) { - var crc = 0xFFFF; - for(var i=0; i < buf.length; i++) { - var b = buf.readUInt8(i); - crc = ((crc >> 8) ^ CRC_TABLE[(crc ^ b) & 0xFF]) & 0xFFFF; - } - return crc; +var calculateCRC = function (buf) { + var crc = 0xFFFF + for (var i = 0; i < buf.length; i++) { + var b = buf.readUInt8(i) + crc = ((crc >> 8) ^ CRC_TABLE[(crc ^ b) & 0xFF]) & 0xFFFF + } + return crc } -var calculateCRCCE = function(buf) { - var crc = 0xFFFF; - for(var i=0; i < buf.length; i++) { - var b = buf.readUInt8(i); - if(b == S101_CE) { - b = S101_XOR ^ buf.readUInt8(++i); - } - crc = ((crc >> 8) ^ CRC_TABLE[(crc ^ b) & 0xFF]) & 0xFFFF; +var calculateCRCCE = function (buf) { + var crc = 0xFFFF + for (var i = 0; i < buf.length; i++) { + var b = buf.readUInt8(i) + if (b === S101_CE) { + b = S101_XOR ^ buf.readUInt8(++i) } - return crc; + crc = ((crc >> 8) ^ CRC_TABLE[(crc ^ b) & 0xFF]) & 0xFFFF + } + return crc } -var validateFrame = function(buf) { - return calculateCRC(buf) == 0xF0B8; +var validateFrame = function (buf) { + return calculateCRC(buf) === 0xF0B8 } -S101Codec.prototype.validateFrame = validateFrame; +S101Codec.prototype.validateFrame = validateFrame -module.exports = S101Codec; +module.exports = S101Codec diff --git a/server.js b/server.js index a829fe9..ec61a61 100755 --- a/server.js +++ b/server.js @@ -1,549 +1,507 @@ -const EventEmitter = require('events').EventEmitter; -const util = require('util'); -const S101Server = require('./client.js').S101Server; -const ember = require('./ember.js'); - -function TreeServer(host, port, tree) { - TreeServer.super_.call(this); - var self = this; - self._debug = false; - - self.callback = undefined; - self.timeoutValue = 2000; - self.server = new S101Server(host, port); - self.tree = tree; - self.clients = new Set(); - self.subscribers = {}; - - self.server.on('listening', () => { - if (self._debug) { console.log("listening"); } - self.emit('listening'); - if (self.callback !== undefined) { - self.callback(); - self.callback = undefined; - } - }); - - self.server.on('connection', (client) => { - if (self._debug) { console.log("new connection from", client.remoteAddress()); } - self.clients.add(client); - client.on("emberTree", (root) => { - if (self._debug) { console.log("new request from", client.remoteAddress(), root); } - // Queue the action to make sure responses are sent in order. - client.addRequest(() => { - try { - let path = self.handleRoot(client, root); - self.emit("request", {client: client.remoteAddress(), root: root, path: path}); - } - catch(e) { - if (self._debug) { console.log(e.stack); } - self.emit("error", e); - } - }); - }); - client.on("disconnected", () => { - self.clients.delete(client); - self.emit('disconnect', client.remoteAddress()); - }); - self.emit('connection', client.remoteAddress()); - }); - - self.server.on('disconnected', () => { - self.emit('disconnected', client.remoteAddress()); - }); - - self.server.on("error", (e) => { - self.emit("error", e); - if (self.callback !== undefined) { - self.callback(e); +const EventEmitter = require('events').EventEmitter +const util = require('util') +const S101Server = require('./client.js').S101Server +const ember = require('./ember.js') + +function TreeServer (host, port, tree) { + TreeServer.super_.call(this) + var self = this + self._debug = false + + self.callback = undefined + self.timeoutValue = 2000 + self.server = new S101Server(host, port) + self.tree = tree + self.clients = new Set() + self.subscribers = {} + + self.server.on('listening', () => { + if (self._debug) { console.log('listening') } + self.emit('listening') + if (self.callback !== undefined) { + self.callback() + self.callback = undefined + } + }) + + self.server.on('connection', (client) => { + if (self._debug) { console.log('new connection from', client.remoteAddress()) } + self.clients.add(client) + client.on('emberTree', (root) => { + if (self._debug) { console.log('new request from', client.remoteAddress(), root) } + // Queue the action to make sure responses are sent in order. + client.addRequest(() => { + try { + let path = self.handleRoot(client, root) + self.emit('request', {client: client.remoteAddress(), root: root, path: path}) + } catch (e) { + if (self._debug) { console.log(e.stack) } + self.emit('error', e) } - }); - + }) + }) + client.on('disconnected', () => { + self.clients.delete(client) + self.emit('disconnect', client.remoteAddress()) + }) + self.emit('connection', client.remoteAddress()) + }) + + self.server.on('disconnected', () => { + self.emit('disconnected') + }) + + self.server.on('error', (e) => { + self.emit('error', e) + if (self.callback !== undefined) { + self.callback(e) + } + }) } -util.inherits(TreeServer, EventEmitter); - - -TreeServer.prototype.listen = function() { - return new Promise((resolve, reject) => { - this.callback = (e) => { - if (e === undefined) { - return resolve(); - } - return reject(e); - }; - this.server.listen(); - }); -}; - -TreeServer.prototype.handleRoot = function(client, root) { - if ((root === undefined) || (root.elements === undefined) || (root.elements < 1)) { - this.emit("error", new Error("invalid request")); - return; - } - +util.inherits(TreeServer, EventEmitter) - const node = root.elements[0]; - if (this._debug) { - let n; - try { - n = JSON.stringify(node); - } - catch(e) { - n = node; - } - console.log("new request", n); +TreeServer.prototype.listen = function () { + return new Promise((resolve, reject) => { + this.callback = (e) => { + if (e === undefined) { + return resolve() + } + return reject(e) } + this.server.listen() + }) +} - if (node.path !== undefined) { - return this.handleQualifiedNode(client, node); - } - else if (node instanceof ember.Command) { - // Command on root element - this.handleCommand(client, this.tree, node.number); - return "root"; - } - else { - return this.handleNode(client, node); - } +TreeServer.prototype.handleRoot = function (client, root) { + if ((root === undefined) || (root.elements === undefined) || (root.elements < 1)) { + this.emit('error', new Error('invalid request')) + return + } + + const node = root.elements[0] + if (this._debug) { + let n + try { + n = JSON.stringify(node) + } catch (e) { + n = node + } + console.log('new request', n) + } + + if (node.path !== undefined) { + return this.handleQualifiedNode(client, node) + } else if (node instanceof ember.Command) { + // Command on root element + this.handleCommand(client, this.tree, node.number) + return 'root' + } else { + return this.handleNode(client, node) + } } -TreeServer.prototype.handleQualifiedNode = function(client, node) { - const path = node.path; - // Find this element in our tree - const element = this.tree.getElementByPath(path); +TreeServer.prototype.handleQualifiedNode = function (client, node) { + const path = node.path + // Find this element in our tree + const element = this.tree.getElementByPath(path) - if ((element === null) || (element === undefined)) { - this.emit("error", new Error(`unknown element at path ${path}`)); - return; - } + if ((element === null) || (element === undefined)) { + this.emit('error', new Error(`unknown element at path ${path}`)) + return + } - if ((node.children !== undefined) && (node.children.length === 1) && + if ((node.children !== undefined) && (node.children.length === 1) && (node.children[0] instanceof ember.Command)) { - this.handleCommand(client, element, node.children[0].number); - } - else { - if (node instanceof ember.QualifiedMatrix) { - this.handleQualifiedMatrix(client, element, node); - } - else if (node instanceof ember.QualifiedParameter) { - this.handleQualifiedParameter(client, element, node); - } - } - return path; + this.handleCommand(client, element, node.children[0].number) + } else { + if (node instanceof ember.QualifiedMatrix) { + this.handleQualifiedMatrix(client, element, node) + } else if (node instanceof ember.QualifiedParameter) { + this.handleQualifiedParameter(client, element, node) + } + } + return path } - -TreeServer.prototype.handleNode = function(client, node) { - // traverse the tree - let element = node; - let path = []; - while(element !== undefined) { - if (element.number === undefined) { - this.emit("error", "invalid request"); - return; - } - if (element instanceof ember.Command) { - break; - } - path.push(element.number); - - let children = element.getChildren(); - if ((! children) || (children.length === 0)) { - break; - } - element = element.children[0]; - } - let cmd = element; - - if (cmd === undefined) { - this.emit("error", "invalid request"); - return; - } - - element = this.tree.getElementByPath(path.join(".")); - - if ((element === null) || (element === undefined)) { - this.emit("error", new Error(`unknown element at path ${path}`)); - if (this._debug) { console.log(`unknown element at path ${path}`); } - return; - } - - if (cmd instanceof ember.Command) { - this.handleCommand(client, element, cmd.number); - } - else if ((cmd instanceof ember.MatrixNode) && (cmd.connections !== undefined)) { - this.handleMatrixConnections(client, element, cmd.connections); - } - else if ((cmd instanceof ember.Parameter) && +TreeServer.prototype.handleNode = function (client, node) { + // traverse the tree + let element = node + let path = [] + while (element !== undefined) { + if (element.number === undefined) { + this.emit('error', 'invalid request') + return + } + if (element instanceof ember.Command) { + break + } + path.push(element.number) + + let children = element.getChildren() + if ((!children) || (children.length === 0)) { + break + } + element = element.children[0] + } + let cmd = element + + if (cmd === undefined) { + this.emit('error', 'invalid request') + return + } + + element = this.tree.getElementByPath(path.join('.')) + + if ((element === null) || (element === undefined)) { + this.emit('error', new Error(`unknown element at path ${path}`)) + if (this._debug) { console.log(`unknown element at path ${path}`) } + return + } + + if (cmd instanceof ember.Command) { + this.handleCommand(client, element, cmd.number) + } else if ((cmd instanceof ember.MatrixNode) && (cmd.connections !== undefined)) { + this.handleMatrixConnections(client, element, cmd.connections) + } else if ((cmd instanceof ember.Parameter) && (cmd.contents !== undefined) && (cmd.contents.value !== undefined)) { - if (this._debug) { console.log(`setValue for element at path ${path} with value ${cmd.contents.value}`); } - this.setValue(element, cmd.contents.value, client); - } - else { - this.emit("error", new Error("invalid request format")); - if (this._debug) { console.log("invalid request format"); } - } - return path; + if (this._debug) { console.log(`setValue for element at path ${path} with value ${cmd.contents.value}`) } + this.setValue(element, cmd.contents.value, client) + } else { + this.emit('error', new Error('invalid request format')) + if (this._debug) { console.log('invalid request format') } + } + return path } -TreeServer.prototype.handleQualifiedMatrix = function(client, element, matrix) -{ - this.handleMatrixConnections(client, element, matrix.connections); +TreeServer.prototype.handleQualifiedMatrix = function (client, element, matrix) { + this.handleMatrixConnections(client, element, matrix.connections) } -TreeServer.prototype.handleQualifiedParameter = function(client, element, parameter) -{ - if (parameter.contents.value !== undefined) { - this.setValue(element, parameter.contents.value, client); - } +TreeServer.prototype.handleQualifiedParameter = function (client, element, parameter) { + if (parameter.contents.value !== undefined) { + this.setValue(element, parameter.contents.value, client) + } } - -TreeServer.prototype.handleMatrixConnections = function(client, matrix, connections, response = true) { - var res; - var root; // ember message root - if (matrix.isQualified()) { - root = new ember.Root(); - res = new ember.QualifiedMatrix(matrix.path); - root.elements = [res]; // do not use addchild or the element will get removed from the tree. - } - else { - res = new ember.MatrixNode(matrix.number); - root = matrix._parent.getTreeBranch(res); - } - res.connections = {}; - for(let id in connections) { - if (!connections.hasOwnProperty(id)) { - continue; - } - let connection = connections[id]; - let conResult = new ember.MatrixConnection(connection.target); - let emitType; - res.connections[connection.target] = conResult; - - - // Apply changes - - if ((connection.operation === undefined) || - (connection.operation.value == ember.MatrixOperation.absolute)) { - matrix.connections[connection.target].setSources(connection.sources); - emitType = "matrix-change"; - } - else if (connection.operation == ember.MatrixOperation.connect) { - matrix.connections[connection.target].connectSources(connection.sources); - emitType = "matrix-connect"; - } - else { // Disconnect - matrix.connections[connection.target].disconnectSources(connection.sources); - emitType = "matrix-disconnect"; - } - - // Send response or update subscribers. - - if (response) { - conResult.sources = matrix.connections[connection.target].sources; - conResult.disposition = ember.MatrixDisposition.modified; - // We got a request so emit something. - this.emit(emitType, { - target: connection.target, - sources: connection.sources, - client: client.remoteAddress() - }); - } - else { - // the action has been applied. So we should either send the current state (absolute) - // or send the action itself (connection.sources) - conResult.sources = matrix.connections[connection.target].sources; - conResult.operation = ember.MatrixOperation.absolute; - } - } - if (client !== undefined) { - client.sendBERNode(root); - } - else { - this.updateSubscribers(matrix.getPath(), root, client); - } +TreeServer.prototype.handleMatrixConnections = function (client, matrix, connections, response = true) { + var res + var root // ember message root + if (matrix.isQualified()) { + root = new ember.Root() + res = new ember.QualifiedMatrix(matrix.path) + root.elements = [res] // do not use addchild or the element will get removed from the tree. + } else { + res = new ember.MatrixNode(matrix.number) + root = matrix._parent.getTreeBranch(res) + } + res.connections = {} + for (let id in connections) { + if (!connections.hasOwnProperty(id)) { + continue + } + let connection = connections[id] + let conResult = new ember.MatrixConnection(connection.target) + let emitType + res.connections[connection.target] = conResult + + // Apply changes + + if ((connection.operation === undefined) || + (connection.operation.value === ember.MatrixOperation.absolute)) { + matrix.connections[connection.target].setSources(connection.sources) + emitType = 'matrix-change' + } else if (connection.operation === ember.MatrixOperation.connect) { + matrix.connections[connection.target].connectSources(connection.sources) + emitType = 'matrix-connect' + } else { // Disconnect + matrix.connections[connection.target].disconnectSources(connection.sources) + emitType = 'matrix-disconnect' + } + + // Send response or update subscribers. + + if (response) { + conResult.sources = matrix.connections[connection.target].sources + conResult.disposition = ember.MatrixDisposition.modified + // We got a request so emit something. + this.emit(emitType, { + target: connection.target, + sources: connection.sources, + client: client.remoteAddress() + }) + } else { + // the action has been applied. So we should either send the current state (absolute) + // or send the action itself (connection.sources) + conResult.sources = matrix.connections[connection.target].sources + conResult.operation = ember.MatrixOperation.absolute + } + } + if (client !== undefined) { + client.sendBERNode(root) + } else { + this.updateSubscribers(matrix.getPath(), root, client) + } } -const validateMatrixOperation = function(matrix, target, sources) { - if (matrix === undefined) { - throw new Error(`matrix not found with path ${path}`); - } - if (matrix.contents === undefined) { - throw new Error(`invalid matrix at ${path} : no contents`); - } - if (matrix.contents.targetCount === undefined) { - throw new Error(`invalid matrix at ${path} : no targetCount`); - } - if ((target < 0) || (target >= matrix.contents.targetCount)) { - throw new Error(`target id ${target} out of range 0 - ${matrix.contents.targetCount}`); - } - if (sources.length === undefined) { - throw new Error("invalid sources format"); - } +const validateMatrixOperation = function (matrix, target, sources, path) { + if (matrix === undefined) { + throw new Error(`matrix not found with path ${path}`) + } + if (matrix.contents === undefined) { + throw new Error(`invalid matrix at ${path} : no contents`) + } + if (matrix.contents.targetCount === undefined) { + throw new Error(`invalid matrix at ${path} : no targetCount`) + } + if ((target < 0) || (target >= matrix.contents.targetCount)) { + throw new Error(`target id ${target} out of range 0 - ${matrix.contents.targetCount}`) + } + if (sources.length === undefined) { + throw new Error('invalid sources format') + } } -const doMatrixOperation = function(server, path, target, sources, operation) { - let matrix = server.tree.getElementByPath(path); +const doMatrixOperation = function (server, path, target, sources, operation) { + let matrix = server.tree.getElementByPath(path) - validateMatrixOperation(matrix, target, sources); + validateMatrixOperation(matrix, target, sources, path) - let connection = new ember.MatrixConnection(target); - connection.sources = sources; - connection.operation = operation; - server.handleMatrixConnections(undefined, matrix, [connection], false); + let connection = new ember.MatrixConnection(target) + connection.sources = sources + connection.operation = operation + server.handleMatrixConnections(undefined, matrix, [connection], false) } -TreeServer.prototype.matrixConnect = function(path, target, sources) { - doMatrixOperation(this, path, target, sources, ember.MatrixOperation.connect); +TreeServer.prototype.matrixConnect = function (path, target, sources) { + doMatrixOperation(this, path, target, sources, ember.MatrixOperation.connect) } -TreeServer.prototype.matrixDisconnect = function(path, target, sources) { - doMatrixOperation(this, path, target, sources, ember.MatrixOperation.disconnect); +TreeServer.prototype.matrixDisconnect = function (path, target, sources) { + doMatrixOperation(this, path, target, sources, ember.MatrixOperation.disconnect) } -TreeServer.prototype.matrixSet = function(path, target, sources) { - doMatrixOperation(this, path, target, sources, ember.MatrixOperation.absolute); +TreeServer.prototype.matrixSet = function (path, target, sources) { + doMatrixOperation(this, path, target, sources, ember.MatrixOperation.absolute) } -TreeServer.prototype.handleCommand = function(client, element, cmd) { - if (cmd === ember.GetDirectory) { - this.handleGetDirectory(client, element); - } - else if (cmd === ember.Subscribe) { - this.handleSubscribe(client, element); - } - else if (cmd === ember.Unsubscribe) { - this.handleUnSubscribe(client, element); - } - else { - this.emit("error", new Error(`invalid command ${cmd}`)); - } +TreeServer.prototype.handleCommand = function (client, element, cmd) { + if (cmd === ember.GetDirectory) { + this.handleGetDirectory(client, element) + } else if (cmd === ember.Subscribe) { + this.handleSubscribe(client, element) + } else if (cmd === ember.Unsubscribe) { + this.handleUnSubscribe(client, element) + } else { + this.emit('error', new Error(`invalid command ${cmd}`)) + } } -TreeServer.prototype.getResponse = function(element) { - let res = element; - if (element.isQualified()) { - res = new ember.Root(); - res.elements = [element]; - } - else if (element._parent) { - res = element._parent.getTreeBranch(element); - } - return res; +TreeServer.prototype.getResponse = function (element) { + let res = element + if (element.isQualified()) { + res = new ember.Root() + res.elements = [element] + } else if (element._parent) { + res = element._parent.getTreeBranch(element) + } + return res } -TreeServer.prototype.handleGetDirectory = function(client, element) { - - if (client !== undefined) { - if ((element.isMatrix() || element.isParameter()) && +TreeServer.prototype.handleGetDirectory = function (client, element) { + if (client !== undefined) { + if ((element.isMatrix() || element.isParameter()) && (!element.isStream())) { - // ember spec: parameter without streamIdentifier should - // report their value changes automatically. - this.subscribe(client, element); - } - let res = this.getResponse(element); - client.sendBERNode(res); + // ember spec: parameter without streamIdentifier should + // report their value changes automatically. + this.subscribe(client, element) } + let res = this.getResponse(element) + client.sendBERNode(res) + } } -TreeServer.prototype.handleSubscribe = function(client, element) { - this.subscribe(client, element); +TreeServer.prototype.handleSubscribe = function (client, element) { + this.subscribe(client, element) } -TreeServer.prototype.handleUnSubscribe = function(client, element) { - this.unsubscribe(client, element); +TreeServer.prototype.handleUnSubscribe = function (client, element) { + this.unsubscribe(client, element) } - -TreeServer.prototype.subscribe = function(client, element) { - const path = element.getPath(); - if (this.subscribers[path] === undefined) { - this.subscribers[path] = new Set(); - } - this.subscribers[path].add(client); +TreeServer.prototype.subscribe = function (client, element) { + const path = element.getPath() + if (this.subscribers[path] === undefined) { + this.subscribers[path] = new Set() + } + this.subscribers[path].add(client) } -TreeServer.prototype.unsubscribe = function(client, element) { - const path = element.getPath(); - if (this.subscribers[path] === undefined) { - return; - } - this.subscribers[path].delete(client); +TreeServer.prototype.unsubscribe = function (client, element) { + const path = element.getPath() + if (this.subscribers[path] === undefined) { + return + } + this.subscribers[path].delete(client) } -TreeServer.prototype.setValue = function(element, value, origin, key) { - return new Promise((resolve, reject) => { - // Change the element value if write access permitted. - if (element.contents !== undefined) { - if (element.isParameter()) { - if ((element.contents.access !== undefined) && +TreeServer.prototype.setValue = function (element, value, origin, key) { + return new Promise((resolve, reject) => { + // Change the element value if write access permitted. + if (element.contents !== undefined) { + if (element.isParameter()) { + if ((element.contents.access !== undefined) && (element.contents.access.value > 1)) { - element.contents.value = value; - this.emit("value-change", element); - } - } - else if (element.isMatrix()) { - if ((key !== undefined) && (element.contents.hasOwnProperty(key))) { - element.contents[key] = value; - this.emit("value-change", element); - } - } + element.contents.value = value + this.emit('value-change', element) } - - let res = this.getResponse(element); - if (origin) { - if (this._debug) { console.log("Sending setvalue response", res); } - origin.sendBERNode(res) + } else if (element.isMatrix()) { + if ((key !== undefined) && (element.contents.hasOwnProperty(key))) { + element.contents[key] = value + this.emit('value-change', element) } - // Update the subscribers - this.updateSubscribers(element.getPath(), res, origin); - }); -} - -TreeServer.prototype.replaceElement = function(element) { - let path = element.getPath(); - let parent = this.tree.getElementByPath(path); - if ((parent === undefined)||(parent._parent === undefined)) { - throw new Error(`Could not find element at path ${path}`); + } } - parent = parent._parent; - let children = parent.getChildren(); - let newList = []; - for(let i = 0; i <= children.length; i++) { - if (children[i] && children[i].getPath() == path) { - element._parent = parent; // move it to new tree. - children[i] = element; - let res = this.getResponse(element); - this.updateSubscribers(path,res); - return; - } + + let res = this.getResponse(element) + if (origin) { + if (this._debug) { console.log('Sending setvalue response', res) } + origin.sendBERNode(res) } + // Update the subscribers + this.updateSubscribers(element.getPath(), res, origin) + }) } +TreeServer.prototype.replaceElement = function (element) { + let path = element.getPath() + let parent = this.tree.getElementByPath(path) + if ((parent === undefined) || (parent._parent === undefined)) { + throw new Error(`Could not find element at path ${path}`) + } + parent = parent._parent + let children = parent.getChildren() + for (let i = 0; i <= children.length; i++) { + if (children[i] && children[i].getPath() === path) { + element._parent = parent // move it to new tree. + children[i] = element + let res = this.getResponse(element) + this.updateSubscribers(path, res) + return + } + } +} -TreeServer.prototype.updateSubscribers = function(path, response, origin) { - if (this.subscribers[path] === undefined) { - return; - } +TreeServer.prototype.updateSubscribers = function (path, response, origin) { + if (this.subscribers[path] === undefined) { + return + } - for (let client of this.subscribers[path]) { - if (client === origin) { - continue; // already sent the response to origin - } - if (this.clients.has(client)) { - client.queueMessage(response); - } - else { - // clean up subscribers - client is gone - this.subscribers[path].delete(client); - } + for (let client of this.subscribers[path]) { + if (client === origin) { + continue // already sent the response to origin + } + if (this.clients.has(client)) { + client.queueMessage(response) + } else { + // clean up subscribers - client is gone + this.subscribers[path].delete(client) } + } } -const parseObj = function(parent, obj, isQualified) { - let path = parent.getPath(); - for(let i = 0; i < obj.length; i++) { - let emberElement; - let content = obj[i]; - let number = content.number !== undefined ? content.number : i; - delete content.number; - //console.log(`parsing obj at number ${number}`, content); - if (content.value !== undefined) { - //console.log("new parameter"); - // this is a parameter - if (isQualified) { - emberElement = new ember.QualifiedParameter(`${path}${path !== "" ? "." : ""}${number}`); - } - else { - emberElement = new ember.Parameter(number); - } - emberElement.contents = new ember.ParameterContents(content.value); - if (content.type) { - emberElement.contents.type = ember.ParameterType.get(content.type); - delete content.type; - } - else { - emberElement.contents.type = ember.ParameterType.string; - } - if (content.access) { - emberElement.contents.access = ember.ParameterAccess.get(content.access); - delete content.access; - } - else { - emberElement.contents.access = ember.ParameterAccess.read; - } +const parseObj = function (parent, obj, isQualified) { + let path = parent.getPath() + for (let i = 0; i < obj.length; i++) { + let emberElement + let content = obj[i] + let number = content.number !== undefined ? content.number : i + delete content.number + // console.log(`parsing obj at number ${number}`, content); + if (content.value !== undefined) { + // console.log("new parameter"); + // this is a parameter + if (isQualified) { + emberElement = new ember.QualifiedParameter(`${path}${path !== '' ? '.' : ''}${number}`) + } else { + emberElement = new ember.Parameter(number) + } + emberElement.contents = new ember.ParameterContents(content.value) + if (content.type) { + emberElement.contents.type = ember.ParameterType.get(content.type) + delete content.type + } else { + emberElement.contents.type = ember.ParameterType.string + } + if (content.access) { + emberElement.contents.access = ember.ParameterAccess.get(content.access) + delete content.access + } else { + emberElement.contents.access = ember.ParameterAccess.read + } + } else if (content.targetCount !== undefined) { + // console.log("new matrix"); + if (isQualified) { + emberElement = new ember.QualifiedMatrix(`${path}${path !== '' ? '.' : ''}${number}`) + } else { + emberElement = new ember.MatrixNode(number) + } + emberElement.contents = new ember.MatrixContents() + + if (content.labels) { + emberElement.contents.labels = [] + for (let l = 0; l < content.labels.length; l++) { + emberElement.contents.labels.push( + new ember.Label(content.labels[l]) + ) } - else if (content.targetCount !== undefined) { - //console.log("new matrix"); - if (isQualified) { - emberElement = new ember.QualifiedMatrix(`${path}${path !== "" ? "." : ""}${number}`); - } - else { - emberElement = new ember.MatrixNode(number); - } - emberElement.contents = new ember.MatrixContents(); - - if (content.labels) { - emberElement.contents.labels = []; - for(let l = 0; l < content.labels.length; l++) { - emberElement.contents.labels.push( - new ember.Label(content.labels[l]) - ); - } - delete content.labels; - } - - - if (content.connections) { - emberElement.connections = {}; - for (let c in content.connections) { - if (! content.connections.hasOwnProperty(c)) { - continue; - } - let t = content.connections[c].target !== undefined ? content.connections[c].target : 0; - let connection = new ember.MatrixConnection(t); - connection.setSources(content.connections[c].sources); - emberElement.connections[t] = connection; - } - delete content.connections; - } - else { - emberElement.connections = {}; - for (let t = 0; t < content.targetCount; t++) { - let connection = new ember.MatrixConnection(t); - emberElement.connections[t] = connection; - } - } + delete content.labels + } + + if (content.connections) { + emberElement.connections = {} + for (let c in content.connections) { + if (!content.connections.hasOwnProperty(c)) { + continue + } + let t = content.connections[c].target !== undefined ? content.connections[c].target : 0 + let connection = new ember.MatrixConnection(t) + connection.setSources(content.connections[c].sources) + emberElement.connections[t] = connection } - else { - //console.log("new node"); - if (isQualified) { - emberElement = new ember.QualifiedNode(`${path}${path !== "" ? "." : ""}${number}`); - } - else { - emberElement = new ember.Node(number); - } - emberElement.contents = new ember.NodeContents(); + delete content.connections + } else { + emberElement.connections = {} + for (let t = 0; t < content.targetCount; t++) { + let connection = new ember.MatrixConnection(t) + emberElement.connections[t] = connection } - for(let id in content) { - if ((id !== "children") && (content.hasOwnProperty(id))) { - //console.log(`adding contents ${id}`); - emberElement.contents[id] = content[id]; - } - else { - parseObj(emberElement, content.children, isQualified); - } - } - parent.addChild(emberElement); - } + } + } else { + // console.log("new node"); + if (isQualified) { + emberElement = new ember.QualifiedNode(`${path}${path !== '' ? '.' : ''}${number}`) + } else { + emberElement = new ember.Node(number) + } + emberElement.contents = new ember.NodeContents() + } + for (let id in content) { + if ((id !== 'children') && (content.hasOwnProperty(id))) { + // console.log(`adding contents ${id}`); + emberElement.contents[id] = content[id] + } else { + parseObj(emberElement, content.children, isQualified) + } + } + parent.addChild(emberElement) + } } -TreeServer.JSONtoTree = function(obj, isQualified = true) { - let tree = new ember.Root(); - parseObj(tree, obj, isQualified); - return tree; +TreeServer.JSONtoTree = function (obj, isQualified = true) { + let tree = new ember.Root() + parseObj(tree, obj, isQualified) + return tree } -module.exports = TreeServer; +module.exports = TreeServer diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..47133c6 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1113 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^7.0.4": + version "7.0.60" + resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.60.tgz#5406c35961e4f9e2d5a1b9482daa14501754ecda" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.5.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" + +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-escapes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asn1@evs-broadcast/node-asn1: + version "0.5.1" + resolved "https://codeload.github.com/evs-broadcast/node-asn1/tar.gz/2fc158464a92e1465523f108295abd54e7ce86db" + +async@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +colors@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cycle@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + +debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + dependencies: + esutils "^2.0.2" + +enum@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/enum/-/enum-2.5.0.tgz#f205b8c65a335a8ace8081105df971b18568b984" + dependencies: + is-buffer "^1.1.0" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +eslint-config-standard@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz#87ee0d3c9d95382dc761958cbb23da9eea31e0ba" + +eslint-import-resolver-node@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + dependencies: + debug "^2.6.9" + resolve "^1.5.0" + +eslint-module-utils@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-import@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.11.0.tgz#15aeea37a67499d848e8e981806d4627b5503816" + dependencies: + contains-path "^0.1.0" + debug "^2.6.8" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.2.0" + has "^1.0.1" + lodash "^4.17.4" + minimatch "^3.0.3" + read-pkg-up "^2.0.0" + resolve "^1.6.0" + +eslint-plugin-node@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" + dependencies: + ignore "^3.3.6" + minimatch "^3.0.4" + resolve "^1.3.3" + semver "^5.4.1" + +eslint-plugin-promise@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz#f4bde5c2c77cdd69557a8f69a24d1ad3cfc9e67e" + +eslint-plugin-standard@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" + +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + +eslint@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" + dependencies: + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" + esquery "^1.0.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + regexpp "^1.0.1" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "4.0.2" + text-table "~0.2.0" + +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +external-editor@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +eyes@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +function-bind@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + +glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.0.1: + version "11.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.4.0.tgz#b85c793349561c16076a3c13549238a27945f1bc" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hosted-git-info@^2.1.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" + +iconv-lite@^0.4.17: + version "0.4.21" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.21.tgz#c47f8733d02171189ebc4a400f3218d348094798" + dependencies: + safer-buffer "^2.1.0" + +ignore@^3.3.3, ignore@^3.3.6: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-buffer@^1.1.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + +isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isstream@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.9.1: + version "3.11.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash@^4.17.4, lodash@^4.3.0: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + +long@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" + +lru-cache@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + +minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +p-limit@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@^2.2.8: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" + +smart-buffer@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-3.0.3.tgz#76d4abf863d6aa91d5c9fd694cd51b242782e59f" + dependencies: + "@types/node" "^7.0.4" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + +string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" + dependencies: + has-flag "^3.0.0" + +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +winston-color@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/winston-color/-/winston-color-1.0.0.tgz#7dcf28fded016585247f2aadc10ce8aafbe1fac6" + dependencies: + winston "^2.1.1" + +winston@^2.1.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.1.tgz#a3a9265105564263c6785b4583b8c8aca26fded6" + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + stack-trace "0.0.x" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"