Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add host option #4

Merged
merged 2 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface GetPortOptions {
random?: boolean
port?: number
ports?: number[]
host?: string

memoDir?: string
memoName?: string
Expand All @@ -60,6 +61,10 @@ First port to check. Default is `process.env.PORT || 3000`

Alternative ports to check. Default is `[4000, 5000, 6000, 7000]`

### `host`

The host to check. Default is `process.env.HOST || '0.0.0.0'`

### `memoDir` / `memoName`

Options passed to [fs-memo](https://github.com/nuxt-contrib/fs-memo)
Expand Down
8 changes: 8 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { Config } from '@jest/types'

const config: Config.InitialOptions = {
preset: 'ts-jest',
testEnvironment: 'node'
}

export default config
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@
"scripts": {
"build": "siroc build",
"lint": "eslint --ext ts .",
"release": "yarn build && standard-version && npm publish && git push --follow-tags"
"release": "yarn build && standard-version && npm publish && git push --follow-tags",
"test": "jest"
},
"dependencies": {
"fs-memo": "^1.2.0"
},
"devDependencies": {
"@nuxtjs/eslint-config-typescript": "latest",
"@types/jest": "^26.0.22",
"@types/node": "latest",
"eslint": "latest",
"jest": "^26.6.3",
"siroc": "^0.4.0",
"standard-version": "latest",
"ts-jest": "^26.5.4",
"ts-node": "^9.1.1",
"typescript": "latest"
}
}
16 changes: 9 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface GetPortOptions {
random: boolean
port: number
ports: number[]
host: string
memoDir: string
memoName: string
}
Expand All @@ -17,6 +18,7 @@ const defaults = {
random: false,
port: parseInt(process.env.PORT || '') || 3000,
ports: [4000, 5000, 6000, 7000],
host: process.env.HOST || '0.0.0.0',
memoName: 'port'
}

Expand Down Expand Up @@ -50,30 +52,30 @@ export async function getPort (config?: GetPortInput): Promise<number> {
portsToCheck.push(memo[memoKey])
}

const availablePort = await checkPorts(portsToCheck)
const availablePort = await checkPorts(portsToCheck, options.host)

// Persist
await setMemo({ [memoKey]: availablePort }, memoOptions)

return availablePort
}

async function checkPorts (ports: number[]): Promise<number> {
for (const p of ports) {
const r = await checkPort(p)
async function checkPorts (ports: number[], host: string): Promise<number> {
for (const port of ports) {
const r = await checkPort(port, host)
if (r) {
return r
}
}
return checkPort(0) as unknown as number
return checkPort(0, host) as unknown as number
}

function checkPort (port: number): Promise<number|false> {
function checkPort (port: number, host: string): Promise<number|false> {
return new Promise((resolve) => {
const server = createServer()
server.unref()
server.on('error', () => { resolve(false) })
server.listen({ port }, () => {
server.listen(port, host, () => {
const { port } = server.address() as AddressInfo
server.close(() => { resolve(port) })
})
Expand Down
45 changes: 45 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Server } from 'net'
import { getPort } from '../src'
import { blockPort } from './utils'

describe('getPort ()', () => {
describe('checks ports on default host`', () => {
let portBlocker: Server

afterEach(() => {
portBlocker?.close()
})

test('default port is NOT IN USE', async () => {
const port = await getPort()
expect(port).toEqual(3000)
})

test('default port is in use', async () => {
portBlocker = await blockPort(3000)
const port = await getPort()
expect(port).toEqual(4000)
})
})
})

describe('getPort (host)', () => {
describe('checks ports on `localhost`', () => {
let portBlocker: Server

afterEach(() => {
portBlocker?.close()
})

test('default port is NOT IN USE', async () => {
const port = await getPort({ host: 'localhost' })
expect(port).toEqual(3000)
})

test('default port is IN USE', async () => {
portBlocker = await blockPort(3000, 'localhost')
const port = await getPort({ host: 'localhost' })
expect(port).toEqual(4000)
})
})
})
31 changes: 31 additions & 0 deletions test/process.env.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Server } from 'net'
import { blockPort } from './utils'

describe('getPort (host)', () => {
const ENV = process.env
let portBlocker: Server

beforeEach(() => {
jest.resetModules()
process.env = ENV
})

afterEach(() => {
process.env = ENV
portBlocker?.close()
})

test('default port is not use', async () => {
const { getPort } = await import('../src')
const port = await getPort()
expect(port).toEqual(3000)
})

test('default port is in use', async () => {
process.env.HOST = 'localhost'
const { getPort } = await import('../src')
portBlocker = await blockPort(3000, 'localhost')
const port = await getPort()
expect(port).toEqual(4000)
})
})
21 changes: 21 additions & 0 deletions test/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createServer, Server } from 'net'

export function blockPort (port: number, host = '0.0.0.0'): Promise<Server> {
return new Promise((resolve) => {
const blocker = createServer()
blocker.listen(port, host, () => {
resolve(blocker)
})
})
}

export async function blockPorts (ports: number[], host = '0.0.0.0'): Promise<Server[]> {
const portBlockers: Server[] = []

for (const port of ports) {
const blocker = await blockPort(port, host)
portBlockers.push(blocker)
}

return portBlockers
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"strict": true,
"declaration": true,
"types": [
"node"
"node",
"jest"
]
},
"include": [
Expand Down
Loading