2022-06-13 14:35:11 +03:00
|
|
|
import express from 'express';
|
|
|
|
import http from 'http';
|
2023-01-06 04:12:28 +03:00
|
|
|
import getPort from 'get-port';
|
2022-06-13 14:35:11 +03:00
|
|
|
import socketClusterServer from 'socketcluster-server';
|
2023-01-06 04:12:28 +03:00
|
|
|
import getOptions from './options';
|
2022-06-13 14:35:11 +03:00
|
|
|
import routes from './routes';
|
|
|
|
import createStore from './store';
|
2019-01-04 01:30:48 +03:00
|
|
|
|
2023-01-06 04:12:28 +03:00
|
|
|
// const LOG_LEVEL_NONE = 0;
|
|
|
|
// const LOG_LEVEL_ERROR = 1;
|
2020-10-26 08:57:34 +03:00
|
|
|
const LOG_LEVEL_WARN = 2;
|
|
|
|
const LOG_LEVEL_INFO = 3;
|
2019-01-04 01:30:48 +03:00
|
|
|
|
2023-01-06 04:12:28 +03:00
|
|
|
export default async function (argv: { [arg: string]: any }): Promise<{
|
2020-10-26 08:57:34 +03:00
|
|
|
portAlreadyUsed?: boolean;
|
2022-06-13 14:35:11 +03:00
|
|
|
listener: (eventName: 'ready') => { once(): Promise<void> };
|
2020-10-26 08:57:34 +03:00
|
|
|
}> {
|
|
|
|
const options = Object.assign(getOptions(argv), {
|
2020-08-08 23:26:39 +03:00
|
|
|
allowClientPublish: false,
|
2019-01-04 01:30:48 +03:00
|
|
|
});
|
2020-10-26 08:57:34 +03:00
|
|
|
const port = options.port;
|
|
|
|
const logLevel =
|
2019-01-10 21:51:14 +03:00
|
|
|
options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel;
|
2023-01-06 04:12:28 +03:00
|
|
|
// Check port already used
|
|
|
|
const p = await getPort({ port });
|
|
|
|
if (port !== p) {
|
|
|
|
if (logLevel >= LOG_LEVEL_WARN) {
|
|
|
|
console.log(`[ReduxDevTools] Server port ${port} is already used.`);
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
portAlreadyUsed: true,
|
|
|
|
listener: function () {
|
|
|
|
return {
|
|
|
|
once() {
|
|
|
|
return Promise.resolve();
|
2020-08-08 23:26:39 +03:00
|
|
|
},
|
2023-01-06 04:12:28 +03:00
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
2022-06-13 14:35:11 +03:00
|
|
|
|
2023-01-06 04:12:28 +03:00
|
|
|
if (logLevel >= LOG_LEVEL_INFO) {
|
|
|
|
console.log('[ReduxDevTools] Start server...');
|
|
|
|
console.log('-'.repeat(80) + '\n');
|
|
|
|
}
|
|
|
|
const httpServer = http.createServer();
|
|
|
|
const agServer = socketClusterServer.attach(httpServer, options);
|
2022-06-13 14:35:11 +03:00
|
|
|
|
2023-01-06 04:12:28 +03:00
|
|
|
const app = express();
|
|
|
|
httpServer.on('request', app);
|
|
|
|
const store = createStore(options);
|
|
|
|
app.use(routes(options, store, agServer));
|
2022-06-13 14:35:11 +03:00
|
|
|
|
2023-01-06 04:12:28 +03:00
|
|
|
agServer.setMiddleware(
|
|
|
|
agServer.MIDDLEWARE_INBOUND,
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
|
|
async (middlewareStream) => {
|
|
|
|
for await (const action of middlewareStream) {
|
|
|
|
if (action.type === action.TRANSMIT) {
|
|
|
|
const channel = action.receiver;
|
|
|
|
const data = action.data;
|
|
|
|
if (
|
|
|
|
channel.substring(0, 3) === 'sc-' ||
|
|
|
|
channel === 'respond' ||
|
|
|
|
channel === 'log'
|
|
|
|
) {
|
|
|
|
void agServer.exchange.transmitPublish(channel, data);
|
|
|
|
} else if (channel === 'log-noid') {
|
|
|
|
void agServer.exchange.transmitPublish('log', {
|
|
|
|
id: action.socket.id,
|
|
|
|
data: data,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else if (action.type === action.SUBSCRIBE) {
|
|
|
|
if (action.channel === 'report') {
|
|
|
|
store
|
|
|
|
.list()
|
|
|
|
.then(function (data) {
|
|
|
|
void agServer.exchange.transmitPublish('report', {
|
|
|
|
type: 'list',
|
|
|
|
data: data,
|
2022-06-13 14:35:11 +03:00
|
|
|
});
|
2023-01-06 04:12:28 +03:00
|
|
|
})
|
|
|
|
.catch(function (error) {
|
|
|
|
console.error(error); // eslint-disable-line no-console
|
|
|
|
});
|
2022-06-13 14:35:11 +03:00
|
|
|
}
|
2023-01-06 04:12:28 +03:00
|
|
|
}
|
|
|
|
action.allow();
|
2019-01-04 01:30:48 +03:00
|
|
|
}
|
2023-01-06 04:12:28 +03:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
void (async () => {
|
|
|
|
for await (const { socket } of agServer.listener('connection')) {
|
|
|
|
let channelToWatch: string, channelToEmit: string;
|
|
|
|
void (async () => {
|
|
|
|
for await (const request of socket.procedure('login')) {
|
|
|
|
const credentials = request.data;
|
|
|
|
if (credentials === 'master') {
|
|
|
|
channelToWatch = 'respond';
|
|
|
|
channelToEmit = 'log';
|
|
|
|
} else {
|
|
|
|
channelToWatch = 'log';
|
|
|
|
channelToEmit = 'respond';
|
|
|
|
}
|
|
|
|
request.end(channelToWatch);
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
void (async () => {
|
|
|
|
for await (const request of socket.procedure('getReport')) {
|
|
|
|
const id = request.data as string;
|
|
|
|
store
|
|
|
|
.get(id)
|
|
|
|
.then(function (data) {
|
|
|
|
request.end(data);
|
|
|
|
})
|
|
|
|
.catch(function (error) {
|
|
|
|
console.error(error); // eslint-disable-line no-console
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
void (async () => {
|
|
|
|
for await (const data of socket.listener('disconnect')) {
|
|
|
|
const channel = agServer.exchange.channel('sc-' + socket.id);
|
|
|
|
channel.unsubscribe();
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
|
|
void agServer.exchange.transmitPublish(channelToEmit!, {
|
|
|
|
id: socket.id,
|
|
|
|
type: 'DISCONNECTED',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
|
|
|
httpServer.listen(options.port);
|
|
|
|
// @ts-expect-error Shouldn't there be a 'ready' event?
|
|
|
|
return agServer;
|
2020-10-26 08:57:34 +03:00
|
|
|
}
|