index.cjs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. const net = require('net');
  4. const os = require('os');
  5. const fsMemo = require('fs-memo');
  6. const unsafePorts = /* @__PURE__ */ new Set([
  7. 1,
  8. 7,
  9. 9,
  10. 11,
  11. 13,
  12. 15,
  13. 17,
  14. 19,
  15. 20,
  16. 21,
  17. 22,
  18. 23,
  19. 25,
  20. 37,
  21. 42,
  22. 43,
  23. 53,
  24. 69,
  25. 77,
  26. 79,
  27. 87,
  28. 95,
  29. 101,
  30. 102,
  31. 103,
  32. 104,
  33. 109,
  34. 110,
  35. 111,
  36. 113,
  37. 115,
  38. 117,
  39. 119,
  40. 123,
  41. 135,
  42. 137,
  43. 139,
  44. 143,
  45. 161,
  46. 179,
  47. 389,
  48. 427,
  49. 465,
  50. 512,
  51. 513,
  52. 514,
  53. 515,
  54. 526,
  55. 530,
  56. 531,
  57. 532,
  58. 540,
  59. 548,
  60. 554,
  61. 556,
  62. 563,
  63. 587,
  64. 601,
  65. 636,
  66. 989,
  67. 990,
  68. 993,
  69. 995,
  70. 1719,
  71. 1720,
  72. 1723,
  73. 2049,
  74. 3659,
  75. 4045,
  76. 5060,
  77. 5061,
  78. 6e3,
  79. 6566,
  80. 6665,
  81. 6666,
  82. 6667,
  83. 6668,
  84. 6669,
  85. 6697,
  86. 10080
  87. ]);
  88. function isUnsafePort(port) {
  89. return unsafePorts.has(port);
  90. }
  91. function isSafePort(port) {
  92. return !isUnsafePort(port);
  93. }
  94. function log(...args) {
  95. console.log("[get-port]", ...args);
  96. }
  97. async function getPort(config = {}) {
  98. if (typeof config === "number" || typeof config === "string") {
  99. config = { port: parseInt(config + "") || 0 };
  100. }
  101. const options = {
  102. name: "default",
  103. random: false,
  104. ports: [],
  105. portRange: [],
  106. alternativePortRange: [3e3, 3100],
  107. host: void 0,
  108. memoName: "port",
  109. verbose: false,
  110. ...config,
  111. port: parseInt(process.env.PORT || "") || config.port || 3e3
  112. };
  113. if (options.random) {
  114. return getRandomPort(options.host);
  115. }
  116. const portsToCheck = [
  117. options.port,
  118. ...options.ports,
  119. ...generateRange(...options.portRange)
  120. ].filter((port) => {
  121. if (!port) {
  122. return false;
  123. }
  124. if (!isSafePort(port)) {
  125. if (options.verbose) {
  126. log("Ignoring unsafe port:", port);
  127. }
  128. return false;
  129. }
  130. return true;
  131. });
  132. const memoOptions = { name: options.memoName, dir: options.memoDir };
  133. const memoKey = "port_" + options.name;
  134. const memo = await fsMemo.getMemo(memoOptions);
  135. if (memo[memoKey]) {
  136. portsToCheck.push(memo[memoKey]);
  137. }
  138. let availablePort = await findPort(portsToCheck, options.host, options.verbose, false);
  139. if (!availablePort) {
  140. availablePort = await findPort(generateRange(...options.alternativePortRange), options.host, options.verbose);
  141. if (options.verbose) {
  142. log(`Unable to find an available port (tried ${portsToCheck.join(", ") || "-"}). Using alternative port:`, availablePort);
  143. }
  144. }
  145. await fsMemo.setMemo({ [memoKey]: availablePort }, memoOptions);
  146. return availablePort;
  147. }
  148. async function getRandomPort(host) {
  149. const port = await checkPort(0, host);
  150. if (port === false) {
  151. throw new Error("Unable to obtain an available random port number!");
  152. }
  153. return port;
  154. }
  155. async function waitForPort(port, opts = {}) {
  156. const delay = opts.delay || 500;
  157. const retries = opts.retries || 4;
  158. for (let i = retries; i > 0; i--) {
  159. if (await checkPort(port, opts.host) === false) {
  160. return;
  161. }
  162. await new Promise((resolve) => setTimeout(resolve, delay));
  163. }
  164. throw new Error(`Timeout waiting for port ${port} after ${retries} retries with ${delay}ms interval.`);
  165. }
  166. async function checkPort(port, host = process.env.HOST, _verbose) {
  167. if (!host) {
  168. host = getLocalHosts([void 0, "0.0.0.0"]);
  169. }
  170. if (!Array.isArray(host)) {
  171. return _checkPort(port, host);
  172. }
  173. for (const _host of host) {
  174. const _port = await _checkPort(port, _host);
  175. if (_port === false) {
  176. if (port < 1024 && _verbose) {
  177. log("Unable to listen to priviliged port:", `${_host}:${port}`);
  178. }
  179. return false;
  180. }
  181. if (port === 0 && _port !== 0) {
  182. port = _port;
  183. }
  184. }
  185. return port;
  186. }
  187. function generateRange(from, to) {
  188. if (to < from) {
  189. return [];
  190. }
  191. const r = [];
  192. for (let i = from; i < to; i++) {
  193. r.push(i);
  194. }
  195. return r;
  196. }
  197. function _checkPort(port, host) {
  198. return new Promise((resolve) => {
  199. const server = net.createServer();
  200. server.unref();
  201. server.on("error", (err) => {
  202. if (err.code === "EINVAL" || err.code === "EADDRNOTAVAIL") {
  203. resolve(port !== 0 && isSafePort(port) && port);
  204. } else {
  205. resolve(false);
  206. }
  207. });
  208. server.listen({ port, host }, () => {
  209. const { port: port2 } = server.address();
  210. server.close(() => {
  211. resolve(isSafePort(port2) && port2);
  212. });
  213. });
  214. });
  215. }
  216. function getLocalHosts(additional) {
  217. const hosts = new Set(additional);
  218. for (const _interface of Object.values(os.networkInterfaces())) {
  219. for (const config of _interface) {
  220. hosts.add(config.address);
  221. }
  222. }
  223. return Array.from(hosts);
  224. }
  225. async function findPort(ports, host, _verbose = false, _random = true) {
  226. for (const port of ports) {
  227. const r = await checkPort(port, host, _verbose);
  228. if (r) {
  229. return r;
  230. }
  231. }
  232. if (_random) {
  233. const randomPort = await getRandomPort(host);
  234. if (_verbose) {
  235. log(`Unable to find an available port (tried ${ports.join(", ") || "-"}). Using random port:`, randomPort);
  236. }
  237. return randomPort;
  238. } else {
  239. return 0;
  240. }
  241. }
  242. exports.checkPort = checkPort;
  243. exports.getPort = getPort;
  244. exports.getRandomPort = getRandomPort;
  245. exports.isSafePort = isSafePort;
  246. exports.isUnsafePort = isUnsafePort;
  247. exports.waitForPort = waitForPort;