diff --git a/packages/redux-devtools-cli/package.json b/packages/redux-devtools-cli/package.json index 7c4f665c..4fda9427 100644 --- a/packages/redux-devtools-cli/package.json +++ b/packages/redux-devtools-cli/package.json @@ -49,7 +49,7 @@ "cross-spawn": "^7.0.3", "electron": "^22.0.0", "express": "^4.18.2", - "getport": "^0.1.0", + "get-port": "^5.1.1", "graphql": "^16.6.0", "knex": "^2.3.0", "lodash": "^4.17.21", diff --git a/packages/redux-devtools-cli/src/getport.ts b/packages/redux-devtools-cli/src/getport.ts deleted file mode 100644 index dc6dc87f..00000000 --- a/packages/redux-devtools-cli/src/getport.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'getport' { - export default function getport( - start: number, - callback: (e: Error | undefined, port: number) => void - ): void; -} diff --git a/packages/redux-devtools-cli/src/index.ts b/packages/redux-devtools-cli/src/index.ts index 24b8104e..ddf6c84d 100644 --- a/packages/redux-devtools-cli/src/index.ts +++ b/packages/redux-devtools-cli/src/index.ts @@ -1,21 +1,17 @@ import express from 'express'; import http from 'http'; -import getPort from 'getport'; +import getPort from 'get-port'; import socketClusterServer from 'socketcluster-server'; -import getOptions, { Options } from './options'; +import getOptions from './options'; import routes from './routes'; import createStore from './store'; -// var LOG_LEVEL_NONE = 0; -const LOG_LEVEL_ERROR = 1; +// const LOG_LEVEL_NONE = 0; +// const LOG_LEVEL_ERROR = 1; const LOG_LEVEL_WARN = 2; const LOG_LEVEL_INFO = 3; -export interface ExtendedOptions extends Options { - allowClientPublish: boolean; -} - -export default function (argv: { [arg: string]: any }): Promise<{ +export default async function (argv: { [arg: string]: any }): Promise<{ portAlreadyUsed?: boolean; listener: (eventName: 'ready') => { once(): Promise }; }> { @@ -25,131 +21,120 @@ export default function (argv: { [arg: string]: any }): Promise<{ const port = options.port; const logLevel = options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel; - return new Promise(function (resolve) { - // Check port already used - getPort(port, function (err, p) { - /* eslint-disable no-console */ - if (err) { - if (logLevel >= LOG_LEVEL_ERROR) { - console.error(err); - } - return; - } - if (port !== p) { - if (logLevel >= LOG_LEVEL_WARN) { - console.log(`[ReduxDevTools] Server port ${port} is already used.`); - } - resolve({ - portAlreadyUsed: true, - listener: function (eventName: 'ready') { - return { - once() { - return Promise.resolve(); - }, - }; + // 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(); }, - }); - } else { - 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); + }; + }, + }; + } - const app = express(); - httpServer.on('request', app); - const store = createStore(options); - app.use(routes(options, store, agServer)); + 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); - 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, - }); - }) - .catch(function (error) { - console.error(error); // eslint-disable-line no-console - }); - } - } - action.allow(); - } + const app = express(); + httpServer.on('request', app); + const store = createStore(options); + app.use(routes(options, store, agServer)); + + 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, + }); } - ); - - 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', + } else if (action.type === action.SUBSCRIBE) { + if (action.channel === 'report') { + store + .list() + .then(function (data) { + void agServer.exchange.transmitPublish('report', { + type: 'list', + data: data, }); - } - })(); + }) + .catch(function (error) { + console.error(error); // eslint-disable-line no-console + }); } - })(); - - httpServer.listen(options.port); - // @ts-expect-error Shouldn't there be a 'ready' event? - resolve(agServer); + } + action.allow(); } - /* eslint-enable no-console */ - }); - }); + } + ); + + 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; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index badc82c1..832952a7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -951,7 +951,7 @@ importers: eslint-config-prettier: ^8.5.0 eslint-plugin-jest: ^27.1.7 express: ^4.18.2 - getport: ^0.1.0 + get-port: ^5.1.1 graphql: ^16.6.0 jest: ^29.3.1 knex: ^2.3.0 @@ -983,7 +983,7 @@ importers: cross-spawn: 7.0.3 electron: 22.0.0 express: 4.18.2 - getport: 0.1.0 + get-port: 5.1.1 graphql: 16.6.0 knex: 2.3.0_sqlite3@5.1.4 lodash: 4.17.21 @@ -13892,6 +13892,11 @@ packages: resolution: {integrity: sha512-41eOxtlGgHQRbFyA8KTH+w+32Em3cRdfBud7j67ulzmIfmaHX9doq47s0fa4P5o9H64BZX9nrYI6sJvk46Op+Q==} dev: false + /get-port/5.1.1: + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} + dev: false + /get-stdin/4.0.1: resolution: {integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==} engines: {node: '>=0.10.0'} @@ -13932,10 +13937,6 @@ packages: resolution: {integrity: sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==} dev: false - /getport/0.1.0: - resolution: {integrity: sha512-hx+r6Q5IutZH+5k+zeZe78J4vzgW9IqLzfz8+hqMa9NrM1ccpgPIxrxqiBg+aioJMKcCK5qNKKcGdes3PeTlKQ==} - dev: false - /github-slugger/1.5.0: resolution: {integrity: sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==} dev: true