2018-12-23 07:56:44 -06:00
|
|
|
const {createDebugAction} = require('./debug');
|
|
|
|
const {pack, unpack} = require('./packer');
|
|
|
|
|
|
|
|
const debug = require('debug')('truss:comm:dispatcher');
|
|
|
|
|
|
|
|
export class Dispatcher {
|
|
|
|
|
|
|
|
constructor(actions = (() => ({})), hooks = (() => ({}))) {
|
|
|
|
this.args = [];
|
|
|
|
this.lookup = {actions, hooks};
|
|
|
|
}
|
|
|
|
|
|
|
|
connect() {
|
|
|
|
|
|
|
|
const netServer = require('./socket.ipc').server();
|
|
|
|
|
|
|
|
netServer.on('connection', (socket) => {
|
|
|
|
socket.on('error', (error) => { this.handleError(error); });
|
|
|
|
|
|
|
|
socket.setEncoding('utf8');
|
|
|
|
socket.on('data', (chunk) => {
|
|
|
|
|
|
|
|
let action = undefined;
|
|
|
|
try { action = unpack(chunk); }
|
|
|
|
catch (error) { return this.handleError(error); }
|
|
|
|
|
|
|
|
const actions = this.createActions();
|
|
|
|
if (!(action.type in actions)) {
|
|
|
|
debug(`discarding ${JSON.stringify(action, null, ' ')}!`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const debugAction = createDebugAction(debug, action);
|
|
|
|
if (debugAction) {
|
|
|
|
debug(`dispatching ${JSON.stringify(debugAction, null, ' ')}`);
|
|
|
|
}
|
2018-12-24 13:21:03 -06:00
|
|
|
const actionPromise = actions[action.type](action);
|
|
|
|
Promise.resolve(actionPromise).then((result) => {
|
2018-12-23 07:56:44 -06:00
|
|
|
if ('undefined' === typeof result) {
|
|
|
|
debug(`undefined result from ${action.type} not forwarded!`);
|
|
|
|
}
|
2018-12-24 13:21:03 -06:00
|
|
|
else {
|
|
|
|
socket.write(pack(result));
|
|
|
|
}
|
2018-12-23 07:56:44 -06:00
|
|
|
socket.end();
|
|
|
|
}).catch((error) => { this.handleError(error); });
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
netServer.on('listening', () => {
|
|
|
|
debug(`dispatcher listening...`);
|
|
|
|
});
|
|
|
|
|
|
|
|
netServer.listen();
|
|
|
|
|
|
|
|
return netServer;
|
|
|
|
}
|
|
|
|
|
|
|
|
createActions() {
|
|
|
|
|
|
|
|
const actions = this.lookup.actions(...this.args);
|
|
|
|
const hooks = this.lookup.hooks(...this.args);
|
|
|
|
|
|
|
|
// builtin hook plumbing
|
|
|
|
actions['truss/hook'] = (action) => {
|
|
|
|
if (!(action.payload.hook in hooks)) { return undefined; }
|
|
|
|
return hooks[action.payload.hook](...action.payload.args);
|
|
|
|
}
|
|
|
|
|
|
|
|
// builtin schema
|
|
|
|
const originalSchema = actions['truss/schema'] || (() => ({}));
|
|
|
|
actions['truss/schema'] = (action) => {
|
|
|
|
return {...originalSchema(action), hooks: Object.keys(hooks)};
|
|
|
|
}
|
|
|
|
|
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
|
|
|
handleError(error) {
|
|
|
|
console.error(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
lookupActions(lookup) { this.lookup.actions = lookup; }
|
|
|
|
|
|
|
|
lookupHooks(lookup) { this.lookup.hooks = lookup; }
|
|
|
|
|
|
|
|
setArgs(...args) { this.args = args; }
|
|
|
|
}
|