@edgible-team/cli 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +136 -0
  2. package/README.md +450 -0
  3. package/dist/client/api-client.js +1057 -0
  4. package/dist/client/index.js +21 -0
  5. package/dist/commands/agent.js +1280 -0
  6. package/dist/commands/ai.js +608 -0
  7. package/dist/commands/application.js +885 -0
  8. package/dist/commands/auth.js +570 -0
  9. package/dist/commands/base/BaseCommand.js +93 -0
  10. package/dist/commands/base/CommandHandler.js +7 -0
  11. package/dist/commands/base/command-wrapper.js +58 -0
  12. package/dist/commands/base/middleware.js +77 -0
  13. package/dist/commands/config.js +116 -0
  14. package/dist/commands/connectivity.js +59 -0
  15. package/dist/commands/debug.js +98 -0
  16. package/dist/commands/discover.js +144 -0
  17. package/dist/commands/examples/migrated-command-example.js +180 -0
  18. package/dist/commands/gateway.js +494 -0
  19. package/dist/commands/managedGateway.js +787 -0
  20. package/dist/commands/utils/config-validator.js +76 -0
  21. package/dist/commands/utils/gateway-prompt.js +79 -0
  22. package/dist/commands/utils/input-parser.js +120 -0
  23. package/dist/commands/utils/output-formatter.js +109 -0
  24. package/dist/config/app-config.js +99 -0
  25. package/dist/detection/SystemCapabilityDetector.js +1244 -0
  26. package/dist/detection/ToolDetector.js +305 -0
  27. package/dist/detection/WorkloadDetector.js +314 -0
  28. package/dist/di/bindings.js +99 -0
  29. package/dist/di/container.js +88 -0
  30. package/dist/di/types.js +32 -0
  31. package/dist/index.js +52 -0
  32. package/dist/interfaces/IDaemonManager.js +3 -0
  33. package/dist/repositories/config-repository.js +62 -0
  34. package/dist/repositories/gateway-repository.js +35 -0
  35. package/dist/scripts/postinstall.js +101 -0
  36. package/dist/services/AgentStatusManager.js +299 -0
  37. package/dist/services/ConnectivityTester.js +271 -0
  38. package/dist/services/DependencyInstaller.js +475 -0
  39. package/dist/services/LocalAgentManager.js +2216 -0
  40. package/dist/services/application/ApplicationService.js +299 -0
  41. package/dist/services/auth/AuthService.js +214 -0
  42. package/dist/services/aws.js +644 -0
  43. package/dist/services/daemon/DaemonManagerFactory.js +65 -0
  44. package/dist/services/daemon/DockerDaemonManager.js +395 -0
  45. package/dist/services/daemon/LaunchdDaemonManager.js +257 -0
  46. package/dist/services/daemon/PodmanDaemonManager.js +369 -0
  47. package/dist/services/daemon/SystemdDaemonManager.js +221 -0
  48. package/dist/services/daemon/WindowsServiceDaemonManager.js +210 -0
  49. package/dist/services/daemon/index.js +16 -0
  50. package/dist/services/edgible.js +3060 -0
  51. package/dist/services/gateway/GatewayService.js +334 -0
  52. package/dist/state/config.js +146 -0
  53. package/dist/types/AgentConfig.js +5 -0
  54. package/dist/types/AgentStatus.js +5 -0
  55. package/dist/types/ApiClient.js +5 -0
  56. package/dist/types/ApiRequests.js +5 -0
  57. package/dist/types/ApiResponses.js +5 -0
  58. package/dist/types/Application.js +5 -0
  59. package/dist/types/CaddyJson.js +5 -0
  60. package/dist/types/UnifiedAgentStatus.js +56 -0
  61. package/dist/types/WireGuard.js +5 -0
  62. package/dist/types/Workload.js +5 -0
  63. package/dist/types/agent.js +5 -0
  64. package/dist/types/command-options.js +5 -0
  65. package/dist/types/connectivity.js +5 -0
  66. package/dist/types/errors.js +250 -0
  67. package/dist/types/gateway-types.js +5 -0
  68. package/dist/types/index.js +48 -0
  69. package/dist/types/models/ApplicationData.js +5 -0
  70. package/dist/types/models/CertificateData.js +5 -0
  71. package/dist/types/models/DeviceData.js +5 -0
  72. package/dist/types/models/DevicePoolData.js +5 -0
  73. package/dist/types/models/OrganizationData.js +5 -0
  74. package/dist/types/models/OrganizationInviteData.js +5 -0
  75. package/dist/types/models/ProviderConfiguration.js +5 -0
  76. package/dist/types/models/ResourceData.js +5 -0
  77. package/dist/types/models/ServiceResourceData.js +5 -0
  78. package/dist/types/models/UserData.js +5 -0
  79. package/dist/types/route.js +5 -0
  80. package/dist/types/validation/schemas.js +218 -0
  81. package/dist/types/validation.js +5 -0
  82. package/dist/utils/FileIntegrityManager.js +256 -0
  83. package/dist/utils/PathMigration.js +219 -0
  84. package/dist/utils/PathResolver.js +235 -0
  85. package/dist/utils/PlatformDetector.js +277 -0
  86. package/dist/utils/console-logger.js +130 -0
  87. package/dist/utils/docker-compose-parser.js +179 -0
  88. package/dist/utils/errors.js +130 -0
  89. package/dist/utils/health-checker.js +155 -0
  90. package/dist/utils/json-logger.js +72 -0
  91. package/dist/utils/log-formatter.js +293 -0
  92. package/dist/utils/logger.js +59 -0
  93. package/dist/utils/network-utils.js +217 -0
  94. package/dist/utils/output.js +182 -0
  95. package/dist/utils/passwordValidation.js +91 -0
  96. package/dist/utils/progress.js +167 -0
  97. package/dist/utils/sudo-checker.js +22 -0
  98. package/dist/utils/urls.js +32 -0
  99. package/dist/utils/validation.js +31 -0
  100. package/dist/validation/schemas.js +175 -0
  101. package/dist/validation/validator.js +67 -0
  102. package/package.json +83 -0
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ /**
3
+ * Utility functions for parsing and formatting journalctl logs
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.parseJournalctlLine = parseJournalctlLine;
10
+ exports.parseJournalctlOutput = parseJournalctlOutput;
11
+ exports.formatLogEntryColored = formatLogEntryColored;
12
+ exports.formatLogEntries = formatLogEntries;
13
+ exports.formatLogEntriesColored = formatLogEntriesColored;
14
+ exports.formatLogEntry = formatLogEntry;
15
+ exports.filterByLevel = filterByLevel;
16
+ exports.filterByModule = filterByModule;
17
+ exports.matchesLevel = matchesLevel;
18
+ exports.matchesModule = matchesModule;
19
+ exports.processLogs = processLogs;
20
+ exports.processLogLine = processLogLine;
21
+ const chalk_1 = __importDefault(require("chalk"));
22
+ /**
23
+ * Parse a single journalctl line to extract JSON log entry
24
+ * Handles systemd journal format: "timestamp hostname process: {json}"
25
+ * Example: "Nov 15 23:41:22 hostname node[123]: {\"timestamp\":...}"
26
+ */
27
+ function parseJournalctlLine(line) {
28
+ if (!line.trim()) {
29
+ return null;
30
+ }
31
+ // Find the JSON part - look for the pattern ": {" which separates the systemd prefix from JSON
32
+ // We need to find the last colon before a '{' to handle timestamps that contain colons
33
+ const jsonStartIndex = line.indexOf(': {');
34
+ if (jsonStartIndex === -1) {
35
+ // Try to find just a colon followed by whitespace and then {
36
+ const colonIndex = line.lastIndexOf(':');
37
+ if (colonIndex === -1) {
38
+ return null;
39
+ }
40
+ const afterColon = line.substring(colonIndex + 1).trim();
41
+ if (!afterColon.startsWith('{')) {
42
+ return null;
43
+ }
44
+ try {
45
+ const parsed = JSON.parse(afterColon);
46
+ return parsed;
47
+ }
48
+ catch (error) {
49
+ return null;
50
+ }
51
+ }
52
+ const jsonPart = line.substring(jsonStartIndex + 2).trim(); // +2 to skip ": "
53
+ if (!jsonPart.startsWith('{')) {
54
+ return null;
55
+ }
56
+ try {
57
+ const parsed = JSON.parse(jsonPart);
58
+ return parsed;
59
+ }
60
+ catch (error) {
61
+ // Skip lines that aren't valid JSON
62
+ return null;
63
+ }
64
+ }
65
+ /**
66
+ * Parse journalctl output to extract JSON log entries
67
+ * Handles systemd journal format: "timestamp hostname process: {json}"
68
+ */
69
+ function parseJournalctlOutput(rawLogs) {
70
+ const lines = rawLogs.split('\n');
71
+ const entries = [];
72
+ for (const line of lines) {
73
+ const entry = parseJournalctlLine(line);
74
+ if (entry) {
75
+ entries.push(entry);
76
+ }
77
+ }
78
+ return entries;
79
+ }
80
+ /**
81
+ * Get color for log level
82
+ */
83
+ function getLevelColor(level) {
84
+ const levelUpper = level.toUpperCase();
85
+ switch (levelUpper) {
86
+ case 'ERROR':
87
+ return chalk_1.default.redBright.bold;
88
+ case 'WARN':
89
+ return chalk_1.default.yellowBright.bold;
90
+ case 'INFO':
91
+ return chalk_1.default.cyanBright.bold;
92
+ case 'DEBUG':
93
+ return chalk_1.default.gray;
94
+ default:
95
+ return chalk_1.default.whiteBright;
96
+ }
97
+ }
98
+ /**
99
+ * Get color for module name
100
+ */
101
+ function getModuleColor(module) {
102
+ // Use vibrant, punchy colors for modules
103
+ const moduleColors = {
104
+ 'agent': chalk_1.default.blueBright.bold,
105
+ 'api-client': chalk_1.default.magentaBright.bold,
106
+ 'caddy': chalk_1.default.greenBright.bold,
107
+ 'haproxy': chalk_1.default.cyanBright.bold,
108
+ 'firewall': chalk_1.default.redBright.bold,
109
+ 'health': chalk_1.default.greenBright.bold,
110
+ 'status': chalk_1.default.yellowBright.bold,
111
+ 'update': chalk_1.default.cyanBright.bold,
112
+ };
113
+ const moduleLower = module.toLowerCase();
114
+ return moduleColors[moduleLower] || chalk_1.default.whiteBright.bold;
115
+ }
116
+ /**
117
+ * Format a single log entry with colors
118
+ */
119
+ function formatLogEntryColored(entry, singleLine = false) {
120
+ const levelColor = getLevelColor(entry.level);
121
+ const moduleColor = getModuleColor(entry.module);
122
+ // Format timestamp
123
+ const timestamp = entry.timestamp ? new Date(entry.timestamp).toLocaleString() : '';
124
+ const timestampStr = chalk_1.default.gray.dim(timestamp);
125
+ // Format level with color
126
+ const levelStr = levelColor(`[${entry.level.toUpperCase().padEnd(5)}]`);
127
+ // Format module with color
128
+ const moduleStr = moduleColor(`[${entry.module}]`);
129
+ // Format message
130
+ const messageStr = chalk_1.default.whiteBright(entry.message);
131
+ // Build the formatted line
132
+ let formatted = `${timestampStr} ${levelStr} ${moduleStr} ${messageStr}`;
133
+ // Add data if present and not in single-line mode
134
+ if (!singleLine && entry.data !== undefined) {
135
+ const dataStr = JSON.stringify(entry.data, null, 2);
136
+ formatted += chalk_1.default.gray.dim(`\n Data: ${dataStr}`);
137
+ }
138
+ // Add error trace if present and not in single-line mode
139
+ if (!singleLine && entry.errorTrace) {
140
+ formatted += chalk_1.default.redBright.bold(`\n Error Trace:\n${entry.errorTrace}`);
141
+ }
142
+ return formatted;
143
+ }
144
+ /**
145
+ * Format log entries as single-line JSON (one per line)
146
+ */
147
+ function formatLogEntries(entries) {
148
+ return entries.map(entry => JSON.stringify(entry)).join('\n');
149
+ }
150
+ /**
151
+ * Format log entries with colors
152
+ */
153
+ function formatLogEntriesColored(entries, singleLine = false) {
154
+ return entries.map(entry => formatLogEntryColored(entry, singleLine)).join('\n');
155
+ }
156
+ /**
157
+ * Format a single log entry as single-line JSON
158
+ */
159
+ function formatLogEntry(entry) {
160
+ return JSON.stringify(entry);
161
+ }
162
+ /**
163
+ * Filter log entries by level
164
+ * When filtering by a specific level, shows that level and all more severe levels above it
165
+ * - error: shows only error
166
+ * - warn: shows error and warn
167
+ * - info: shows error, warn, and info
168
+ * - debug: shows error, warn, info, and debug
169
+ * - all: shows everything (no filtering)
170
+ */
171
+ function filterByLevel(entries, level) {
172
+ if (level === 'all') {
173
+ return entries;
174
+ }
175
+ const levelUpper = level.toUpperCase();
176
+ // Define level hierarchy: error(0) is most severe, debug(3) is most verbose
177
+ const levelHierarchy = {
178
+ 'ERROR': 0,
179
+ 'WARN': 1,
180
+ 'INFO': 2,
181
+ 'DEBUG': 3
182
+ };
183
+ const targetLevel = levelHierarchy[levelUpper];
184
+ if (targetLevel === undefined) {
185
+ // Unknown level, show all
186
+ return entries;
187
+ }
188
+ return entries.filter(entry => {
189
+ const entryLevel = entry.level?.toUpperCase() || '';
190
+ const entryLevelNum = levelHierarchy[entryLevel];
191
+ if (entryLevelNum === undefined) {
192
+ // Unknown entry level, include it
193
+ return true;
194
+ }
195
+ // Include entries at the target level or more severe (lower number)
196
+ // So if filtering for 'info' (2), show error(0), warn(1), and info(2), but not debug(3)
197
+ return entryLevelNum <= targetLevel;
198
+ });
199
+ }
200
+ /**
201
+ * Filter log entries by module(s) - supports comma-separated list
202
+ */
203
+ function filterByModule(entries, module) {
204
+ const modules = module.split(',').map(m => m.trim().toLowerCase()).filter(m => m.length > 0);
205
+ if (modules.length === 0) {
206
+ return entries;
207
+ }
208
+ return entries.filter(entry => {
209
+ const entryModule = entry.module?.toLowerCase() || '';
210
+ return modules.includes(entryModule);
211
+ });
212
+ }
213
+ /**
214
+ * Check if a log entry matches the level filter
215
+ * When filtering by a specific level, shows that level and all more severe levels above it
216
+ */
217
+ function matchesLevel(entry, level) {
218
+ if (level === 'all') {
219
+ return true;
220
+ }
221
+ const levelUpper = level.toUpperCase();
222
+ const levelHierarchy = {
223
+ 'ERROR': 0,
224
+ 'WARN': 1,
225
+ 'INFO': 2,
226
+ 'DEBUG': 3
227
+ };
228
+ const targetLevel = levelHierarchy[levelUpper];
229
+ if (targetLevel === undefined) {
230
+ // Unknown level, include it
231
+ return true;
232
+ }
233
+ const entryLevel = entry.level?.toUpperCase() || '';
234
+ const entryLevelNum = levelHierarchy[entryLevel];
235
+ if (entryLevelNum === undefined) {
236
+ // Unknown entry level, include it
237
+ return true;
238
+ }
239
+ // Include entries at the target level or more severe (lower number)
240
+ return entryLevelNum <= targetLevel;
241
+ }
242
+ /**
243
+ * Check if a log entry matches the module filter(s) - supports comma-separated list
244
+ */
245
+ function matchesModule(entry, module) {
246
+ const modules = module.split(',').map(m => m.trim().toLowerCase()).filter(m => m.length > 0);
247
+ if (modules.length === 0) {
248
+ return true;
249
+ }
250
+ const entryModule = entry.module?.toLowerCase() || '';
251
+ return modules.includes(entryModule);
252
+ }
253
+ /**
254
+ * Parse, filter (if needed), and format journalctl logs
255
+ */
256
+ function processLogs(rawLogs, options = {}) {
257
+ const entries = parseJournalctlOutput(rawLogs);
258
+ let filteredEntries = entries;
259
+ // Filter by level first (from JSON level field)
260
+ if (options.level) {
261
+ filteredEntries = filterByLevel(filteredEntries, options.level);
262
+ }
263
+ // Then filter by module
264
+ if (options.module) {
265
+ filteredEntries = filterByModule(filteredEntries, options.module);
266
+ }
267
+ if (options.colored !== false) {
268
+ return formatLogEntriesColored(filteredEntries, options.singleLine || false);
269
+ }
270
+ return formatLogEntries(filteredEntries);
271
+ }
272
+ /**
273
+ * Process logs line by line (for streaming/follow mode)
274
+ */
275
+ function processLogLine(line, options = {}) {
276
+ const entry = parseJournalctlLine(line);
277
+ if (!entry) {
278
+ return null;
279
+ }
280
+ // Filter by level (from JSON level field)
281
+ if (options.level && !matchesLevel(entry, options.level)) {
282
+ return null;
283
+ }
284
+ // Filter by module
285
+ if (options.module && !matchesModule(entry, options.module)) {
286
+ return null;
287
+ }
288
+ if (options.colored !== false) {
289
+ return formatLogEntryColored(entry, options.singleLine || false);
290
+ }
291
+ return formatLogEntry(entry);
292
+ }
293
+ //# sourceMappingURL=log-formatter.js.map
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * Logger interface for abstracting logging operations
4
+ * Allows for different implementations (console, JSON, file, etc.)
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.LogLevel = void 0;
8
+ exports.parseLogLevel = parseLogLevel;
9
+ exports.getLogLevelName = getLogLevelName;
10
+ var LogLevel;
11
+ (function (LogLevel) {
12
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
13
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
14
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
15
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
16
+ LogLevel[LogLevel["NONE"] = 4] = "NONE";
17
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
18
+ /**
19
+ * Get log level from string
20
+ */
21
+ function parseLogLevel(level) {
22
+ const upper = level.toUpperCase();
23
+ switch (upper) {
24
+ case 'DEBUG':
25
+ return LogLevel.DEBUG;
26
+ case 'INFO':
27
+ return LogLevel.INFO;
28
+ case 'WARN':
29
+ case 'WARNING':
30
+ return LogLevel.WARN;
31
+ case 'ERROR':
32
+ return LogLevel.ERROR;
33
+ case 'NONE':
34
+ case 'SILENT':
35
+ return LogLevel.NONE;
36
+ default:
37
+ return LogLevel.INFO;
38
+ }
39
+ }
40
+ /**
41
+ * Get log level name
42
+ */
43
+ function getLogLevelName(level) {
44
+ switch (level) {
45
+ case LogLevel.DEBUG:
46
+ return 'DEBUG';
47
+ case LogLevel.INFO:
48
+ return 'INFO';
49
+ case LogLevel.WARN:
50
+ return 'WARN';
51
+ case LogLevel.ERROR:
52
+ return 'ERROR';
53
+ case LogLevel.NONE:
54
+ return 'NONE';
55
+ default:
56
+ return 'INFO';
57
+ }
58
+ }
59
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.NetworkUtils = void 0;
37
+ const net = __importStar(require("net"));
38
+ const dns = __importStar(require("dns"));
39
+ const util_1 = require("util");
40
+ const dnsLookup = (0, util_1.promisify)(dns.lookup);
41
+ class NetworkUtils {
42
+ /**
43
+ * Test TCP port connectivity
44
+ */
45
+ static async testTcpPort(host, port, timeout = 5000) {
46
+ return new Promise((resolve) => {
47
+ const startTime = Date.now();
48
+ const socket = new net.Socket();
49
+ const cleanup = () => {
50
+ socket.destroy();
51
+ };
52
+ const timer = setTimeout(() => {
53
+ cleanup();
54
+ resolve({
55
+ success: false,
56
+ error: 'Connection timeout'
57
+ });
58
+ }, timeout);
59
+ socket.connect(port, host, () => {
60
+ const latency = Date.now() - startTime;
61
+ cleanup();
62
+ clearTimeout(timer);
63
+ resolve({
64
+ success: true,
65
+ latency
66
+ });
67
+ });
68
+ socket.on('error', (err) => {
69
+ cleanup();
70
+ clearTimeout(timer);
71
+ resolve({
72
+ success: false,
73
+ error: err.message
74
+ });
75
+ });
76
+ });
77
+ }
78
+ /**
79
+ * Test UDP port connectivity (basic check)
80
+ */
81
+ static async testUdpPort(host, port, timeout = 5000) {
82
+ return new Promise((resolve) => {
83
+ const startTime = Date.now();
84
+ const dgram = require('dgram');
85
+ const socket = dgram.createSocket('udp4');
86
+ const cleanup = () => {
87
+ socket.close();
88
+ };
89
+ const timer = setTimeout(() => {
90
+ cleanup();
91
+ resolve({
92
+ success: false,
93
+ error: 'UDP connection timeout'
94
+ });
95
+ }, timeout);
96
+ socket.send('ping', port, host, (err) => {
97
+ if (err) {
98
+ cleanup();
99
+ clearTimeout(timer);
100
+ resolve({
101
+ success: false,
102
+ error: err.message
103
+ });
104
+ return;
105
+ }
106
+ const latency = Date.now() - startTime;
107
+ cleanup();
108
+ clearTimeout(timer);
109
+ resolve({
110
+ success: true,
111
+ latency
112
+ });
113
+ });
114
+ });
115
+ }
116
+ /**
117
+ * Resolve hostname to IP address
118
+ */
119
+ static async resolveHostname(hostname) {
120
+ try {
121
+ const result = await dnsLookup(hostname);
122
+ return {
123
+ success: true,
124
+ ip: result.address
125
+ };
126
+ }
127
+ catch (error) {
128
+ return {
129
+ success: false,
130
+ error: error instanceof Error ? error.message : 'DNS resolution failed'
131
+ };
132
+ }
133
+ }
134
+ /**
135
+ * Check if a port is available locally
136
+ */
137
+ static async isPortAvailable(port, host = 'localhost') {
138
+ return new Promise((resolve) => {
139
+ const server = net.createServer();
140
+ server.listen(port, host, () => {
141
+ server.once('close', () => {
142
+ resolve(true);
143
+ });
144
+ server.close();
145
+ });
146
+ server.on('error', () => {
147
+ resolve(false);
148
+ });
149
+ });
150
+ }
151
+ /**
152
+ * Get local IP addresses
153
+ */
154
+ static getLocalIPs() {
155
+ const interfaces = require('os').networkInterfaces();
156
+ const ips = [];
157
+ for (const name of Object.keys(interfaces)) {
158
+ for (const iface of interfaces[name]) {
159
+ if (iface.family === 'IPv4' && !iface.internal) {
160
+ ips.push(iface.address);
161
+ }
162
+ }
163
+ }
164
+ return ips;
165
+ }
166
+ /**
167
+ * Format network error messages for user-friendly display
168
+ */
169
+ static formatNetworkError(error) {
170
+ if (error.includes('ECONNREFUSED')) {
171
+ return 'Connection refused - the service is not running or not accepting connections';
172
+ }
173
+ if (error.includes('ETIMEDOUT')) {
174
+ return 'Connection timeout - the service is not responding';
175
+ }
176
+ if (error.includes('ENOTFOUND')) {
177
+ return 'Host not found - check the hostname or IP address';
178
+ }
179
+ if (error.includes('EADDRNOTAVAIL')) {
180
+ return 'Address not available - check the IP address';
181
+ }
182
+ if (error.includes('EACCES')) {
183
+ return 'Permission denied - check firewall settings';
184
+ }
185
+ return error;
186
+ }
187
+ /**
188
+ * Validate IP address format
189
+ */
190
+ static isValidIP(ip) {
191
+ const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
192
+ const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
193
+ return ipv4Regex.test(ip) || ipv6Regex.test(ip);
194
+ }
195
+ /**
196
+ * Validate port number
197
+ */
198
+ static isValidPort(port) {
199
+ return Number.isInteger(port) && port > 0 && port <= 65535;
200
+ }
201
+ /**
202
+ * Generate network diagnostic information
203
+ */
204
+ static async generateNetworkDiagnostics(host, port) {
205
+ const dnsResult = await this.resolveHostname(host);
206
+ const tcpResult = await this.testTcpPort(host, port);
207
+ const localIPs = this.getLocalIPs();
208
+ return {
209
+ dnsResolution: dnsResult.success,
210
+ portConnectivity: tcpResult.success,
211
+ localIPs,
212
+ error: tcpResult.error
213
+ };
214
+ }
215
+ }
216
+ exports.NetworkUtils = NetworkUtils;
217
+ //# sourceMappingURL=network-utils.js.map