Skip to content

Commit 8ac5a97

Browse files
factorize code
1 parent e70ecac commit 8ac5a97

File tree

5 files changed

+113
-101
lines changed

5 files changed

+113
-101
lines changed

CONTRIBUTING.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ $ git commit
5454
The commit message should describe what changed and why.
5555

5656
1. The first line should:
57-
5857
- contain a short description of the change
5958
- be 50 characters or less
6059
- be entirely in lowercase with the exception of proper nouns, acronyms, and

lib/nelsonCloud.spec.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,28 @@ describe('child_on', () => {
4646
['available', undefined, { msgtype: 'available' }],
4747
['unavailable', undefined, { msgtype: 'unavailable' }],
4848
['disconnect', undefined, { msgtype: 'quit' }],
49-
])('forwards %s events to the child process', (eventName, payload, expected) => {
50-
const { socket, child } = createHarness();
51-
if (payload === undefined) {
52-
socket.emit(eventName);
53-
} else {
54-
socket.emit(eventName, payload);
55-
}
56-
expect(child.send).toHaveBeenCalledTimes(1);
57-
expect(child.send).toHaveBeenCalledWith(expected);
58-
});
49+
])(
50+
'forwards %s events to the child process',
51+
(eventName, payload, expected) => {
52+
const { socket, child } = createHarness();
53+
if (payload === undefined) {
54+
socket.emit(eventName);
55+
} else {
56+
socket.emit(eventName, payload);
57+
}
58+
expect(child.send).toHaveBeenCalledTimes(1);
59+
expect(child.send).toHaveBeenCalledWith(expected);
60+
},
61+
);
5962

6063
it('emits reply events through io with inferred sender name when missing', () => {
6164
const { socket, ios } = createHarness({ name: 'session-1' });
6265
const payload = { text: 'Hello' };
6366
socket.emit('reply', payload);
64-
expect(ios.emit).toHaveBeenCalledWith('reply', { text: 'Hello', from: 'session-1' });
67+
expect(ios.emit).toHaveBeenCalledWith('reply', {
68+
text: 'Hello',
69+
from: 'session-1',
70+
});
6571
expect(payload).toEqual({ text: 'Hello' });
6672
});
6773

