UNPKG

2.26 kBJavaScriptView Raw
1const portfinder = require('portfinder')
2
3/**
4 * 获取可用端口
5 * @async
6 * @param {Number|Number[]|Object} 正在使用、被占用或保留的端口
7 * @returns {Number}
8 */
9module.exports = async (portUsed) => {
10
11 const portStart = 3000
12 const portEnd = 65535
13
14 /** @type {Array[]} 使用 portfinder 检查的端口号范围组 */
15 const ranges = [
16 [portStart, portEnd]
17 ]
18
19 // console.log('portUsed', portUsed)
20
21 /** @type {Number[]} 忽略的端口号 */
22 const portsIgnore = []
23 if (isNumber(portUsed)) {
24 portsIgnore.push(parseInt(portUsed))
25 } else if (Array.isArray(portUsed)) {
26 portUsed.filter(value => isNumber(value))
27 .forEach(port => portsIgnore.push(parseInt(port)))
28 } else if (typeof portUsed === 'object') {
29 Object.values(portUsed)
30 .filter(value => isNumber(value))
31 .forEach(port => portsIgnore.push(parseInt(port)))
32 }
33
34 // console.log('portsIgnore', portsIgnore)
35
36 // 如果存在忽略的端口号,修改 ranges 为多组模式
37 if (portsIgnore.length) {
38 ranges.shift()
39 let lastPort = portStart
40 portsIgnore.forEach(port => {
41 ranges.push([lastPort, port - 1])
42 lastPort = port
43 })
44 }
45
46 // console.log('ranges', ranges)
47
48 for (let [start, end] of ranges) {
49 const result = await getFreePort(start, end)
50 // console.log(result)
51 if (result)
52 return result
53 }
54}
55
56const isNumber = (value) => Boolean(
57 typeof value === 'number' ||
58 !isNaN(value)
59)
60
61/**
62 * 获取范围内可用的端口
63 * @param {Number} start
64 * @param {Number} end
65 * @returns {Number}
66 */
67const getFreePort = async (start, end) =>
68 portfinder.getPortPromise({
69 port: start, // minimum port
70 stopPort: end // maximum port
71 })
72 .then((port) => {
73 //
74 // `port` is guaranteed to be a free port
75 // in this scope.
76 //
77 return port
78 })
79 .catch((/*err*/) => {
80 //
81 // Could not get a free port, `err` contains the reason.
82 //
83 })