UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

626 lines (584 loc) 21.2 kB
(function() { var EventEmitter, Journal, JournalStore, MemoryJournalStore, calculateMeta, clone, entryToPrettyString, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; EventEmitter = require('events').EventEmitter; clone = require('./Utils').clone; entryToPrettyString = function(entry) { var a; a = entry.args; switch (entry.cmd) { case 'addNode': return "" + a.id + "(" + a.component + ")"; case 'removeNode': return "DEL " + a.id + "(" + a.component + ")"; case 'renameNode': return "RENAME " + a.oldId + " " + a.newId; case 'changeNode': return "META " + a.id; case 'addEdge': return "" + a.from.node + " " + a.from.port + " -> " + a.to.port + " " + a.to.node; case 'removeEdge': return "" + a.from.node + " " + a.from.port + " -X> " + a.to.port + " " + a.to.node; case 'changeEdge': return "META " + a.from.node + " " + a.from.port + " -> " + a.to.port + " " + a.to.node; case 'addInitial': return "'" + a.from.data + "' -> " + a.to.port + " " + a.to.node; case 'removeInitial': return "'" + a.from.data + "' -X> " + a.to.port + " " + a.to.node; case 'startTransaction': return ">>> " + entry.rev + ": " + a.id; case 'endTransaction': return "<<< " + entry.rev + ": " + a.id; case 'changeProperties': return "PROPERTIES"; case 'addGroup': return "GROUP " + a.name; case 'renameGroup': return "RENAME GROUP " + a.oldName + " " + a.newName; case 'removeGroup': return "DEL GROUP " + a.name; case 'changeGroup': return "META GROUP " + a.name; case 'addInport': return "INPORT " + a.name; case 'removeInport': return "DEL INPORT " + a.name; case 'renameInport': return "RENAME INPORT " + a.oldId + " " + a.newId; case 'changeInport': return "META INPORT " + a.name; case 'addOutport': return "OUTPORT " + a.name; case 'removeOutport': return "DEL OUTPORT " + a.name; case 'renameOutport': return "RENAME OUTPORT " + a.oldId + " " + a.newId; case 'changeOutport': return "META OUTPORT " + a.name; default: throw new Error("Unknown journal entry: " + entry.cmd); } }; calculateMeta = function(oldMeta, newMeta) { var k, setMeta, v; setMeta = {}; for (k in oldMeta) { v = oldMeta[k]; setMeta[k] = null; } for (k in newMeta) { v = newMeta[k]; setMeta[k] = v; } return setMeta; }; JournalStore = (function(_super) { __extends(JournalStore, _super); JournalStore.prototype.lastRevision = 0; function JournalStore(graph) { this.graph = graph; this.lastRevision = 0; } JournalStore.prototype.putTransaction = function(revId, entries) { if (revId > this.lastRevision) { this.lastRevision = revId; } return this.emit('transaction', revId); }; JournalStore.prototype.fetchTransaction = function(revId, entries) {}; return JournalStore; })(EventEmitter); MemoryJournalStore = (function(_super) { __extends(MemoryJournalStore, _super); function MemoryJournalStore(graph) { MemoryJournalStore.__super__.constructor.call(this, graph); this.transactions = []; } MemoryJournalStore.prototype.putTransaction = function(revId, entries) { MemoryJournalStore.__super__.putTransaction.call(this, revId, entries); return this.transactions[revId] = entries; }; MemoryJournalStore.prototype.fetchTransaction = function(revId) { return this.transactions[revId]; }; return MemoryJournalStore; })(JournalStore); Journal = (function(_super) { __extends(Journal, _super); Journal.prototype.graph = null; Journal.prototype.entries = []; Journal.prototype.subscribed = true; function Journal(graph, metadata, store) { this.endTransaction = __bind(this.endTransaction, this); this.startTransaction = __bind(this.startTransaction, this); var edge, group, iip, k, node, v, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; this.graph = graph; this.entries = []; this.subscribed = true; this.store = store || new MemoryJournalStore(this.graph); if (this.store.transactions.length === 0) { this.currentRevision = -1; this.startTransaction('initial', metadata); _ref = this.graph.nodes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { node = _ref[_i]; this.appendCommand('addNode', node); } _ref1 = this.graph.edges; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { edge = _ref1[_j]; this.appendCommand('addEdge', edge); } _ref2 = this.graph.initializers; for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { iip = _ref2[_k]; this.appendCommand('addInitial', iip); } if (Object.keys(this.graph.properties).length > 0) { this.appendCommand('changeProperties', this.graph.properties, {}); } _ref3 = this.graph.inports; for (k in _ref3) { v = _ref3[k]; this.appendCommand('addInport', { name: k, port: v }); } _ref4 = this.graph.outports; for (k in _ref4) { v = _ref4[k]; this.appendCommand('addOutport', { name: k, port: v }); } _ref5 = this.graph.groups; for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { group = _ref5[_l]; this.appendCommand('addGroup', group); } this.endTransaction('initial', metadata); } else { this.currentRevision = this.store.lastRevision; } this.graph.on('addNode', (function(_this) { return function(node) { return _this.appendCommand('addNode', node); }; })(this)); this.graph.on('removeNode', (function(_this) { return function(node) { return _this.appendCommand('removeNode', node); }; })(this)); this.graph.on('renameNode', (function(_this) { return function(oldId, newId) { var args; args = { oldId: oldId, newId: newId }; return _this.appendCommand('renameNode', args); }; })(this)); this.graph.on('changeNode', (function(_this) { return function(node, oldMeta) { return _this.appendCommand('changeNode', { id: node.id, "new": node.metadata, old: oldMeta }); }; })(this)); this.graph.on('addEdge', (function(_this) { return function(edge) { return _this.appendCommand('addEdge', edge); }; })(this)); this.graph.on('removeEdge', (function(_this) { return function(edge) { return _this.appendCommand('removeEdge', edge); }; })(this)); this.graph.on('changeEdge', (function(_this) { return function(edge, oldMeta) { return _this.appendCommand('changeEdge', { from: edge.from, to: edge.to, "new": edge.metadata, old: oldMeta }); }; })(this)); this.graph.on('addInitial', (function(_this) { return function(iip) { return _this.appendCommand('addInitial', iip); }; })(this)); this.graph.on('removeInitial', (function(_this) { return function(iip) { return _this.appendCommand('removeInitial', iip); }; })(this)); this.graph.on('changeProperties', (function(_this) { return function(newProps, oldProps) { return _this.appendCommand('changeProperties', { "new": newProps, old: oldProps }); }; })(this)); this.graph.on('addGroup', (function(_this) { return function(group) { return _this.appendCommand('addGroup', group); }; })(this)); this.graph.on('renameGroup', (function(_this) { return function(oldName, newName) { return _this.appendCommand('renameGroup', { oldName: oldName, newName: newName }); }; })(this)); this.graph.on('removeGroup', (function(_this) { return function(group) { return _this.appendCommand('removeGroup', group); }; })(this)); this.graph.on('changeGroup', (function(_this) { return function(group, oldMeta) { return _this.appendCommand('changeGroup', { name: group.name, "new": group.metadata, old: oldMeta }); }; })(this)); this.graph.on('addExport', (function(_this) { return function(exported) { return _this.appendCommand('addExport', exported); }; })(this)); this.graph.on('removeExport', (function(_this) { return function(exported) { return _this.appendCommand('removeExport', exported); }; })(this)); this.graph.on('addInport', (function(_this) { return function(name, port) { return _this.appendCommand('addInport', { name: name, port: port }); }; })(this)); this.graph.on('removeInport', (function(_this) { return function(name, port) { return _this.appendCommand('removeInport', { name: name, port: port }); }; })(this)); this.graph.on('renameInport', (function(_this) { return function(oldId, newId) { return _this.appendCommand('renameInport', { oldId: oldId, newId: newId }); }; })(this)); this.graph.on('changeInport', (function(_this) { return function(name, port, oldMeta) { return _this.appendCommand('changeInport', { name: name, "new": port.metadata, old: oldMeta }); }; })(this)); this.graph.on('addOutport', (function(_this) { return function(name, port) { return _this.appendCommand('addOutport', { name: name, port: port }); }; })(this)); this.graph.on('removeOutport', (function(_this) { return function(name, port) { return _this.appendCommand('removeOutport', { name: name, port: port }); }; })(this)); this.graph.on('renameOutport', (function(_this) { return function(oldId, newId) { return _this.appendCommand('renameOutport', { oldId: oldId, newId: newId }); }; })(this)); this.graph.on('changeOutport', (function(_this) { return function(name, port, oldMeta) { return _this.appendCommand('changeOutport', { name: name, "new": port.metadata, old: oldMeta }); }; })(this)); this.graph.on('startTransaction', (function(_this) { return function(id, meta) { return _this.startTransaction(id, meta); }; })(this)); this.graph.on('endTransaction', (function(_this) { return function(id, meta) { return _this.endTransaction(id, meta); }; })(this)); } Journal.prototype.startTransaction = function(id, meta) { if (!this.subscribed) { return; } if (this.entries.length > 0) { throw Error("Inconsistent @entries"); } this.currentRevision++; return this.appendCommand('startTransaction', { id: id, metadata: meta }, this.currentRevision); }; Journal.prototype.endTransaction = function(id, meta) { if (!this.subscribed) { return; } this.appendCommand('endTransaction', { id: id, metadata: meta }, this.currentRevision); this.store.putTransaction(this.currentRevision, this.entries); return this.entries = []; }; Journal.prototype.appendCommand = function(cmd, args, rev) { var entry; if (!this.subscribed) { return; } entry = { cmd: cmd, args: clone(args) }; if (rev != null) { entry.rev = rev; } return this.entries.push(entry); }; Journal.prototype.executeEntry = function(entry) { var a; a = entry.args; switch (entry.cmd) { case 'addNode': return this.graph.addNode(a.id, a.component); case 'removeNode': return this.graph.removeNode(a.id); case 'renameNode': return this.graph.renameNode(a.oldId, a.newId); case 'changeNode': return this.graph.setNodeMetadata(a.id, calculateMeta(a.old, a["new"])); case 'addEdge': return this.graph.addEdge(a.from.node, a.from.port, a.to.node, a.to.port); case 'removeEdge': return this.graph.removeEdge(a.from.node, a.from.port, a.to.node, a.to.port); case 'changeEdge': return this.graph.setEdgeMetadata(a.from.node, a.from.port, a.to.node, a.to.port, calculateMeta(a.old, a["new"])); case 'addInitial': return this.graph.addInitial(a.from.data, a.to.node, a.to.port); case 'removeInitial': return this.graph.removeInitial(a.to.node, a.to.port); case 'startTransaction': return null; case 'endTransaction': return null; case 'changeProperties': return this.graph.setProperties(a["new"]); case 'addGroup': return this.graph.addGroup(a.name, a.nodes, a.metadata); case 'renameGroup': return this.graph.renameGroup(a.oldName, a.newName); case 'removeGroup': return this.graph.removeGroup(a.name); case 'changeGroup': return this.graph.setGroupMetadata(a.name, calculateMeta(a.old, a["new"])); case 'addInport': return this.graph.addInport(a.name, a.port.process, a.port.port, a.port.metadata); case 'removeInport': return this.graph.removeInport(a.name); case 'renameInport': return this.graph.renameInport(a.oldId, a.newId); case 'changeInport': return this.graph.setInportMetadata(a.name, calculateMeta(a.old, a["new"])); case 'addOutport': return this.graph.addOutport(a.name, a.port.process, a.port.port, a.port.metadata(a.name)); case 'removeOutport': return this.graph.removeOutport; case 'renameOutport': return this.graph.renameOutport(a.oldId, a.newId); case 'changeOutport': return this.graph.setOutportMetadata(a.name, calculateMeta(a.old, a["new"])); default: throw new Error("Unknown journal entry: " + entry.cmd); } }; Journal.prototype.executeEntryInversed = function(entry) { var a; a = entry.args; switch (entry.cmd) { case 'addNode': return this.graph.removeNode(a.id); case 'removeNode': return this.graph.addNode(a.id, a.component); case 'renameNode': return this.graph.renameNode(a.newId, a.oldId); case 'changeNode': return this.graph.setNodeMetadata(a.id, calculateMeta(a["new"], a.old)); case 'addEdge': return this.graph.removeEdge(a.from.node, a.from.port, a.to.node, a.to.port); case 'removeEdge': return this.graph.addEdge(a.from.node, a.from.port, a.to.node, a.to.port); case 'changeEdge': return this.graph.setEdgeMetadata(a.from.node, a.from.port, a.to.node, a.to.port, calculateMeta(a["new"], a.old)); case 'addInitial': return this.graph.removeInitial(a.to.node, a.to.port); case 'removeInitial': return this.graph.addInitial(a.from.data, a.to.node, a.to.port); case 'startTransaction': return null; case 'endTransaction': return null; case 'changeProperties': return this.graph.setProperties(a.old); case 'addGroup': return this.graph.removeGroup(a.name); case 'renameGroup': return this.graph.renameGroup(a.newName, a.oldName); case 'removeGroup': return this.graph.addGroup(a.name, a.nodes, a.metadata); case 'changeGroup': return this.graph.setGroupMetadata(a.name, calculateMeta(a["new"], a.old)); case 'addInport': return this.graph.removeInport(a.name); case 'removeInport': return this.graph.addInport(a.name, a.port.process, a.port.port, a.port.metadata); case 'renameInport': return this.graph.renameInport(a.newId, a.oldId); case 'changeInport': return this.graph.setInportMetadata(a.name, calculateMeta(a["new"], a.old)); case 'addOutport': return this.graph.removeOutport(a.name); case 'removeOutport': return this.graph.addOutport(a.name, a.port.process, a.port.port, a.port.metadata); case 'renameOutport': return this.graph.renameOutport(a.newId, a.oldId); case 'changeOutport': return this.graph.setOutportMetadata(a.name, calculateMeta(a["new"], a.old)); default: throw new Error("Unknown journal entry: " + entry.cmd); } }; Journal.prototype.moveToRevision = function(revId) { var entries, entry, i, r, _i, _j, _k, _l, _len, _ref, _ref1, _ref2, _ref3, _ref4; if (revId === this.currentRevision) { return; } this.subscribed = false; if (revId > this.currentRevision) { for (r = _i = _ref = this.currentRevision + 1; _ref <= revId ? _i <= revId : _i >= revId; r = _ref <= revId ? ++_i : --_i) { _ref1 = this.store.fetchTransaction(r); for (_j = 0, _len = _ref1.length; _j < _len; _j++) { entry = _ref1[_j]; this.executeEntry(entry); } } } else { for (r = _k = _ref2 = this.currentRevision, _ref3 = revId + 1; _k >= _ref3; r = _k += -1) { entries = this.store.fetchTransaction(r); for (i = _l = _ref4 = entries.length - 1; _l >= 0; i = _l += -1) { this.executeEntryInversed(entries[i]); } } } this.currentRevision = revId; return this.subscribed = true; }; Journal.prototype.undo = function() { if (!this.canUndo()) { return; } return this.moveToRevision(this.currentRevision - 1); }; Journal.prototype.canUndo = function() { return this.currentRevision > 0; }; Journal.prototype.redo = function() { if (!this.canRedo()) { return; } return this.moveToRevision(this.currentRevision + 1); }; Journal.prototype.canRedo = function() { return this.currentRevision < this.store.lastRevision; }; Journal.prototype.toPrettyString = function(startRev, endRev) { var e, entry, lines, r, _i, _j, _len; startRev |= 0; endRev |= this.store.lastRevision; lines = []; for (r = _i = startRev; startRev <= endRev ? _i < endRev : _i > endRev; r = startRev <= endRev ? ++_i : --_i) { e = this.store.fetchTransaction(r); for (_j = 0, _len = e.length; _j < _len; _j++) { entry = e[_j]; lines.push(entryToPrettyString(entry)); } } return lines.join('\n'); }; Journal.prototype.toJSON = function(startRev, endRev) { var entries, entry, r, _i, _j, _len, _ref; startRev |= 0; endRev |= this.store.lastRevision; entries = []; for (r = _i = startRev; _i < endRev; r = _i += 1) { _ref = this.store.fetchTransaction(r); for (_j = 0, _len = _ref.length; _j < _len; _j++) { entry = _ref[_j]; entries.push(entryToPrettyString(entry)); } } return entries; }; Journal.prototype.save = function(file, success) { var json; json = JSON.stringify(this.toJSON(), null, 4); return require('fs').writeFile("" + file + ".json", json, "utf-8", function(err, data) { if (err) { throw err; } return success(file); }); }; return Journal; })(EventEmitter); exports.Journal = Journal; exports.JournalStore = JournalStore; exports.MemoryJournalStore = MemoryJournalStore; }).call(this);