@@ -96,7 +102,10 @@ describe('child_emit', () => {
96102
[{ msgtype: 'available' }, (msg) => ['available']],
97103
[{ msgtype: 'unavailable' }, (msg) => ['unavailable']],
98104
[{ msgtype: 'quit' }, (msg) => ['quit']],
99-
[{ msgtype: 'custom', output: 'value' }, (msg) => [msg.msgtype, msg.output]],
105+
[
106+
{ msgtype: 'custom', output: 'value' },
107+
(msg) => [msg.msgtype, msg.output],
108+
],
100109
])('emits %p through the provided socket', (message, expectedFactory) => {
101110
const socket = { emit: jest.fn() };
102111
child_emit(socket, message);

lib/nelsonProcess.js

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,40 +70,11 @@ function startNelsonProcess() {
7070
process.once('exit', () => cleanup());
7171
// Listen for messages from the parent process
7272
process.on('message', (msg) => {
73-
switch (msg.msgtype) {
74-
case 'initialization':
75-
// Initialize socket and start Nelson application
76-
handleInitialization(msg.id);
77-
break;
78-
case 'command':
79-
// Forward command to Nelson application
80-
commandio?.emit('command', { data: msg.data });
81-
break;
82-
case 'prompt':
83-
// Handle user prompt
84-
console.log(`emit prompt ${msg.data}`);
85-
commandio?.emit('prompt', msg.data);
86-
break;
87-
case 'clc':
88-
// Clear console
89-
commandio?.emit('clc');
90-
break;
91-
case 'available':
92-
// Set application as available
93-
commandio?.emit('available');
94-
break;
95-
case 'stop':
96-
// Stop the application
97-
commandio?.emit('stop');
98-
cleanup(true);
99-
break;
100-
case 'quit':
101-
// Terminate Nelson application
102-
cleanup(true);
103-
break;
104-
default:
105-
// Log unknown message types
106-
console.warn(`Unknown message: ${msg.msgtype}`);
73+
const handler = messageHandlers[msg.msgtype];
74+
if (handler) {
75+
handler(msg);
76+
} else {
77+
console.warn(`Unknown message: ${msg.msgtype}`);
10778
}
10879
});
10980
//=============================================================================
@@ -189,8 +160,12 @@ function startNelsonProcess() {
189160
.flat()
190161
.filter(Boolean);
191162
const candidate =
192-
interfaces.find((details) => details.family === 'IPv4' && !details.internal) ??
193-
interfaces.find((details) => details.family === 'IPv6' && !details.internal) ??
163+
interfaces.find(
164+
(details) => details.family === 'IPv4' && !details.internal,
165+
) ??
166+
interfaces.find(
167+
(details) => details.family === 'IPv6' && !details.internal,
168+
) ??
194169
interfaces.find((details) => details.family === 'IPv4') ??
195170
interfaces.find((details) => details.family === 'IPv6');
196171

@@ -210,6 +185,30 @@ function startNelsonProcess() {
210185
return { address, family: candidate.family };
211186
}
212187
//=============================================================================
188+
function emitToCommandIO(event, payload) {
189+
if (!commandio) {
190+
return;
191+
}
192+
payload === undefined
193+
? commandio.emit(event)
194+
: commandio.emit(event, payload);
195+
}
196+
197+
const messageHandlers = {
198+
initialization: (msg) => handleInitialization(msg.id),
199+
command: (msg) => emitToCommandIO('command', { data: msg.data }),
200+
prompt: (msg) => {
201+
console.log(`emit prompt ${msg.data}`);
202+
emitToCommandIO('prompt', msg.data);
203+
},
204+
clc: () => emitToCommandIO('clc'),
205+
available: () => emitToCommandIO('available'),
206+
stop: () => {
207+
emitToCommandIO('stop');
208+
cleanup(true);
209+
},
210+
quit: () => cleanup(true),
211+
};
213212
}
214213
//=============================================================================
215214
/**

lib/nelsonSocketIO.js

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ const childProcess = require('child_process');
2828
const findFreePort = require('find-free-port');
2929
const limiter = require('./rate-limiter.js');
3030
//=============================================================================
31+
const SOCKET_TO_CHILD_FORWARDERS = {
32+
command: (data) => ({ msgtype: 'command', data }),
33+
clc: () => ({ msgtype: 'clc' }),
34+
stop: () => ({ msgtype: 'stop' }),
35+
available: () => ({ msgtype: 'available' }),
36+
unavailable: () => ({ msgtype: 'unavailable' }),
37+
disconnect: () => ({ msgtype: 'quit' }),
38+
};
39+
//=============================================================================
40+
const CHILD_TO_SOCKET_FORWARDERS = {
41+
command_received: (socket) => socket.emit('command_received'),
42+
prompt: (socket, msg) => socket.emit('prompt', msg.output),
43+
reply: (socket, msg) => socket.emit('reply', msg),
44+
clc: (socket) => socket.emit('clc'),
45+
stop: (socket) => socket.emit('stop'),
46+
available: (socket) => socket.emit('available'),
47+
unavailable: (socket) => socket.emit('unavailable'),
48+
quit: (socket) => socket.emit('quit'),
49+
};
50+
//=============================================================================
3151
const app = express();
3252
const resourcesDir = path.join(__dirname, '..', 'resources');
3353
const nelsonProcessPath = path.join(__dirname, 'nelsonProcess.js');
@@ -62,7 +82,9 @@ function nelsonSocketIO() {
6282
(err, freePort) => {
6383
if (err) {
6484
console.error('Unable to find free Nelson port:', err.message);
65-
socket.emit('error', { message: 'Unable to initialise Nelson session.' });
85+
socket.emit('error', {
86+
message: 'Unable to initialise Nelson session.',
87+
});
6688
child.kill();
6789
return;
6890
}
@@ -78,29 +100,16 @@ function nelsonSocketIO() {
78100
}
79101
//=============================================================================
80102
function child_on(socket, child, ios) {
81-
socket.on('command', (data) => {
82-
child.send({ msgtype: 'command', data });
83-
});
84-
85-
socket.on('clc', () => {
86-
child.send({ msgtype: 'clc' });
87-
});
88-
89-
socket.on('stop', () => {
90-
child.send({ msgtype: 'stop' });
91-
});
92-
93-
socket.on('available', () => {
94-
child.send({ msgtype: 'available' });
95-
});
96-
97-
socket.on('unavailable', () => {
98-
child.send({ msgtype: 'unavailable' });
99-
});
100-
101-
socket.on('disconnect', () => {
102-
child.send({ msgtype: 'quit' });
103-
});
103+
Object.entries(SOCKET_TO_CHILD_FORWARDERS).forEach(
104+
([event, buildMessage]) => {
105+
socket.on(event, (data) => {
106+
const payload = buildMessage(data);
107+
if (payload) {
108+
child.send(payload);
109+
}
110+
});
111+
},
112+
);
104113

105114
socket.on('reply', (data = {}) => {
106115
const payload = { ...data };
@@ -120,35 +129,12 @@ function child_on(socket, child, ios) {
120129
}
121130
//=============================================================================
122131
function child_emit(socket, msg) {
123-
switch (msg.msgtype) {
124-
case 'command_received':
125-
socket.emit('command_received');
126-
break;
127-
case 'prompt':
128-
socket.emit('prompt', msg.output);
129-
break;
130-
case 'reply':
131-
socket.emit(msg.msgtype, msg);
132-
break;
133-
case 'clc':
134-
socket.emit('clc');
135-
break;
136-
case 'stop':
137-
socket.emit('stop');
138-
break;
139-
case 'available':
140-
socket.emit('available');
141-
break;
142-
case 'unavailable':
143-
socket.emit('unavailable');
144-
break;
145-
case 'quit':
146-
socket.emit('quit');
147-
break;
148-
default:
149-
socket.emit(msg.msgtype, msg.output);
150-
break;
132+
const forwarder = CHILD_TO_SOCKET_FORWARDERS[msg.msgtype];
133+
if (forwarder) {
134+
forwarder(socket, msg);
135+
return;
151136
}
137+
socket.emit(msg.msgtype, msg.output);
152138
}
153139
//=============================================================================
154140
module.exports = { nelsonSocketIO, __test__: { child_on, child_emit } };

nelson-cloud.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11
#!/usr/bin/env node
2+
//=============================================================================
3+
// Copyright (c) 2016-present Allan CORNET (Nelson)
4+
//=============================================================================
5+
// LICENCE_BLOCK_BEGIN
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU General Public License as published by
8+
// the Free Software Foundation, either version 2 of the License, or
9+
// (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU General Public License
17+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
// LICENCE_BLOCK_END
19+
//=============================================================================
220
'use strict';
321
const { nelsonSocketIO } = require('./lib/nelsonSocketIO');
422
nelsonSocketIO();
23+
//=============================================================================

0 commit comments

Comments
 (0)