voidct 1.0.0
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.
- package/README.md +99 -0
- package/bun.lock +41 -0
- package/package.json +39 -0
- package/src/config.ts +131 -0
- package/src/handlers.ts +357 -0
- package/src/hub/auth.ts +18 -0
- package/src/hub/config.ts +42 -0
- package/src/hub/index.ts +137 -0
- package/src/hub/logger.ts +53 -0
- package/src/hub/process_manager.ts +62 -0
- package/src/hub/tunnel.ts +46 -0
- package/src/index.ts +312 -0
- package/src/utils.ts +112 -0
- package/tsconfig.json +30 -0
package/src/utils.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { existsSync, readFileSync, unlinkSync } from 'fs';
|
|
2
|
+
import { createServer } from 'net';
|
|
3
|
+
import { getPidPath, getStatePath } from './config';
|
|
4
|
+
|
|
5
|
+
export function isPortAvailable(port: number): Promise<boolean> {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
const server = createServer();
|
|
8
|
+
server.once('error', () => {
|
|
9
|
+
resolve(false);
|
|
10
|
+
});
|
|
11
|
+
server.once('listening', () => {
|
|
12
|
+
server.close();
|
|
13
|
+
resolve(true);
|
|
14
|
+
});
|
|
15
|
+
server.listen(port, '127.0.0.1');
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function findAvailablePort(startPort: number): Promise<number> {
|
|
20
|
+
let port = startPort;
|
|
21
|
+
while (port < 65535) {
|
|
22
|
+
if (await isPortAvailable(port)) {
|
|
23
|
+
return port;
|
|
24
|
+
}
|
|
25
|
+
port++;
|
|
26
|
+
}
|
|
27
|
+
throw new Error('No available ports found');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isServerRunning(): { running: boolean; pid: number | null } {
|
|
31
|
+
const pidPath = getPidPath();
|
|
32
|
+
if (!existsSync(pidPath)) {
|
|
33
|
+
return { running: false, pid: null };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const content = readFileSync(pidPath, 'utf-8');
|
|
38
|
+
const pid = parseInt(content.trim(), 10);
|
|
39
|
+
|
|
40
|
+
// Check if process is running
|
|
41
|
+
try {
|
|
42
|
+
process.kill(pid, 0); // Signal 0 checks if process exists
|
|
43
|
+
return { running: true, pid };
|
|
44
|
+
} catch {
|
|
45
|
+
// Process not running, clean up stale PID file
|
|
46
|
+
unlinkSync(pidPath);
|
|
47
|
+
return { running: false, pid: null };
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
return { running: false, pid: null };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function killServer(pid: number): boolean {
|
|
55
|
+
try {
|
|
56
|
+
process.kill(pid, 'SIGTERM');
|
|
57
|
+
return true;
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function cleanupServerFiles(): void {
|
|
64
|
+
const pidPath = getPidPath();
|
|
65
|
+
const statePath = getStatePath();
|
|
66
|
+
|
|
67
|
+
try { unlinkSync(pidPath); } catch { }
|
|
68
|
+
try { unlinkSync(statePath); } catch { }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function checkForUpdates(currentVersion: string): Promise<{ hasUpdate: boolean; version?: string; url?: string }> {
|
|
72
|
+
try {
|
|
73
|
+
const response = await fetch('https://api.github.com/repos/xptea/voidconnect-cli/releases/latest', {
|
|
74
|
+
headers: {
|
|
75
|
+
'User-Agent': 'voidconnect-cli-update-checker'
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
return { hasUpdate: false };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const data = await response.json() as { tag_name: string; html_url: string };
|
|
84
|
+
const remoteVersion = data.tag_name.replace(/^v/i, '');
|
|
85
|
+
|
|
86
|
+
if (isNewerVersion(remoteVersion, currentVersion)) {
|
|
87
|
+
return {
|
|
88
|
+
hasUpdate: true,
|
|
89
|
+
version: remoteVersion,
|
|
90
|
+
url: data.html_url
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return { hasUpdate: false };
|
|
95
|
+
} catch {
|
|
96
|
+
return { hasUpdate: false };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function isNewerVersion(remote: string, local: string): boolean {
|
|
101
|
+
const parse = (v: string) => v.split('.').map(s => parseInt(s, 10) || 0);
|
|
102
|
+
const rParts = parse(remote);
|
|
103
|
+
const lParts = parse(local);
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < Math.max(rParts.length, lParts.length); i++) {
|
|
106
|
+
const r = rParts[i] || 0;
|
|
107
|
+
const l = lParts[i] || 0;
|
|
108
|
+
if (r > l) return true;
|
|
109
|
+
if (r < l) return false;
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"jsxImportSource": "@opentui/react",
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
|
|
12
|
+
// Bundler mode
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"allowImportingTsExtensions": true,
|
|
15
|
+
"verbatimModuleSyntax": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
|
|
18
|
+
// Best practices
|
|
19
|
+
"strict": true,
|
|
20
|
+
"skipLibCheck": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
"noUncheckedIndexedAccess": true,
|
|
23
|
+
"noImplicitOverride": true,
|
|
24
|
+
|
|
25
|
+
// Some stricter flags (disabled by default)
|
|
26
|
+
"noUnusedLocals": false,
|
|
27
|
+
"noUnusedParameters": false,
|
|
28
|
+
"noPropertyAccessFromIndexSignature": false
|
|
29
|
+
}
|
|
30
|
+
}
|