diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..3c4ba9b --- /dev/null +++ b/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": [ + "eslint-config-egg/typescript", + "eslint-config-egg/lib/rules/enforce-node-prefix" + ], + "rules": { + "@typescript-eslint/ban-ts-comment": "off" + } +} \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index ed9eafd..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -module.exports = { - extends: 'eslint-config-egg', - parserOptions: { - ecmaVersion: 2020, - }, -}; diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 22a8662..c4ab048 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -15,4 +15,4 @@ jobs: uses: artusjs/github-actions/.github/workflows/node-test.yml@v1 with: os: 'ubuntu-latest' - version: '14, 16, 18' + version: '16, 18, 20' diff --git a/.gitignore b/.gitignore index 8dfbbd1..c0a0f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules coverage *.un~ *.sw* +.tshy* +dist/ \ No newline at end of file diff --git a/bin/detect-port.js b/bin/detect-port.ts similarity index 91% rename from bin/detect-port.js rename to bin/detect-port.ts index 84da022..d035ec1 100644 --- a/bin/detect-port.js +++ b/bin/detect-port.ts @@ -1,14 +1,14 @@ #!/usr/bin/env node -'use strict'; - -const pkg = require('../package'); +import pkg from '../package.json'; +import detectPort from '../src/detect-port.js'; const args = process.argv.slice(2); let arg_0 = args[0]; if (arg_0 && [ '-v', '--version' ].includes(arg_0.toLowerCase())) { console.log(pkg.version); + process.exit(0); } @@ -21,18 +21,15 @@ const removeByValue = (arr, val) => { } }; -const main = require('..'); - const port = parseInt(arg_0, 10); const isVerbose = args.includes('--verbose'); removeByValue(args, '--verbose'); arg_0 = args[0]; - if (!arg_0) { const random = Math.floor(9000 + Math.random() * (65535 - 9000)); - main(random, (err, port) => { + detectPort(random, (err, port) => { if (isVerbose) { if (err) { console.log(`get available port failed with ${err}`); @@ -61,7 +58,7 @@ if (!arg_0) { console.log(` ${pkg.homepage}`); console.log(); } else { - main(port, (err, _port) => { + detectPort(port, (err, _port) => { if (isVerbose) { if (err) { console.log(`get available port failed with ${err}`); diff --git a/index.js b/index.js deleted file mode 100644 index 2dc88ab..0000000 --- a/index.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; - -module.exports = require('./lib/detect-port'); -module.exports.waitPort = require('./lib/wait-port'); diff --git a/lib/wait-port.js b/lib/wait-port.js deleted file mode 100644 index 2322aae..0000000 --- a/lib/wait-port.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const debug = require('debug')('wait-port'); -const detect = require('./detect-port'); - -const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); - -async function waitPort(port, options = {}) { - const { retryInterval = 1000, retries = Infinity } = options; - let count = 1; - - async function loop() { - debug('retries', retries, 'count', count); - if (count > retries) { - const err = new Error('retries exceeded'); - err.retries = retries; - err.count = count; - throw err; - } - count++; - const freePort = await detect(port); - if (freePort === port) { - await sleep(retryInterval); - return loop(); - } - return true; - } - - return await loop(); -} - -module.exports = waitPort; diff --git a/package.json b/package.json index 2104d7e..a3f6024 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "detect": "./bin/detect-port.js", "detect-port": "./bin/detect-port.js" }, - "main": "index.js", + "main": "./dist/commonjs/index.js", "files": [ "bin", "lib", @@ -21,28 +21,54 @@ "url": "git://github.com/node-modules/detect-port.git" }, "dependencies": { - "address": "^1.0.1", - "debug": "4" + "address": "^2.0.1" }, "devDependencies": { - "command-line-test": "1", - "egg-bin": "^5.2.0", - "eslint": "^8.23.1", - "eslint-config-egg": "^12.0.0", - "git-contributor": "1", - "mm": "^2.1.0", - "pedding": "^1.1.0", - "power-assert": "^1.6.1" + "@eggjs/tsconfig": "^1.3.3", + "@types/node": "^20.9.0", + "c8": "^8.0.1", + "eslint": "^8.52.0", + "eslint-config-egg": "^13.0.0", + "execa": "^8.0.1", + "git-contributor": "^2.1.5", + "strip-ansi": "^7.1.0", + "ts-node": "^10.9.1", + "tshy": "^1.8.0", + "tshy-after": "^1.0.0", + "tsx": "^4.1.2", + "typescript": "^5.2.2" }, "scripts": { - "test": "egg-bin test", - "ci": "npm run lint && egg-bin cov", - "lint": "eslint .", - "contributor": "git-contributor" + "test": "npm run lint -- --fix && tsx --test test/*.test.ts", + "lint": "eslint src test --ext ts", + "ci": "npm run lint && npm run cov && npm run prepublishOnly", + "contributor": "git-contributor", + "prepublishOnly": "npm run tsc && tshy && tshy-after", + "tsc": "tsc ./bin/detect-port.ts --resolveJsonModule --esModuleInterop", + "cov": "c8 npm test" }, "engines": { "node": ">= 4.0.0" }, "homepage": "https://github.com/node-modules/detect-port", - "license": "MIT" + "license": "MIT", + "tshy": { + "exports": { + ".": "./src/index.ts" + } + }, + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" + } + } + }, + "types": "./dist/commonjs/index.d.ts", + "type": "module" } diff --git a/lib/detect-port.js b/src/detect-port.ts similarity index 57% rename from lib/detect-port.js rename to src/detect-port.ts index c94ceb0..981d603 100644 --- a/lib/detect-port.js +++ b/src/detect-port.ts @@ -1,24 +1,35 @@ -'use strict'; +import net from 'node:net'; +import { ip } from 'address'; +import { debuglog } from 'node:util'; -const net = require('net'); -const address = require('address'); -const debug = require('debug')('detect-port'); +const debug = debuglog('detect-port'); -module.exports = (port, callback) => { - let hostname = ''; +type DetectPortCallback = (err: Error | null, port: number) => void; - if (typeof port === 'object' && port) { +interface PortConfig { + port?: number | string; + hostname?: string | undefined; + callback?: DetectPortCallback; +} + +export default function detectPort(port?: number | PortConfig | string): Promise; +export default function detectPort(callback: DetectPortCallback): void; +export default function detectPort(port: number | PortConfig | string | undefined, callback: DetectPortCallback): void; +export default function detectPort(port?: number | string | PortConfig | DetectPortCallback, callback?: DetectPortCallback) { + let hostname: string | undefined = ''; + + if (port && typeof port === 'object') { hostname = port.hostname; callback = port.callback; port = port.port; } else { if (typeof port === 'function') { callback = port; - port = null; + port = void 0; } } - port = parseInt(port) || 0; + port = parseInt(port as unknown as string) || 0; let maxPort = port + 10; if (maxPort > 65535) { maxPort = 65535; @@ -29,13 +40,13 @@ module.exports = (port, callback) => { } // promise return new Promise(resolve => { - tryListen(port, maxPort, hostname, (_, realPort) => { + tryListen(port as number, maxPort, hostname, (_, realPort) => { resolve(realPort); }); }); -}; +} -function tryListen(port, maxPort, hostname, callback) { +function tryListen(port: number, maxPort: number, hostname: string | undefined, callback: (...args: any[]) => void) { function handleError() { port++; if (port >= maxPort) { @@ -50,7 +61,7 @@ function tryListen(port, maxPort, hostname, callback) { if (hostname) { listen(port, hostname, (err, realPort) => { if (err) { - if (err.code === 'EADDRNOTAVAIL') { + if ((err as any).code === 'EADDRNOTAVAIL') { return callback(new Error('the ip that is not unknown on the machine')); } return handleError(); @@ -60,34 +71,34 @@ function tryListen(port, maxPort, hostname, callback) { }); } else { // 1. check null - listen(port, null, (err, realPort) => { + listen(port, void 0, (err, realPort) => { // ignore random listening if (port === 0) { return callback(err, realPort); } if (err) { - return handleError(err); + return handleError(); } // 2. check 0.0.0.0 listen(port, '0.0.0.0', err => { if (err) { - return handleError(err); + return handleError(); } // 3. check localhost listen(port, 'localhost', err => { // if localhost refer to the ip that is not unkonwn on the machine, you will see the error EADDRNOTAVAIL // https://stackoverflow.com/questions/10809740/listen-eaddrnotavail-error-in-node-js - if (err && err.code !== 'EADDRNOTAVAIL') { - return handleError(err); + if (err && (err as any).code !== 'EADDRNOTAVAIL') { + return handleError(); } // 4. check current ip - listen(port, address.ip(), (err, realPort) => { + listen(port, ip(), (err, realPort) => { if (err) { - return handleError(err); + return handleError(); } callback(null, realPort); @@ -98,21 +109,23 @@ function tryListen(port, maxPort, hostname, callback) { } } -function listen(port, hostname, callback) { +function listen(port: number, hostname: string | undefined, callback: (...args: any[]) => void) { const server = new net.Server(); server.on('error', err => { debug('listen %s:%s error: %s', hostname, port, err); server.close(); - if (err.code === 'ENOTFOUND') { + + if ((err as any).code === 'ENOTFOUND') { debug('ignore dns ENOTFOUND error, get free %s:%s', hostname, port); return callback(null, port); } + return callback(err); }); server.listen(port, hostname, () => { - port = server.address().port; + port = (server.address() as net.AddressInfo).port; server.close(); debug('get free %s:%s', hostname, port); return callback(null, port); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..e7782f1 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,6 @@ +import detectPort from './detect-port.js'; +import waitPort from './wait-port.js'; + +export default detectPort; + +export { waitPort }; diff --git a/src/wait-port.ts b/src/wait-port.ts new file mode 100644 index 0000000..b9a1a97 --- /dev/null +++ b/src/wait-port.ts @@ -0,0 +1,35 @@ +import { debuglog } from 'node:util'; +import detectPort from './detect-port.js'; + +const debug = debuglog('wait-port'); + +const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); + +export interface WaitPortOptions { + retryInterval?: number; + retries?: number; +} + +export default async function waitPort(port: number, options: WaitPortOptions = {}) { + const { retryInterval = 1000, retries = Infinity } = options; + let count = 1; + + async function loop() { + debug('retries', retries, 'count', count); + if (count > retries) { + const err = new Error('retries exceeded'); + (err as any).retries = retries; + (err as any).count = count; + throw err; + } + count++; + const freePort = await detectPort(port); + if (freePort === port) { + await sleep(retryInterval); + return loop(); + } + return true; + } + + return await loop(); +} diff --git a/test/cli.test.js b/test/cli.test.js deleted file mode 100644 index a5067ab..0000000 --- a/test/cli.test.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; - -const path = require('path'); -const assert = require('assert'); -const CliTest = require('command-line-test'); - -const pkg = require('../package'); - -const cliTest = new CliTest(); -const binFile = path.resolve(pkg.bin[pkg.name]); - -describe('command-line tool test', () => { - - it('should show version and exit', async () => { - let res = await cliTest.exec(`node ${binFile} -v`, {}); - assert.equal(res.stdout, pkg.version); - res = await cliTest.exec(`node ${binFile} --version`, {}); - assert(res.stdout.includes(pkg.version)); - }); - - it('should output usage information', async () => { - let res = await cliTest.exec(`node ${binFile} -h`, {}); - assert(res.stdout.includes(pkg.description)); - res = await cliTest.exec(`node ${binFile} --help`, {}); - assert(res.stdout.includes(pkg.description)); - res = await cliTest.exec(`node ${binFile} help`, {}); - assert(res.stdout.includes(pkg.description)); - res = await cliTest.exec(`node ${binFile} xxx`, {}); - assert(res.stdout.includes(pkg.description)); - }); - - it('should output available port randomly', async () => { - const res = await cliTest.exec(`node ${binFile}`, {}); - const port = parseInt(res.stdout.trim(), 10); - assert(port >= 9000 && port < 65535); - }); - - it('should output available port from the given port', async () => { - const givenPort = 9000; - const res = await cliTest.exec(`node ${binFile} ${givenPort}`, {}); - const port = parseInt(res.stdout.trim(), 10); - assert(port >= givenPort && port < 65535); - }); - - it('should output verbose logs', async () => { - const res = await cliTest.exec(`node ${binFile} --verbose`, {}); - assert(res.stdout.includes('random')); - }); - -}); diff --git a/test/cli.test.ts b/test/cli.test.ts new file mode 100644 index 0000000..6695600 --- /dev/null +++ b/test/cli.test.ts @@ -0,0 +1,58 @@ +import stripAnsi from 'strip-ansi'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, it } from 'node:test'; +import { execaNode } from 'execa'; +import { strict as assert } from 'node:assert'; +import pkg from '../package.json'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const execaNodeWithLoader = (async (scripPath, args, options) => { + return execaNode(scripPath, args, { + ...options, + verbose: true, + nodeOptions: [ '--loader', 'tsx' ], + }); +}) as typeof execaNode; + +describe('test/cli.test.js', async () => { + const binFile = path.join(__dirname, '../bin/detect-port.ts'); + + it('should show version', async () => { + let res = await execaNodeWithLoader(binFile, [ '-v' ]); + assert(res.stdout, pkg.version); + res = await execaNodeWithLoader(binFile, [ '--version' ]); + assert(res.stdout, pkg.version); + }); + + it('should output usage information', async () => { + let res = await execaNodeWithLoader(binFile, [ '-h' ]); + assert(res.stdout.includes(pkg.description)); + res = await execaNodeWithLoader(binFile, [ '--help' ]); + assert(res.stdout.includes(pkg.description)); + res = await await execaNodeWithLoader(binFile, [ 'help' ]); + assert(res.stdout.includes(pkg.description)); + res = await await execaNodeWithLoader(binFile, [ 'xxx' ]); + assert(res.stdout.includes(pkg.description)); + }); + + it('should output available port randomly', { only: true }, async () => { + const res = await execaNodeWithLoader(binFile); + const port = parseInt(stripAnsi(res.stdout).trim(), 10); + assert(port >= 9000 && port < 65535); + }); + + it('should output available port from the given port', async () => { + const givenPort = 9000; + const res = await execaNodeWithLoader(binFile, [ givenPort + '' ]); + const port = parseInt(stripAnsi(res.stdout).trim(), 10); + assert(port >= givenPort && port < 65535); + }); + + it('should output verbose logs', async () => { + const res = await execaNodeWithLoader(binFile, [ '--verbose' ]); + assert(res.stdout.includes('random')); + }); +}); diff --git a/test/detect-port.test.js b/test/detect-port.test.js deleted file mode 100644 index af1b3a5..0000000 --- a/test/detect-port.test.js +++ /dev/null @@ -1,189 +0,0 @@ -'use strict'; - -const mm = require('mm'); -const dns = require('dns'); -const net = require('net'); -const pedding = require('pedding'); -const address = require('address'); -const assert = require('power-assert'); - -const detectPort = require('..'); - -describe('test/detect-port.test.js', () => { - describe('detect port test', () => { - const servers = []; - before(done => { - done = pedding(13, done); - const server = new net.Server(); - server.listen(3000, 'localhost', done); - server.on('error', err => { - console.error('listen localhost error:', err); - }); - servers.push(server); - - const server2 = new net.Server(); - server2.listen(4000, address.ip(), done); - servers.push(server2); - - const server3 = new net.Server(); - server3.listen(8080, '0.0.0.0', done); - servers.push(server3); - - for (let port = 7000; port < 7010; port++) { - const server = new net.Server(); - if (port % 3 === 0) { - server.listen(port, done); - } else if (port % 3 === 1) { - server.listen(port, 'localhost', done); - } else { - server.listen(port, address.ip(), done); - } - servers.push(server); - } - }); - after(() => { - servers.forEach(server => server.close()); - }); - - afterEach(mm.restore); - - it('get random port', done => { - detectPort((_, port) => { - assert(port >= 1024 && port < 65535); - done(); - }); - }); - - it('callback with occupied port', done => { - const _port = 80; - detectPort(_port, (_, port) => { - assert(port >= _port && port < 65535); - done(); - }); - }); - - it('work with listening next port 3001 because 3000 was listened to localhost', done => { - const port = 3000; - detectPort(port, (_, realPort) => { - assert(realPort === 3001); - done(); - }); - }); - - it('should listen next port 4001 when localhost is not binding', done => { - // https://github.com/nodejs/node/blob/6af72d4b037eba38d94395f57a03a498a2efef09/lib/net.js#L1463 - // mock dns.lookup - mm(dns, '__rawLookup', dns.lookup); - mm(dns, 'lookup', (address, callback) => { - if (address !== 'localhost') { - return dns.__rawLookup(address, callback); - } - process.nextTick(() => { - const err = new Error(`getaddrinfo ENOTFOUND ${address}`); - err.code = 'ENOTFOUND'; - callback(err); - }); - }); - const port = 4000; - detectPort(port, (_, realPort) => { - assert(realPort === 4001); - done(); - }); - }); - - it('work with listening next port 4001 because 4000 was listened to ' + address.ip(), done => { - const port = 4000; - detectPort(port, (_, realPort) => { - assert(realPort === 4001); - done(); - }); - }); - - it('work with listening next port 8081 because 8080 was listened to 0.0.0.0:8080', done => { - const port = 8080; - detectPort(port, (_, realPort) => { - assert(realPort === 8081); - done(); - }); - }); - - it('work with listening random port when try port hit maxPort', done => { - const port = 7000; - detectPort(port, (_, realPort) => { - assert(realPort < 7000 || realPort > 7009); - done(); - }); - }); - - it('work with sending object with hostname', done => { - const port = 7000; - const hostname = '127.0.0.1'; - detectPort({ - port, - hostname, - callback: (_, realPort) => { - assert(realPort >= 7000 && realPort < 65535); - done(); - }, - }); - }); - - it('promise with sending object with hostname', done => { - const port = 7000; - const hostname = '127.0.0.1'; - detectPort({ - port, - hostname, - }).then(realPort => { - assert(realPort >= 7000 && realPort < 65535); - done(); - }); - }); - - it('callback with string arg', done => { - const _port = '8080'; - detectPort(_port, (_, port) => { - assert(port >= 8080 && port < 65535); - done(); - }); - }); - - it('callback with wrong arguments', done => { - detectPort('oooo', (_, port) => { - assert(port > 0); - done(); - }); - }); - - it('generator usage', async () => { - const _port = 8080; - const port = await detectPort(_port); - assert(port >= _port && port < 65535); - }); - - it('promise usage', done => { - const _port = 8080; - detectPort(_port) - .then(port => { - assert(port >= _port && port < 65535); - done(); - }) - .catch(done); - }); - - it('promise with wrong arguments', done => { - detectPort() - .then(port => { - assert(port > 0); - done(); - }) - .catch(done); - }); - - it('generator with wrong arguments and return random port', async () => { - const port = await detectPort('oooo'); - assert(port > 0); - assert(typeof port === 'number'); - }); - }); -}); diff --git a/test/detect-port.test.ts b/test/detect-port.test.ts new file mode 100644 index 0000000..f1593fc --- /dev/null +++ b/test/detect-port.test.ts @@ -0,0 +1,188 @@ +import dns from 'node:dns'; +import net from 'node:net'; +import { strict as assert } from 'node:assert'; +import { mock, describe, it, before, after } from 'node:test'; +import { ip } from 'address'; + +import detectPort from '../src/detect-port.js'; + +describe('test/detect-port.test.js', () => { + describe('detect port test', () => { + const servers: net.Server[] = []; + before((_, done) => { + let count = 0; + const cb = mock.fn((err?: Error) => { + if (err) { + done(err); + } + count += 1; + if (count === 13) { + done(); + } + }); + const server = new net.Server(); + server.listen(3000, 'localhost', cb); + server.on('error', err => { + console.error('listen localhost error:', err); + }); + servers.push(server); + + const server2 = new net.Server(); + server2.listen(4000, ip(), cb); + servers.push(server2); + + const server3 = new net.Server(); + server3.listen(8080, '0.0.0.0', cb); + servers.push(server3); + + for (let port = 7000; port < 7010; port++) { + const server = new net.Server(); + if (port % 3 === 0) { + server.listen(port, cb); + } else if (port % 3 === 1) { + server.listen(port, 'localhost', cb); + } else { + server.listen(port, ip(), cb); + } + servers.push(server); + } + }); + after(() => { + servers.forEach(server => server.close()); + mock.reset(); + }); + + it('get random port with callback', (_, done) => { + detectPort((_, port) => { + assert(port >= 1024 && port < 65535); + done(); + }); + + }); + + it('get random port with promise', async () => { + const port = await detectPort(); + + assert(port >= 1024 && port < 65535); + }); + + it('with occupied port', async () => { + const port = 80; + const realPort = await detectPort(port); + + assert(realPort >= port && realPort < 65535); + }); + + it('work with listening next port 3001 because 3000 was listened to localhost', async () => { + const port = 3000; + const realPort = await detectPort(port); + + assert(realPort === 3001); + }); + + it('should listen next port 4001 when localhost is not binding', async t => { + t.mock.method(dns, 'lookup', (address: string, callback: (...args: any[]) => void) => { + if (address !== 'localhost') { + return dns.lookup(address, callback); + } + process.nextTick(() => { + const err = new Error(`getaddrinfo ENOTFOUND ${address}`); + (err as any).code = 'ENOTFOUND'; + callback(err); + }); + }, { times: 1 }); + + const port = 4000; + const realPort = await detectPort(port); + + assert(realPort === 4001); + + t.mock.reset(); + }); + + it('work with listening next port 4001 because 4000 was listened to ' + ip(), async () => { + const port = 4000; + const realPort = await detectPort(port); + + assert(realPort === 4001); + }); + + it('work with listening next port 8081 because 8080 was listened to 0.0.0.0:8080', async () => { + const port = 8080; + const realPort = await detectPort(port); + + assert(realPort === 8081); + }); + + it('work with listening random port when try port hit maxPort', async () => { + const port = 7000; + const realPort = await detectPort(port); + assert(realPort < 7000 || realPort > 7009); + }); + + it('work with sending object with hostname', (_, done) => { + const port = 7000; + const hostname = '127.0.0.1'; + detectPort({ + port, + hostname, + callback: (_, realPort) => { + assert(realPort >= 7000 && realPort < 65535); + done(); + }, + }); + }); + + it('promise with sending object with hostname', async () => { + const port = 7000; + const hostname = '127.0.0.1'; + const realPort = await detectPort({ + port, + hostname, + }); + assert(realPort >= 7000 && realPort < 65535); + }); + + it('with string arg', async () => { + const port = '8080'; + const realPort = await detectPort(port); + assert(realPort >= 8080 && realPort < 65535); + }); + + it('with wrong arguments', async () => { + const port = await detectPort('oooo'); + assert(port && port > 0); + }); + + it('generator usage', async () => { + const port = 8080; + const realPort = await detectPort(port); + assert(realPort >= port && realPort < 65535); + }); + + it('promise usage', (_, done) => { + const _port = 8080; + detectPort(_port) + .then(port => { + assert(port >= _port && port < 65535); + done(); + }) + .catch(done); + }); + + it('promise with wrong arguments', (_, done) => { + detectPort() + .then(port => { + assert(port > 0); + done(); + }) + .catch(done); + }); + + it('generator with wrong arguments and return random port', async () => { + const port = await detectPort('oooo'); + assert(port > 0); + assert(typeof port === 'number'); + }); + }); +}); diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index de65ecc..0000000 --- a/test/mocha.opts +++ /dev/null @@ -1 +0,0 @@ ---timeout 30000 \ No newline at end of file diff --git a/test/wait-port.test.js b/test/wait-port.test.js deleted file mode 100644 index 84f407a..0000000 --- a/test/wait-port.test.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -const mm = require('mm'); -const net = require('net'); - -const { waitPort } = require('..'); - -describe('test/wait-port.test.js', () => { - describe('wait for port', () => { - const servers = []; - after(() => { - servers.forEach(server => server.close()); - }); - - afterEach(mm.restore); - - it('should be work', done => { - const port = 9090; - const server = new net.Server(); - server.listen(port, '0.0.0.0'); - servers.push(server); - setTimeout(() => { - waitPort(port).then().finally(done); - }); - }); - - it('should be work when retries exceeded', done => { - const port = 9093; - waitPort(port, { - retries: 3, - retryInterval: 100, - }).then().finally(done); - }); - }); -}); diff --git a/test/wait-port.test.ts b/test/wait-port.test.ts new file mode 100644 index 0000000..a1e41a0 --- /dev/null +++ b/test/wait-port.test.ts @@ -0,0 +1,33 @@ +import net from 'node:net'; +import { describe, it, after } from 'node:test'; +import { strict as assert } from 'node:assert'; + +import waitPort from '../src/wait-port.js'; + +describe('test/wait-port.test.js', () => { + describe('wait for port', () => { + const servers: net.Server[] = []; + after(() => { + servers.forEach(server => server.close()); + }); + + it('should be work', (_, done) => { + const port = 9090; + const server = new net.Server(); + server.listen(port, '0.0.0.0'); + servers.push(server); + setTimeout(() => { + waitPort(port).then().finally(done); + }); + }); + + it('should be work when retries exceeded', async () => { + try { + const port = 9093; + await waitPort(port, { retries: 3, retryInterval: 100 }); + } catch (err:any) { + assert(err.message === 'retries exceeded'); + } + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..10b9c72 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@eggjs/tsconfig", + "compilerOptions": { + "target": "es2022", + "module": "nodenext", + "moduleResolution": "nodenext" + } +} \ No newline at end of file