@data-fair/dev-server 2.0.20 → 2.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-fair/dev-server",
3
- "version": "2.0.20",
3
+ "version": "2.0.22",
4
4
  "description": "A development server for optimal development experience of data-fair applications.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/app.js CHANGED
@@ -21,37 +21,60 @@ const server = createServer(app);
21
21
  // web socket server, used both by dev-server UI (opened on / path)
22
22
  // and by application (opened on /data-fair), in this case we transmit all messages to and from data-fair
23
23
  const wss = new WebSocketServer({ noServer: true });
24
- let devServerWS;
25
- let dataFairWS;
24
+ let devServerWS = [];
25
+ let dataFairWS = [];
26
+ const dataFairWSChannels = new Map();
27
+ const dfWsUrl = config.dataFair.url.replace('http://', 'ws://').replace('https://', 'wss://') + '/';
28
+ const dataFairOutputWS = new WebSocket(dfWsUrl);
29
+ dataFairOutputWS.on('open', () => {
30
+ debug('connect to external websocket server ' + dfWsUrl);
31
+ });
32
+ dataFairOutputWS.on('message', (data) => {
33
+ const dataStr = data.toString();
34
+ const message = JSON.parse(dataStr);
35
+ debug('incoming message from data-fair socket', message);
36
+ for (const ws of dataFairWS) {
37
+ if (dataFairWSChannels.get(ws)?.includes(message.channel)) {
38
+ ws.send(dataStr);
39
+ }
40
+ }
41
+ });
42
+ dataFairOutputWS.on('error', (err) => console.error('failed to connect to external websocket server', dfWsUrl, err));
43
+ dataFairOutputWS.on('close', () => console.error('external websocket was closed', dfWsUrl));
26
44
  server.on('upgrade', function upgrade(req, socket, head) {
27
45
  wss.handleUpgrade(req, socket, head, (ws) => {
46
+ debug('Opening websocket ' + req.url);
28
47
  if (req.url === '/data-fair' || req.url === '/data-fair/') {
29
- if (dataFairWS)
30
- dataFairWS.terminate();
31
- dataFairWS = ws;
48
+ dataFairWS.push(ws);
49
+ ws.on('close', () => { dataFairWS = dataFairWS.filter(_ws => _ws !== ws); });
32
50
  ws.on('message', (data) => {
33
51
  if (dataFairOutputWS) {
34
52
  const message = JSON.parse(data);
35
- if (message.type === 'subscribe' && config.dataFair.apiKey)
36
- message.apiKey = config.dataFair.apiKey;
53
+ debug('outgoing message to data-fair socket', message);
54
+ if (message.type === 'subscribe') {
55
+ dataFairWSChannels.set(ws, (dataFairWSChannels.get(ws) ?? []).concat([message.channel]));
56
+ if (config.dataFair.apiKey)
57
+ message.apiKey = config.dataFair.apiKey;
58
+ }
59
+ if (message.type === 'unsubscribe') {
60
+ dataFairWSChannels.set(ws, (dataFairWSChannels.get(ws) ?? []).filter(c => c !== message.channel));
61
+ }
37
62
  dataFairOutputWS.send(JSON.stringify(message));
38
63
  }
39
64
  });
40
65
  }
66
+ else if (req.url === '/') {
67
+ debug('connect main dev-server WS');
68
+ devServerWS.push(ws);
69
+ ws.on('close', () => { devServerWS = devServerWS.filter(_ws => _ws !== ws); });
70
+ }
41
71
  else {
42
- if (devServerWS)
43
- devServerWS.terminate();
44
- devServerWS = ws;
72
+ console.warn('ignore WebSocket to path not managed by dev-server', req.url);
45
73
  }
46
74
  wss.emit('connection', ws, req);
75
+ ws.on('error', () => ws.terminate());
47
76
  });
48
77
  });
49
- const dfWsUrl = config.dataFair.url.replace('http://', 'ws://').replace('https://', 'wss://') + '/';
50
- const dataFairOutputWS = new WebSocket(dfWsUrl);
51
- dataFairOutputWS.on('open', () => dataFairOutputWS.send('connect to external websocket server ' + dfWsUrl));
52
- dataFairOutputWS.on('message', (data) => { if (dataFairWS)
53
- dataFairWS.send(data.toString()); });
54
- dataFairOutputWS.on('error', (err) => console.error('failed to connect to external websocket server', dfWsUrl, err));
55
78
  app.use(cors());
56
79
  app.use(express.json());
57
80
  // very basic CRUD of config
@@ -67,10 +90,9 @@ app.put('/config', (req, res, next) => {
67
90
  });
68
91
  app.post('/config/error', (req, res) => {
69
92
  console.log('Application sent an error', req.body);
70
- if (devServerWS)
71
- devServerWS.send(JSON.stringify({ type: 'app-error', data: req.body }));
72
- else
73
- console.error('no dev-server websocket open to send error to');
93
+ for (const ws of devServerWS) {
94
+ ws.send(JSON.stringify({ type: 'app-error', data: req.body }));
95
+ }
74
96
  res.send();
75
97
  });
76
98
  // re-expose the application performing similar modifications to the body as data-fair
@@ -263,11 +285,10 @@ export const run = async () => {
263
285
  return server;
264
286
  };
265
287
  export const stop = async () => {
266
- if (devServerWS)
267
- devServerWS.terminate();
268
- if (dataFairWS)
269
- dataFairWS.terminate();
288
+ for (const ws of dataFairWS)
289
+ ws.terminate();
290
+ for (const ws of devServerWS)
291
+ ws.terminate();
270
292
  server.close();
271
293
  await eventPromise(server, 'close');
272
- await app.get('client').close();
273
294
  };