index.cjs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. async function getPort(config) {
  95. if (typeof config === "number" || typeof config === "string") {
  96. config = { port: parseInt(config + "") };
  97. }
  98. const options = {
  99. name: "default",
  100. random: false,
  101. port: parseInt(process.env.PORT || "") || 3e3,
  102. ports: [],
  103. portRange: [3e3, 3100],
  104. host: void 0,
  105. memoName: "port",
  106. ...config
  107. };
  108. if (options.random) {
  109. return getRandomPort(options.host);
  110. }
  111. const portsToCheck = [
  112. options.port,
  113. ...options.ports,
  114. ...generateRange(options.portRange[0], options.portRange[1])
  115. ].filter((port) => port && isSafePort(port));
  116. const memoOptions = { name: options.memoName, dir: options.memoDir };
  117. const memoKey = "port_" + options.name;
  118. const memo = await fsMemo.getMemo(memoOptions);
  119. if (memo[memoKey]) {
  120. portsToCheck.push(memo[memoKey]);
  121. }
  122. const availablePort = await findPort(portsToCheck, options.host);
  123. await fsMemo.setMemo({ [memoKey]: availablePort }, memoOptions);
  124. return availablePort;
  125. }
  126. async function getRandomPort(host) {
  127. const port = await checkPort(0, host);
  128. if (port === false) {
  129. throw new Error("Unable to obtain an available random port number!");
  130. }
  131. return port;
  132. }
  133. async function waitForPort(port, opts = {}) {
  134. const delay = opts.delay || 500;
  135. const retries = opts.retries || 4;
  136. for (let i = retries; i > 0; i--) {
  137. if (await checkPort(port, opts.host) === false) {
  138. return;
  139. }
  140. await new Promise((resolve) => setTimeout(resolve, delay));
  141. }
  142. throw new Error(`Timeout waiting for port ${port} after ${retries} retries with ${delay}ms interval.`);
  143. }
  144. async function checkPort(port, host = process.env.HOST) {
  145. if (!host) {
  146. host = getLocalHosts([void 0, "0.0.0.0"]);
  147. }
  148. if (!Array.isArray(host)) {
  149. return _checkPort(port, host);
  150. }
  151. for (const _host of host) {
  152. const _port = await _checkPort(port, _host);
  153. if (_port === false) {
  154. return false;
  155. }
  156. if (port === 0 && _port !== 0) {
  157. port = _port;
  158. }
  159. }
  160. return port;
  161. }
  162. function generateRange(from, to) {
  163. if (to < from) {
  164. return [];
  165. }
  166. const r = [];
  167. for (let i = from; i < to; i++) {
  168. r.push(i);
  169. }
  170. return r;
  171. }
  172. function _checkPort(port, host) {
  173. return new Promise((resolve) => {
  174. const server = net.createServer();
  175. server.unref();
  176. server.on("error", (err) => {
  177. if (err.code === "EINVAL" || err.code === "EADDRNOTAVAIL") {
  178. resolve(port !== 0 && isSafePort(port) && port);
  179. } else {
  180. resolve(false);
  181. }
  182. });
  183. server.listen({ port, host }, () => {
  184. const { port: port2 } = server.address();
  185. server.close(() => {
  186. resolve(isSafePort(port2) && port2);
  187. });
  188. });
  189. });
  190. }
  191. function getLocalHosts(additional) {
  192. const hosts = new Set(additional);
  193. for (const _interface of Object.values(os.networkInterfaces())) {
  194. for (const config of _interface) {
  195. hosts.add(config.address);
  196. }
  197. }
  198. return Array.from(hosts);
  199. }
  200. async function findPort(ports, host) {
  201. for (const port of ports) {
  202. const r = await checkPort(port, host);
  203. if (r) {
  204. return r;
  205. }
  206. }
  207. return getRandomPort(host);
  208. }
  209. exports.checkPort = checkPort;
  210. exports.getPort = getPort;
  211. exports.getRandomPort = getRandomPort;
  212. exports.isSafePort = isSafePort;
  213. exports.isUnsafePort = isUnsafePort;
  214. exports.waitForPort = waitForPort;