@seflless/ghosttown 1.6.0 → 1.6.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.
- package/package.json +1 -1
- package/src/cli.js +65 -27
- package/src/cli.test.ts +75 -0
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -512,8 +512,8 @@ function getNextDisplayNumber() {
|
|
|
512
512
|
}
|
|
513
513
|
|
|
514
514
|
/**
|
|
515
|
-
* Check if the background server is running and get its port
|
|
516
|
-
* @returns {{ running: boolean, port: number | null }}
|
|
515
|
+
* Check if the background server is running and get its port and protocol
|
|
516
|
+
* @returns {{ running: boolean, port: number | null, useHttp: boolean }}
|
|
517
517
|
*/
|
|
518
518
|
function getServerStatus() {
|
|
519
519
|
try {
|
|
@@ -525,22 +525,42 @@ function getServerStatus() {
|
|
|
525
525
|
const isRunning = output.split('\n').includes(SERVER_SESSION_NAME);
|
|
526
526
|
|
|
527
527
|
if (!isRunning) {
|
|
528
|
-
return { running: false, port: null };
|
|
528
|
+
return { running: false, port: null, useHttp: false };
|
|
529
529
|
}
|
|
530
530
|
|
|
531
531
|
// Get the port from tmux environment
|
|
532
|
+
let port = 8080;
|
|
532
533
|
try {
|
|
533
534
|
const envOutput = execSync(`tmux show-environment -t ${SERVER_SESSION_NAME} GHOSTTOWN_PORT`, {
|
|
534
535
|
encoding: 'utf8',
|
|
535
536
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
536
537
|
});
|
|
537
|
-
const
|
|
538
|
-
|
|
538
|
+
const parsedPort = Number.parseInt(envOutput.split('=')[1], 10);
|
|
539
|
+
if (!Number.isNaN(parsedPort)) {
|
|
540
|
+
port = parsedPort;
|
|
541
|
+
}
|
|
539
542
|
} catch (e) {
|
|
540
|
-
|
|
543
|
+
// Use default port
|
|
541
544
|
}
|
|
545
|
+
|
|
546
|
+
// Get the protocol from tmux environment (default to HTTPS if not set)
|
|
547
|
+
let useHttp = false;
|
|
548
|
+
try {
|
|
549
|
+
const envOutput = execSync(
|
|
550
|
+
`tmux show-environment -t ${SERVER_SESSION_NAME} GHOSTTOWN_USE_HTTP`,
|
|
551
|
+
{
|
|
552
|
+
encoding: 'utf8',
|
|
553
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
useHttp = envOutput.split('=')[1]?.trim() === '1';
|
|
557
|
+
} catch (e) {
|
|
558
|
+
// Use default (HTTPS)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return { running: true, port, useHttp };
|
|
542
562
|
} catch (err) {
|
|
543
|
-
return { running: false, port: null };
|
|
563
|
+
return { running: false, port: null, useHttp: false };
|
|
544
564
|
}
|
|
545
565
|
}
|
|
546
566
|
|
|
@@ -1083,8 +1103,9 @@ function killAllSessions() {
|
|
|
1083
1103
|
/**
|
|
1084
1104
|
* Start the server in the background using a tmux session
|
|
1085
1105
|
* @param {number} port - Port to listen on
|
|
1106
|
+
* @param {boolean} useHttp - Use HTTP instead of HTTPS (default: false, meaning HTTPS is used)
|
|
1086
1107
|
*/
|
|
1087
|
-
function startServerInBackground(port = 8080) {
|
|
1108
|
+
function startServerInBackground(port = 8080, useHttp = false) {
|
|
1088
1109
|
// Check if tmux is installed
|
|
1089
1110
|
if (!checkTmuxInstalled()) {
|
|
1090
1111
|
printTmuxInstallHelp();
|
|
@@ -1141,24 +1162,34 @@ function startServerInBackground(port = 8080) {
|
|
|
1141
1162
|
stdio: 'pipe',
|
|
1142
1163
|
});
|
|
1143
1164
|
|
|
1165
|
+
// Set the protocol environment variable in the tmux session
|
|
1166
|
+
execSync(
|
|
1167
|
+
`tmux set-environment -t ${SERVER_SESSION_NAME} GHOSTTOWN_USE_HTTP ${useHttp ? '1' : '0'}`,
|
|
1168
|
+
{
|
|
1169
|
+
stdio: 'pipe',
|
|
1170
|
+
}
|
|
1171
|
+
);
|
|
1172
|
+
|
|
1144
1173
|
// Disable status bar for cleaner look
|
|
1145
1174
|
execSync(`tmux set-option -t ${SERVER_SESSION_NAME} status off`, { stdio: 'pipe' });
|
|
1146
1175
|
|
|
1147
|
-
// Run the server with background mode flag
|
|
1176
|
+
// Run the server with background mode flag (add --http if needed)
|
|
1177
|
+
const httpFlag = useHttp ? ' --http' : '';
|
|
1148
1178
|
execSync(
|
|
1149
|
-
`tmux send-keys -t ${SERVER_SESSION_NAME} 'node "${gtPath}" --server-background -p ${port}' Enter`,
|
|
1179
|
+
`tmux send-keys -t ${SERVER_SESSION_NAME} 'node "${gtPath}" --server-background -p ${port}${httpFlag}' Enter`,
|
|
1150
1180
|
{ stdio: 'pipe' }
|
|
1151
1181
|
);
|
|
1152
1182
|
|
|
1153
1183
|
// Get local IPs for display
|
|
1154
1184
|
const localIPs = getLocalIPs();
|
|
1185
|
+
const protocol = useHttp ? 'http' : 'https';
|
|
1155
1186
|
|
|
1156
1187
|
console.log('');
|
|
1157
1188
|
console.log(` ${BOLD_YELLOW}Ghosttown server started!${RESET}`);
|
|
1158
1189
|
console.log('');
|
|
1159
|
-
console.log(` ${CYAN}Open:${RESET} ${BEIGE}
|
|
1190
|
+
console.log(` ${CYAN}Open:${RESET} ${BEIGE}${protocol}://localhost:${port}${RESET}`);
|
|
1160
1191
|
if (localIPs.length > 0) {
|
|
1161
|
-
console.log(` ${CYAN}Network:${RESET} ${BEIGE}
|
|
1192
|
+
console.log(` ${CYAN}Network:${RESET} ${BEIGE}${protocol}://${localIPs[0]}:${port}${RESET}`);
|
|
1162
1193
|
}
|
|
1163
1194
|
console.log('');
|
|
1164
1195
|
console.log(` ${CYAN}To stop:${RESET} ${BEIGE}gt stop${RESET}`);
|
|
@@ -1238,12 +1269,13 @@ function showServerStatus() {
|
|
|
1238
1269
|
if (status.running) {
|
|
1239
1270
|
const localIPs = getLocalIPs();
|
|
1240
1271
|
const port = status.port || 8080;
|
|
1272
|
+
const protocol = status.useHttp ? 'http' : 'https';
|
|
1241
1273
|
|
|
1242
1274
|
console.log(` ${GREEN}Server is running${RESET}`);
|
|
1243
1275
|
console.log('');
|
|
1244
|
-
console.log(` ${CYAN}Open:${RESET} ${BEIGE}
|
|
1276
|
+
console.log(` ${CYAN}Open:${RESET} ${BEIGE}${protocol}://localhost:${port}${RESET}`);
|
|
1245
1277
|
if (localIPs.length > 0) {
|
|
1246
|
-
console.log(` ${CYAN}Network:${RESET} ${BEIGE}
|
|
1278
|
+
console.log(` ${CYAN}Network:${RESET} ${BEIGE}${protocol}://${localIPs[0]}:${port}${RESET}`);
|
|
1247
1279
|
}
|
|
1248
1280
|
console.log('');
|
|
1249
1281
|
console.log(` ${DIM}To stop: gt stop${RESET}`);
|
|
@@ -1496,15 +1528,13 @@ Examples:
|
|
|
1496
1528
|
Aliases:
|
|
1497
1529
|
This CLI can also be invoked as 'gt' or 'ght'.
|
|
1498
1530
|
`);
|
|
1499
|
-
|
|
1500
|
-
break;
|
|
1531
|
+
process.exit(0);
|
|
1501
1532
|
}
|
|
1502
1533
|
|
|
1503
1534
|
// Handle version flag
|
|
1504
1535
|
if (arg === '-v' || arg === '--version') {
|
|
1505
1536
|
console.log(VERSION);
|
|
1506
|
-
|
|
1507
|
-
break;
|
|
1537
|
+
process.exit(0);
|
|
1508
1538
|
}
|
|
1509
1539
|
|
|
1510
1540
|
// Handle list command
|
|
@@ -1569,20 +1599,28 @@ Aliases:
|
|
|
1569
1599
|
|
|
1570
1600
|
// Handle start command
|
|
1571
1601
|
else if (arg === 'start') {
|
|
1572
|
-
//
|
|
1602
|
+
// Parse remaining args after 'start' for -p and --http flags
|
|
1573
1603
|
let startPort = 8080;
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1604
|
+
let startUseHttp = false;
|
|
1605
|
+
const remainingArgs = args.slice(i + 1);
|
|
1606
|
+
for (let j = 0; j < remainingArgs.length; j++) {
|
|
1607
|
+
const subArg = remainingArgs[j];
|
|
1608
|
+
if (subArg === '-p' || subArg === '--port') {
|
|
1609
|
+
const portArg = remainingArgs[j + 1];
|
|
1610
|
+
if (portArg) {
|
|
1611
|
+
startPort = Number.parseInt(portArg, 10);
|
|
1612
|
+
if (Number.isNaN(startPort) || startPort < 1 || startPort > 65535) {
|
|
1613
|
+
console.error(`Error: Invalid port number: ${portArg}`);
|
|
1614
|
+
process.exit(1);
|
|
1615
|
+
}
|
|
1581
1616
|
}
|
|
1617
|
+
j++; // Skip the port value
|
|
1618
|
+
} else if (subArg === '--http') {
|
|
1619
|
+
startUseHttp = true;
|
|
1582
1620
|
}
|
|
1583
1621
|
}
|
|
1584
1622
|
handled = true;
|
|
1585
|
-
startServerInBackground(startPort);
|
|
1623
|
+
startServerInBackground(startPort, startUseHttp);
|
|
1586
1624
|
// startServerInBackground exits, so this won't be reached
|
|
1587
1625
|
}
|
|
1588
1626
|
|
package/src/cli.test.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for the ghosttown CLI command-line interface.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, expect, test } from 'bun:test';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __dirname = join(fileURLToPath(import.meta.url), '..');
|
|
13
|
+
const CLI_PATH = join(__dirname, '..', 'bin', 'gt.js');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Run the CLI with given arguments and return stdout/stderr/exit code
|
|
17
|
+
*/
|
|
18
|
+
function runCli(args: string[]): Promise<{ stdout: string; stderr: string; code: number }> {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const proc = spawn('node', [CLI_PATH, ...args], {
|
|
21
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
let stdout = '';
|
|
25
|
+
let stderr = '';
|
|
26
|
+
|
|
27
|
+
proc.stdout.on('data', (data) => {
|
|
28
|
+
stdout += data.toString();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
proc.stderr.on('data', (data) => {
|
|
32
|
+
stderr += data.toString();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
proc.on('close', (code) => {
|
|
36
|
+
resolve({ stdout, stderr, code: code ?? 1 });
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('CLI', () => {
|
|
42
|
+
describe('version flag', () => {
|
|
43
|
+
test('-v should print version and exit', async () => {
|
|
44
|
+
const result = await runCli(['-v']);
|
|
45
|
+
expect(result.code).toBe(0);
|
|
46
|
+
expect(result.stdout.trim()).toMatch(/^\d+\.\d+\.\d+$/);
|
|
47
|
+
expect(result.stderr).toBe('');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('--version should print version and exit', async () => {
|
|
51
|
+
const result = await runCli(['--version']);
|
|
52
|
+
expect(result.code).toBe(0);
|
|
53
|
+
expect(result.stdout.trim()).toMatch(/^\d+\.\d+\.\d+$/);
|
|
54
|
+
expect(result.stderr).toBe('');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('help flag', () => {
|
|
59
|
+
test('-h should print help and exit', async () => {
|
|
60
|
+
const result = await runCli(['-h']);
|
|
61
|
+
expect(result.code).toBe(0);
|
|
62
|
+
expect(result.stdout).toContain('Usage: ghosttown');
|
|
63
|
+
expect(result.stdout).toContain('--version');
|
|
64
|
+
expect(result.stdout).toContain('--help');
|
|
65
|
+
expect(result.stderr).toBe('');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('--help should print help and exit', async () => {
|
|
69
|
+
const result = await runCli(['--help']);
|
|
70
|
+
expect(result.code).toBe(0);
|
|
71
|
+
expect(result.stdout).toContain('Usage: ghosttown');
|
|
72
|
+
expect(result.stderr).toBe('');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|