@studiometa/forge-cli 0.4.3 → 0.4.5
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 +14 -0
- package/dist/cli.js +349 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/deployments/handlers.d.ts.map +1 -1
- package/dist/commands/ssh/command.d.ts +9 -0
- package/dist/commands/ssh/command.d.ts.map +1 -0
- package/dist/commands/ssh/handlers.d.ts +16 -0
- package/dist/commands/ssh/handlers.d.ts.map +1 -0
- package/dist/commands/ssh/help.d.ts +2 -0
- package/dist/commands/ssh/help.d.ts.map +1 -0
- package/dist/commands/ssh/index.d.ts +3 -0
- package/dist/commands/ssh/index.d.ts.map +1 -0
- package/dist/commands/ssh/ssh-target.d.ts +36 -0
- package/dist/commands/ssh/ssh-target.d.ts.map +1 -0
- package/dist/{error-handler-ByMitiOr.js → error-handler-peS_8nl4.js} +23 -3
- package/dist/error-handler-peS_8nl4.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/output.d.ts +0 -4
- package/dist/output.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/error-handler-ByMitiOr.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { S as isOutputFormat, a as createContext, b as ValidationError, c as colors, d as deleteToken, g as setToken, h as setOrganizationSlug, i as runCommand, l as setColorEnabled, m as getToken, n as exitWithValidationError, p as getOrganizationSlug, s as OutputFormatter, u as createConfigStore } from "./error-handler-
|
|
2
|
+
import { S as isOutputFormat, _ as ApiError, a as createContext, b as ValidationError, c as colors, d as deleteToken, g as setToken, h as setOrganizationSlug, i as runCommand, l as setColorEnabled, m as getToken, n as exitWithValidationError, p as getOrganizationSlug, s as OutputFormatter, u as createConfigStore } from "./error-handler-peS_8nl4.js";
|
|
3
3
|
import { activateCertificate, createAuditLogger, createBackupConfig, createCommand, createDatabaseUser, createMonitor, createNginxTemplate, createRedirectRule, createScheduledJob, createSecurityRule, deleteBackupConfig, deleteDatabaseUser, deleteMonitor, deleteNginxTemplate, deleteRedirectRule, deleteScheduledJob, deleteSecurityRule, deploySiteAndWait, getBackupConfig, getCertificate, getCommand, getDaemon, getDatabase, getDatabaseUser, getEnv, getFirewallRule, getMonitor, getNginxConfig, getNginxTemplate, getRecipe, getRedirectRule, getScheduledJob, getSecurityRule, getServer, getSite, getSshKey, getUser, listBackupConfigs, listCommands, listDaemons, listDatabaseUsers, listDatabases, listDeployments, listFirewallRules, listMonitors, listNginxTemplates, listRecipes, listRedirectRules, listScheduledJobs, listSecurityRules, listServers, listSites, listSshKeys, matchByName, rebootServer, restartDaemon, runRecipe, updateBackupConfig, updateDaemon, updateDatabaseUser, updateEnv, updateNginxConfig, updateNginxTemplate, updateRecipe, updateSecurityRule, updateSite } from "@studiometa/forge-core";
|
|
4
4
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
//#region src/audit.ts
|
|
7
9
|
/**
|
|
8
10
|
* Shared audit logger for CLI write operations.
|
|
9
11
|
* Lazily initialized on first use.
|
|
@@ -13,6 +15,8 @@ function getCliAuditLogger() {
|
|
|
13
15
|
if (!_auditLogger) _auditLogger = createAuditLogger("cli");
|
|
14
16
|
return _auditLogger;
|
|
15
17
|
}
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/utils/command-router.ts
|
|
16
20
|
/**
|
|
17
21
|
* Creates a command router function that dispatches to the appropriate handler.
|
|
18
22
|
*/
|
|
@@ -55,6 +59,8 @@ function createCommandRouter(config) {
|
|
|
55
59
|
else await handler(ctx);
|
|
56
60
|
};
|
|
57
61
|
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/utils/resolve.ts
|
|
58
64
|
/**
|
|
59
65
|
* Smart resolution utilities for --server and --site options.
|
|
60
66
|
*
|
|
@@ -106,6 +112,8 @@ async function resolveSiteId(value, serverId, execCtx) {
|
|
|
106
112
|
}
|
|
107
113
|
return String(partial[0].id);
|
|
108
114
|
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/commands/backups/handlers.ts
|
|
109
117
|
async function backupsList(ctx) {
|
|
110
118
|
const server = String(ctx.options.server ?? "");
|
|
111
119
|
if (!server) exitWithValidationError("server_id", "forge backups list --server <server_id>", ctx.formatter);
|
|
@@ -216,7 +224,9 @@ async function backupsDelete(args, ctx) {
|
|
|
216
224
|
ctx.formatter.success(`Backup configuration ${id} deleted.`);
|
|
217
225
|
}, ctx.formatter);
|
|
218
226
|
}
|
|
219
|
-
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/commands/backups/command.ts
|
|
229
|
+
var handleBackupsCommand = createCommandRouter({
|
|
220
230
|
resource: "backups",
|
|
221
231
|
handlers: {
|
|
222
232
|
list: backupsList,
|
|
@@ -232,6 +242,8 @@ const handleBackupsCommand = createCommandRouter({
|
|
|
232
242
|
"delete"
|
|
233
243
|
]
|
|
234
244
|
});
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/commands/backups/help.ts
|
|
235
247
|
function showBackupsHelp(subcommand) {
|
|
236
248
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
237
249
|
${colors.bold("forge backups list")} - List backup configurations on a server
|
|
@@ -309,6 +321,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
309
321
|
Run ${colors.cyan("forge backups <subcommand> --help")} for details.
|
|
310
322
|
`);
|
|
311
323
|
}
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/commands/completion.ts
|
|
312
326
|
/**
|
|
313
327
|
* Shell completion installation command
|
|
314
328
|
*/
|
|
@@ -322,7 +336,7 @@ _forge_completions() {
|
|
|
322
336
|
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
323
337
|
|
|
324
338
|
# Main commands
|
|
325
|
-
commands="config servers s sites deployments d databases db database-users daemons env nginx certificates certs firewall-rules fw ssh-keys backups commands scheduled-jobs user monitors nginx-templates security-rules redirect-rules recipes completion help"
|
|
339
|
+
commands="config servers s sites deployments d databases db database-users daemons env nginx certificates certs firewall-rules fw ssh ssh-keys backups commands scheduled-jobs user monitors nginx-templates security-rules redirect-rules recipes completion help"
|
|
326
340
|
|
|
327
341
|
# Subcommands for each command
|
|
328
342
|
local config_cmds="set get delete"
|
|
@@ -349,7 +363,7 @@ _forge_completions() {
|
|
|
349
363
|
local completion_cmds="bash zsh fish"
|
|
350
364
|
|
|
351
365
|
# Global options
|
|
352
|
-
options="--token --server --site -f --format --no-color -h --help -v --version --name --command --content --from --to --provider --frequency --type --operator --threshold --minutes --key --port --ip-address --user --script --servers --domain --password --credential-id --region --size --project-type --directory"
|
|
366
|
+
options="--token --server --site -f --format --no-color -h --help -v --version --name --command --content --from --to --provider --frequency --type --operator --threshold --minutes --key --port --ip-address --user --private --dry-run --script --servers --domain --password --credential-id --region --size --project-type --directory"
|
|
353
367
|
|
|
354
368
|
# Format options
|
|
355
369
|
local formats="json human table"
|
|
@@ -486,6 +500,7 @@ _forge() {
|
|
|
486
500
|
'certs:Manage SSL certificates (alias)'
|
|
487
501
|
'firewall-rules:Manage firewall rules'
|
|
488
502
|
'fw:Manage firewall rules (alias)'
|
|
503
|
+
'ssh:Open an SSH session to a server'
|
|
489
504
|
'ssh-keys:Manage SSH keys'
|
|
490
505
|
'backups:Manage backup configurations'
|
|
491
506
|
'commands:Manage site commands'
|
|
@@ -775,6 +790,7 @@ complete -c forge -f -n "__fish_use_subcommand" -a "certificates" -d "Manage SSL
|
|
|
775
790
|
complete -c forge -f -n "__fish_use_subcommand" -a "certs" -d "Manage SSL certificates (alias)"
|
|
776
791
|
complete -c forge -f -n "__fish_use_subcommand" -a "firewall-rules" -d "Manage firewall rules"
|
|
777
792
|
complete -c forge -f -n "__fish_use_subcommand" -a "fw" -d "Manage firewall rules (alias)"
|
|
793
|
+
complete -c forge -f -n "__fish_use_subcommand" -a "ssh" -d "Open an SSH session to a server"
|
|
778
794
|
complete -c forge -f -n "__fish_use_subcommand" -a "ssh-keys" -d "Manage SSH keys"
|
|
779
795
|
complete -c forge -f -n "__fish_use_subcommand" -a "backups" -d "Manage backup configurations"
|
|
780
796
|
complete -c forge -f -n "__fish_use_subcommand" -a "commands" -d "Manage site commands"
|
|
@@ -1053,6 +1069,8 @@ function handleCompletionCommand(shell, options = {}) {
|
|
|
1053
1069
|
process.exit(1);
|
|
1054
1070
|
}
|
|
1055
1071
|
}
|
|
1072
|
+
//#endregion
|
|
1073
|
+
//#region src/commands/certificates/handlers.ts
|
|
1056
1074
|
function requireServerSiteDomainRaw(ctx, usage) {
|
|
1057
1075
|
const server = String(ctx.options.server ?? "");
|
|
1058
1076
|
const site = String(ctx.options.site ?? "");
|
|
@@ -1104,7 +1122,9 @@ async function certificatesActivate(args, ctx) {
|
|
|
1104
1122
|
ctx.formatter.success(`Certificate for domain ${domainId} activated.`);
|
|
1105
1123
|
}, ctx.formatter);
|
|
1106
1124
|
}
|
|
1107
|
-
|
|
1125
|
+
//#endregion
|
|
1126
|
+
//#region src/commands/certificates/command.ts
|
|
1127
|
+
var handleCertificatesCommand = createCommandRouter({
|
|
1108
1128
|
resource: "certificates",
|
|
1109
1129
|
handlers: {
|
|
1110
1130
|
get: [certificatesGet, "args"],
|
|
@@ -1112,6 +1132,8 @@ const handleCertificatesCommand = createCommandRouter({
|
|
|
1112
1132
|
},
|
|
1113
1133
|
writeSubcommands: ["activate"]
|
|
1114
1134
|
});
|
|
1135
|
+
//#endregion
|
|
1136
|
+
//#region src/commands/certificates/help.ts
|
|
1115
1137
|
function showCertificatesHelp(subcommand) {
|
|
1116
1138
|
if (subcommand === "get") console.log(`
|
|
1117
1139
|
${colors.bold("forge certificates get")} - Get certificate for a domain
|
|
@@ -1150,6 +1172,8 @@ ${colors.bold("NOTE:")}
|
|
|
1150
1172
|
Run ${colors.cyan("forge certificates <subcommand> --help")} for details.
|
|
1151
1173
|
`);
|
|
1152
1174
|
}
|
|
1175
|
+
//#endregion
|
|
1176
|
+
//#region src/commands/commands/handlers.ts
|
|
1153
1177
|
function requireServerAndSiteRaw$2(ctx, usage) {
|
|
1154
1178
|
const server = String(ctx.options.server ?? "");
|
|
1155
1179
|
const site = String(ctx.options.site ?? "");
|
|
@@ -1219,7 +1243,9 @@ async function commandsCreate(ctx) {
|
|
|
1219
1243
|
ctx.formatter.success("Command queued for execution.");
|
|
1220
1244
|
}, ctx.formatter);
|
|
1221
1245
|
}
|
|
1222
|
-
|
|
1246
|
+
//#endregion
|
|
1247
|
+
//#region src/commands/commands/command.ts
|
|
1248
|
+
var handleCommandsCommand = createCommandRouter({
|
|
1223
1249
|
resource: "commands",
|
|
1224
1250
|
handlers: {
|
|
1225
1251
|
list: commandsList,
|
|
@@ -1229,6 +1255,8 @@ const handleCommandsCommand = createCommandRouter({
|
|
|
1229
1255
|
},
|
|
1230
1256
|
writeSubcommands: ["create"]
|
|
1231
1257
|
});
|
|
1258
|
+
//#endregion
|
|
1259
|
+
//#region src/commands/commands/help.ts
|
|
1232
1260
|
function showCommandsHelp(subcommand) {
|
|
1233
1261
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1234
1262
|
${colors.bold("forge commands list")} - List commands executed on a site
|
|
@@ -1278,6 +1306,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1278
1306
|
Run ${colors.cyan("forge commands <subcommand> --help")} for details.
|
|
1279
1307
|
`);
|
|
1280
1308
|
}
|
|
1309
|
+
//#endregion
|
|
1310
|
+
//#region src/commands/config.ts
|
|
1281
1311
|
/**
|
|
1282
1312
|
* Config command — manage forge configuration
|
|
1283
1313
|
*/
|
|
@@ -1362,6 +1392,8 @@ function handleConfigCommand(subcommand, args, options) {
|
|
|
1362
1392
|
function maskToken(token) {
|
|
1363
1393
|
return token.length > 8 ? `${token.slice(0, 4)}${"*".repeat(token.length - 8)}${token.slice(-4)}` : "****";
|
|
1364
1394
|
}
|
|
1395
|
+
//#endregion
|
|
1396
|
+
//#region src/commands/daemons/handlers.ts
|
|
1365
1397
|
async function daemonsList(ctx) {
|
|
1366
1398
|
const server = String(ctx.options.server ?? "");
|
|
1367
1399
|
if (!server) exitWithValidationError("server_id", "forge daemons list --server <server_id>", ctx.formatter);
|
|
@@ -1443,7 +1475,9 @@ async function daemonsRestart(args, ctx) {
|
|
|
1443
1475
|
ctx.formatter.success(`Daemon ${id} restarted.`);
|
|
1444
1476
|
}, ctx.formatter);
|
|
1445
1477
|
}
|
|
1446
|
-
|
|
1478
|
+
//#endregion
|
|
1479
|
+
//#region src/commands/daemons/command.ts
|
|
1480
|
+
var handleDaemonsCommand = createCommandRouter({
|
|
1447
1481
|
resource: "daemons",
|
|
1448
1482
|
handlers: {
|
|
1449
1483
|
list: daemonsList,
|
|
@@ -1454,6 +1488,8 @@ const handleDaemonsCommand = createCommandRouter({
|
|
|
1454
1488
|
},
|
|
1455
1489
|
writeSubcommands: ["restart", "update"]
|
|
1456
1490
|
});
|
|
1491
|
+
//#endregion
|
|
1492
|
+
//#region src/commands/daemons/help.ts
|
|
1457
1493
|
function showDaemonsHelp(subcommand) {
|
|
1458
1494
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1459
1495
|
${colors.bold("forge daemons list")} - List daemons on a server
|
|
@@ -1498,6 +1534,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1498
1534
|
Run ${colors.cyan("forge daemons <subcommand> --help")} for details.
|
|
1499
1535
|
`);
|
|
1500
1536
|
}
|
|
1537
|
+
//#endregion
|
|
1538
|
+
//#region src/commands/databases/handlers.ts
|
|
1501
1539
|
async function databasesList(ctx) {
|
|
1502
1540
|
const server = String(ctx.options.server ?? "");
|
|
1503
1541
|
if (!server) exitWithValidationError("server_id", "forge databases list --server <server_id>", ctx.formatter);
|
|
@@ -1532,7 +1570,9 @@ async function databasesGet(args, ctx) {
|
|
|
1532
1570
|
]);
|
|
1533
1571
|
}, ctx.formatter);
|
|
1534
1572
|
}
|
|
1535
|
-
|
|
1573
|
+
//#endregion
|
|
1574
|
+
//#region src/commands/databases/command.ts
|
|
1575
|
+
var handleDatabasesCommand = createCommandRouter({
|
|
1536
1576
|
resource: "databases",
|
|
1537
1577
|
handlers: {
|
|
1538
1578
|
list: databasesList,
|
|
@@ -1540,6 +1580,8 @@ const handleDatabasesCommand = createCommandRouter({
|
|
|
1540
1580
|
get: [databasesGet, "args"]
|
|
1541
1581
|
}
|
|
1542
1582
|
});
|
|
1583
|
+
//#endregion
|
|
1584
|
+
//#region src/commands/databases/help.ts
|
|
1543
1585
|
function showDatabasesHelp(subcommand) {
|
|
1544
1586
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1545
1587
|
${colors.bold("forge databases list")} - List databases on a server
|
|
@@ -1577,6 +1619,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1577
1619
|
Run ${colors.cyan("forge databases <subcommand> --help")} for details.
|
|
1578
1620
|
`);
|
|
1579
1621
|
}
|
|
1622
|
+
//#endregion
|
|
1623
|
+
//#region src/commands/database-users/handlers.ts
|
|
1580
1624
|
async function databaseUsersList(ctx) {
|
|
1581
1625
|
const server = String(ctx.options.server ?? "");
|
|
1582
1626
|
if (!server) exitWithValidationError("server_id", "forge database-users list --server <server_id>", ctx.formatter);
|
|
@@ -1677,7 +1721,9 @@ async function databaseUsersDelete(args, ctx) {
|
|
|
1677
1721
|
ctx.formatter.success(`Database user ${id} deleted.`);
|
|
1678
1722
|
}, ctx.formatter);
|
|
1679
1723
|
}
|
|
1680
|
-
|
|
1724
|
+
//#endregion
|
|
1725
|
+
//#region src/commands/database-users/command.ts
|
|
1726
|
+
var handleDatabaseUsersCommand = createCommandRouter({
|
|
1681
1727
|
resource: "database-users",
|
|
1682
1728
|
handlers: {
|
|
1683
1729
|
list: databaseUsersList,
|
|
@@ -1693,6 +1739,8 @@ const handleDatabaseUsersCommand = createCommandRouter({
|
|
|
1693
1739
|
"delete"
|
|
1694
1740
|
]
|
|
1695
1741
|
});
|
|
1742
|
+
//#endregion
|
|
1743
|
+
//#region src/commands/database-users/help.ts
|
|
1696
1744
|
function showDatabaseUsersHelp(subcommand) {
|
|
1697
1745
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1698
1746
|
${colors.bold("forge database-users list")} - List database users on a server
|
|
@@ -1761,6 +1809,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1761
1809
|
Run ${colors.cyan("forge database-users <subcommand> --help")} for details.
|
|
1762
1810
|
`);
|
|
1763
1811
|
}
|
|
1812
|
+
//#endregion
|
|
1813
|
+
//#region src/commands/deployments/handlers.ts
|
|
1764
1814
|
async function deploymentsList(ctx) {
|
|
1765
1815
|
const server = String(ctx.options.server ?? "");
|
|
1766
1816
|
const site = String(ctx.options.site ?? "");
|
|
@@ -1803,14 +1853,17 @@ async function deploymentsDeploy(ctx) {
|
|
|
1803
1853
|
process.stdout.write(chunk);
|
|
1804
1854
|
} : void 0
|
|
1805
1855
|
}, execCtx);
|
|
1806
|
-
if (
|
|
1856
|
+
if (streamLogs) process.stdout.write("\n");
|
|
1857
|
+
else process.stderr.write("\n");
|
|
1807
1858
|
const elapsedSec = (result.data.elapsed_ms / 1e3).toFixed(1);
|
|
1808
|
-
if (result.data.status === "success") ctx.formatter.success(`Deployment succeeded for site ${site_id} (${elapsedSec}s).`);
|
|
1809
|
-
else ctx.formatter.error(`Deployment failed for site ${site_id} (${elapsedSec}s).`);
|
|
1810
1859
|
if (!streamLogs && result.data.log) ctx.formatter.output(result.data.log);
|
|
1860
|
+
if (result.data.status === "success") ctx.formatter.success(`Deployment succeeded for site ${site_id} (${elapsedSec}s).`);
|
|
1861
|
+
else throw new ApiError(`Deployment failed for site ${site_id} (${elapsedSec}s).`);
|
|
1811
1862
|
}, ctx.formatter);
|
|
1812
1863
|
}
|
|
1813
|
-
|
|
1864
|
+
//#endregion
|
|
1865
|
+
//#region src/commands/deployments/command.ts
|
|
1866
|
+
var handleDeploymentsCommand = createCommandRouter({
|
|
1814
1867
|
resource: "deployments",
|
|
1815
1868
|
handlers: {
|
|
1816
1869
|
list: deploymentsList,
|
|
@@ -1819,6 +1872,8 @@ const handleDeploymentsCommand = createCommandRouter({
|
|
|
1819
1872
|
},
|
|
1820
1873
|
writeSubcommands: ["deploy"]
|
|
1821
1874
|
});
|
|
1875
|
+
//#endregion
|
|
1876
|
+
//#region src/commands/deployments/help.ts
|
|
1822
1877
|
function showDeploymentsHelp(subcommand) {
|
|
1823
1878
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1824
1879
|
${colors.bold("forge deployments list")} - List deployments for a site
|
|
@@ -1864,6 +1919,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1864
1919
|
Run ${colors.cyan("forge deployments <subcommand> --help")} for details.
|
|
1865
1920
|
`);
|
|
1866
1921
|
}
|
|
1922
|
+
//#endregion
|
|
1923
|
+
//#region src/commands/env/handlers.ts
|
|
1867
1924
|
async function envGet(ctx) {
|
|
1868
1925
|
const server = String(ctx.options.server ?? "");
|
|
1869
1926
|
const site = String(ctx.options.site ?? "");
|
|
@@ -1900,7 +1957,9 @@ async function envUpdate(ctx) {
|
|
|
1900
1957
|
ctx.formatter.success("Environment variables updated.");
|
|
1901
1958
|
}, ctx.formatter);
|
|
1902
1959
|
}
|
|
1903
|
-
|
|
1960
|
+
//#endregion
|
|
1961
|
+
//#region src/commands/env/command.ts
|
|
1962
|
+
var handleEnvCommand = createCommandRouter({
|
|
1904
1963
|
resource: "env",
|
|
1905
1964
|
handlers: {
|
|
1906
1965
|
get: envGet,
|
|
@@ -1908,6 +1967,8 @@ const handleEnvCommand = createCommandRouter({
|
|
|
1908
1967
|
},
|
|
1909
1968
|
writeSubcommands: ["update"]
|
|
1910
1969
|
});
|
|
1970
|
+
//#endregion
|
|
1971
|
+
//#region src/commands/env/help.ts
|
|
1911
1972
|
function showEnvHelp(subcommand) {
|
|
1912
1973
|
if (subcommand === "get") console.log(`
|
|
1913
1974
|
${colors.bold("forge env get")} - Get environment variables
|
|
@@ -1940,6 +2001,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1940
2001
|
Run ${colors.cyan("forge env <subcommand> --help")} for details.
|
|
1941
2002
|
`);
|
|
1942
2003
|
}
|
|
2004
|
+
//#endregion
|
|
2005
|
+
//#region src/commands/firewall-rules/handlers.ts
|
|
1943
2006
|
async function firewallRulesList(ctx) {
|
|
1944
2007
|
const server = String(ctx.options.server ?? "");
|
|
1945
2008
|
if (!server) exitWithValidationError("server_id", "forge firewall-rules list --server <server_id>", ctx.formatter);
|
|
@@ -1980,7 +2043,9 @@ async function firewallRulesGet(args, ctx) {
|
|
|
1980
2043
|
]);
|
|
1981
2044
|
}, ctx.formatter);
|
|
1982
2045
|
}
|
|
1983
|
-
|
|
2046
|
+
//#endregion
|
|
2047
|
+
//#region src/commands/firewall-rules/command.ts
|
|
2048
|
+
var handleFirewallRulesCommand = createCommandRouter({
|
|
1984
2049
|
resource: "firewall-rules",
|
|
1985
2050
|
handlers: {
|
|
1986
2051
|
list: firewallRulesList,
|
|
@@ -1988,6 +2053,8 @@ const handleFirewallRulesCommand = createCommandRouter({
|
|
|
1988
2053
|
get: [firewallRulesGet, "args"]
|
|
1989
2054
|
}
|
|
1990
2055
|
});
|
|
2056
|
+
//#endregion
|
|
2057
|
+
//#region src/commands/firewall-rules/help.ts
|
|
1991
2058
|
function showFirewallRulesHelp(subcommand) {
|
|
1992
2059
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1993
2060
|
${colors.bold("forge firewall-rules list")} - List firewall rules on a server
|
|
@@ -2021,6 +2088,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2021
2088
|
Run ${colors.cyan("forge firewall-rules <subcommand> --help")} for details.
|
|
2022
2089
|
`);
|
|
2023
2090
|
}
|
|
2091
|
+
//#endregion
|
|
2092
|
+
//#region src/commands/monitors/handlers.ts
|
|
2024
2093
|
async function monitorsList(ctx) {
|
|
2025
2094
|
const server = String(ctx.options.server ?? "");
|
|
2026
2095
|
if (!server) exitWithValidationError("server_id", "forge monitors list --server <server_id>", ctx.formatter);
|
|
@@ -2106,7 +2175,9 @@ async function monitorsDelete(args, ctx) {
|
|
|
2106
2175
|
ctx.formatter.success(`Monitor ${id} deleted.`);
|
|
2107
2176
|
}, ctx.formatter);
|
|
2108
2177
|
}
|
|
2109
|
-
|
|
2178
|
+
//#endregion
|
|
2179
|
+
//#region src/commands/monitors/command.ts
|
|
2180
|
+
var handleMonitorsCommand = createCommandRouter({
|
|
2110
2181
|
resource: "monitors",
|
|
2111
2182
|
handlers: {
|
|
2112
2183
|
list: monitorsList,
|
|
@@ -2117,6 +2188,8 @@ const handleMonitorsCommand = createCommandRouter({
|
|
|
2117
2188
|
},
|
|
2118
2189
|
writeSubcommands: ["create", "delete"]
|
|
2119
2190
|
});
|
|
2191
|
+
//#endregion
|
|
2192
|
+
//#region src/commands/monitors/help.ts
|
|
2120
2193
|
function showMonitorsHelp(subcommand) {
|
|
2121
2194
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2122
2195
|
${colors.bold("forge monitors list")} - List monitors on a server
|
|
@@ -2173,6 +2246,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2173
2246
|
Run ${colors.cyan("forge monitors <subcommand> --help")} for details.
|
|
2174
2247
|
`);
|
|
2175
2248
|
}
|
|
2249
|
+
//#endregion
|
|
2250
|
+
//#region src/commands/nginx/handlers.ts
|
|
2176
2251
|
async function nginxGet(ctx) {
|
|
2177
2252
|
const server = String(ctx.options.server ?? "");
|
|
2178
2253
|
const site = String(ctx.options.site ?? "");
|
|
@@ -2209,7 +2284,9 @@ async function nginxUpdate(ctx) {
|
|
|
2209
2284
|
ctx.formatter.success("Nginx configuration updated.");
|
|
2210
2285
|
}, ctx.formatter);
|
|
2211
2286
|
}
|
|
2212
|
-
|
|
2287
|
+
//#endregion
|
|
2288
|
+
//#region src/commands/nginx/command.ts
|
|
2289
|
+
var handleNginxCommand = createCommandRouter({
|
|
2213
2290
|
resource: "nginx",
|
|
2214
2291
|
handlers: {
|
|
2215
2292
|
get: nginxGet,
|
|
@@ -2217,6 +2294,8 @@ const handleNginxCommand = createCommandRouter({
|
|
|
2217
2294
|
},
|
|
2218
2295
|
writeSubcommands: ["update"]
|
|
2219
2296
|
});
|
|
2297
|
+
//#endregion
|
|
2298
|
+
//#region src/commands/nginx/help.ts
|
|
2220
2299
|
function showNginxHelp(subcommand) {
|
|
2221
2300
|
if (subcommand === "get") console.log(`
|
|
2222
2301
|
${colors.bold("forge nginx get")} - Get nginx configuration
|
|
@@ -2248,6 +2327,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2248
2327
|
Run ${colors.cyan("forge nginx <subcommand> --help")} for details.
|
|
2249
2328
|
`);
|
|
2250
2329
|
}
|
|
2330
|
+
//#endregion
|
|
2331
|
+
//#region src/commands/nginx-templates/handlers.ts
|
|
2251
2332
|
async function nginxTemplatesList(ctx) {
|
|
2252
2333
|
const server = String(ctx.options.server ?? "");
|
|
2253
2334
|
if (!server) exitWithValidationError("server_id", "forge nginx-templates list --server <server_id>", ctx.formatter);
|
|
@@ -2312,11 +2393,14 @@ async function nginxTemplatesUpdate(args, ctx) {
|
|
|
2312
2393
|
await runCommand(async () => {
|
|
2313
2394
|
const token = ctx.getToken();
|
|
2314
2395
|
const execCtx = ctx.createExecutorContext(token);
|
|
2396
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
2397
|
+
const name = ctx.options.name ? String(ctx.options.name) : void 0;
|
|
2398
|
+
const content = ctx.options.content ? String(ctx.options.content) : void 0;
|
|
2315
2399
|
const result = await updateNginxTemplate({
|
|
2316
|
-
server_id
|
|
2400
|
+
server_id,
|
|
2317
2401
|
id,
|
|
2318
|
-
name
|
|
2319
|
-
content
|
|
2402
|
+
name,
|
|
2403
|
+
content
|
|
2320
2404
|
}, execCtx);
|
|
2321
2405
|
ctx.formatter.outputOne(result.data, [
|
|
2322
2406
|
"id",
|
|
@@ -2340,7 +2424,9 @@ async function nginxTemplatesDelete(args, ctx) {
|
|
|
2340
2424
|
ctx.formatter.success(`Nginx template ${id} deleted.`);
|
|
2341
2425
|
}, ctx.formatter);
|
|
2342
2426
|
}
|
|
2343
|
-
|
|
2427
|
+
//#endregion
|
|
2428
|
+
//#region src/commands/nginx-templates/command.ts
|
|
2429
|
+
var handleNginxTemplatesCommand = createCommandRouter({
|
|
2344
2430
|
resource: "nginx-templates",
|
|
2345
2431
|
handlers: {
|
|
2346
2432
|
list: nginxTemplatesList,
|
|
@@ -2356,6 +2442,8 @@ const handleNginxTemplatesCommand = createCommandRouter({
|
|
|
2356
2442
|
"delete"
|
|
2357
2443
|
]
|
|
2358
2444
|
});
|
|
2445
|
+
//#endregion
|
|
2446
|
+
//#region src/commands/nginx-templates/help.ts
|
|
2359
2447
|
function showNginxTemplatesHelp(subcommand) {
|
|
2360
2448
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2361
2449
|
${colors.bold("forge nginx-templates list")} - List Nginx templates on a server
|
|
@@ -2423,6 +2511,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2423
2511
|
Run ${colors.cyan("forge nginx-templates <subcommand> --help")} for details.
|
|
2424
2512
|
`);
|
|
2425
2513
|
}
|
|
2514
|
+
//#endregion
|
|
2515
|
+
//#region src/commands/recipes/handlers.ts
|
|
2426
2516
|
async function recipesList(ctx) {
|
|
2427
2517
|
await runCommand(async () => {
|
|
2428
2518
|
const token = ctx.getToken();
|
|
@@ -2491,7 +2581,9 @@ async function recipesRun(args, ctx) {
|
|
|
2491
2581
|
ctx.formatter.success(`Recipe ${id} dispatched to ${servers.length} server(s).`);
|
|
2492
2582
|
}, ctx.formatter);
|
|
2493
2583
|
}
|
|
2494
|
-
|
|
2584
|
+
//#endregion
|
|
2585
|
+
//#region src/commands/recipes/command.ts
|
|
2586
|
+
var handleRecipesCommand = createCommandRouter({
|
|
2495
2587
|
resource: "recipes",
|
|
2496
2588
|
handlers: {
|
|
2497
2589
|
list: recipesList,
|
|
@@ -2502,6 +2594,8 @@ const handleRecipesCommand = createCommandRouter({
|
|
|
2502
2594
|
},
|
|
2503
2595
|
writeSubcommands: ["update", "run"]
|
|
2504
2596
|
});
|
|
2597
|
+
//#endregion
|
|
2598
|
+
//#region src/commands/recipes/help.ts
|
|
2505
2599
|
function showRecipesHelp(subcommand) {
|
|
2506
2600
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2507
2601
|
${colors.bold("forge recipes list")} - List all recipes
|
|
@@ -2553,6 +2647,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2553
2647
|
Run ${colors.cyan("forge recipes <subcommand> --help")} for details.
|
|
2554
2648
|
`);
|
|
2555
2649
|
}
|
|
2650
|
+
//#endregion
|
|
2651
|
+
//#region src/commands/redirect-rules/handlers.ts
|
|
2556
2652
|
function requireServerAndSiteRaw$1(ctx, usage) {
|
|
2557
2653
|
const server = String(ctx.options.server ?? "");
|
|
2558
2654
|
const site = String(ctx.options.site ?? "");
|
|
@@ -2643,7 +2739,9 @@ async function redirectRulesDelete(args, ctx) {
|
|
|
2643
2739
|
ctx.formatter.success(`Redirect rule ${id} deleted.`);
|
|
2644
2740
|
}, ctx.formatter);
|
|
2645
2741
|
}
|
|
2646
|
-
|
|
2742
|
+
//#endregion
|
|
2743
|
+
//#region src/commands/redirect-rules/command.ts
|
|
2744
|
+
var handleRedirectRulesCommand = createCommandRouter({
|
|
2647
2745
|
resource: "redirect-rules",
|
|
2648
2746
|
handlers: {
|
|
2649
2747
|
list: redirectRulesList,
|
|
@@ -2654,6 +2752,8 @@ const handleRedirectRulesCommand = createCommandRouter({
|
|
|
2654
2752
|
},
|
|
2655
2753
|
writeSubcommands: ["create", "delete"]
|
|
2656
2754
|
});
|
|
2755
|
+
//#endregion
|
|
2756
|
+
//#region src/commands/redirect-rules/help.ts
|
|
2657
2757
|
function showRedirectRulesHelp(subcommand) {
|
|
2658
2758
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2659
2759
|
${colors.bold("forge redirect-rules list")} - List redirect rules for a site
|
|
@@ -2711,6 +2811,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2711
2811
|
Run ${colors.cyan("forge redirect-rules <subcommand> --help")} for details.
|
|
2712
2812
|
`);
|
|
2713
2813
|
}
|
|
2814
|
+
//#endregion
|
|
2815
|
+
//#region src/commands/scheduled-jobs/handlers.ts
|
|
2714
2816
|
async function scheduledJobsList(ctx) {
|
|
2715
2817
|
const server = String(ctx.options.server ?? "");
|
|
2716
2818
|
const site = ctx.options.site ? String(ctx.options.site) : void 0;
|
|
@@ -2741,10 +2843,11 @@ async function scheduledJobsGet(args, ctx) {
|
|
|
2741
2843
|
const token = ctx.getToken();
|
|
2742
2844
|
const execCtx = ctx.createExecutorContext(token);
|
|
2743
2845
|
const server_id = await resolveServerId(server, execCtx);
|
|
2846
|
+
const site_id = site ? await resolveSiteId(site, server_id, execCtx) : void 0;
|
|
2744
2847
|
const result = await getScheduledJob({
|
|
2745
2848
|
server_id,
|
|
2746
2849
|
id,
|
|
2747
|
-
site_id
|
|
2850
|
+
site_id
|
|
2748
2851
|
}, execCtx);
|
|
2749
2852
|
ctx.formatter.outputOne(result.data, [
|
|
2750
2853
|
"id",
|
|
@@ -2799,15 +2902,18 @@ async function scheduledJobsDelete(args, ctx) {
|
|
|
2799
2902
|
const token = ctx.getToken();
|
|
2800
2903
|
const execCtx = ctx.createExecutorContext(token);
|
|
2801
2904
|
const server_id = await resolveServerId(server, execCtx);
|
|
2905
|
+
const site_id = site ? await resolveSiteId(site, server_id, execCtx) : void 0;
|
|
2802
2906
|
await deleteScheduledJob({
|
|
2803
2907
|
server_id,
|
|
2804
2908
|
id,
|
|
2805
|
-
site_id
|
|
2909
|
+
site_id
|
|
2806
2910
|
}, execCtx);
|
|
2807
2911
|
ctx.formatter.success(`Scheduled job ${id} deleted.`);
|
|
2808
2912
|
}, ctx.formatter);
|
|
2809
2913
|
}
|
|
2810
|
-
|
|
2914
|
+
//#endregion
|
|
2915
|
+
//#region src/commands/scheduled-jobs/command.ts
|
|
2916
|
+
var handleScheduledJobsCommand = createCommandRouter({
|
|
2811
2917
|
resource: "scheduled-jobs",
|
|
2812
2918
|
handlers: {
|
|
2813
2919
|
list: scheduledJobsList,
|
|
@@ -2818,6 +2924,8 @@ const handleScheduledJobsCommand = createCommandRouter({
|
|
|
2818
2924
|
},
|
|
2819
2925
|
writeSubcommands: ["create", "delete"]
|
|
2820
2926
|
});
|
|
2927
|
+
//#endregion
|
|
2928
|
+
//#region src/commands/scheduled-jobs/help.ts
|
|
2821
2929
|
function showScheduledJobsHelp(subcommand) {
|
|
2822
2930
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2823
2931
|
${colors.bold("forge scheduled-jobs list")} - List scheduled jobs on a server
|
|
@@ -2871,6 +2979,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2871
2979
|
Run ${colors.cyan("forge scheduled-jobs <subcommand> --help")} for details.
|
|
2872
2980
|
`);
|
|
2873
2981
|
}
|
|
2982
|
+
//#endregion
|
|
2983
|
+
//#region src/commands/security-rules/handlers.ts
|
|
2874
2984
|
function requireServerAndSiteRaw(ctx, usage) {
|
|
2875
2985
|
const server = String(ctx.options.server ?? "");
|
|
2876
2986
|
const site = String(ctx.options.site ?? "");
|
|
@@ -2986,7 +3096,9 @@ async function securityRulesDelete(args, ctx) {
|
|
|
2986
3096
|
ctx.formatter.success(`Security rule ${id} deleted.`);
|
|
2987
3097
|
}, ctx.formatter);
|
|
2988
3098
|
}
|
|
2989
|
-
|
|
3099
|
+
//#endregion
|
|
3100
|
+
//#region src/commands/security-rules/command.ts
|
|
3101
|
+
var handleSecurityRulesCommand = createCommandRouter({
|
|
2990
3102
|
resource: "security-rules",
|
|
2991
3103
|
handlers: {
|
|
2992
3104
|
list: securityRulesList,
|
|
@@ -3002,6 +3114,8 @@ const handleSecurityRulesCommand = createCommandRouter({
|
|
|
3002
3114
|
"delete"
|
|
3003
3115
|
]
|
|
3004
3116
|
});
|
|
3117
|
+
//#endregion
|
|
3118
|
+
//#region src/commands/security-rules/help.ts
|
|
3005
3119
|
function showSecurityRulesHelp(subcommand) {
|
|
3006
3120
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3007
3121
|
${colors.bold("forge security-rules list")} - List security rules for a site
|
|
@@ -3071,6 +3185,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
3071
3185
|
Run ${colors.cyan("forge security-rules <subcommand> --help")} for details.
|
|
3072
3186
|
`);
|
|
3073
3187
|
}
|
|
3188
|
+
//#endregion
|
|
3189
|
+
//#region src/commands/servers/handlers.ts
|
|
3074
3190
|
/**
|
|
3075
3191
|
* CLI handlers for servers commands.
|
|
3076
3192
|
* Delegates all HTTP logic to forge-core executors.
|
|
@@ -3120,7 +3236,9 @@ async function serversReboot(args, ctx) {
|
|
|
3120
3236
|
ctx.formatter.success(`Server ${server_id} reboot initiated.`);
|
|
3121
3237
|
}, ctx.formatter);
|
|
3122
3238
|
}
|
|
3123
|
-
|
|
3239
|
+
//#endregion
|
|
3240
|
+
//#region src/commands/servers/command.ts
|
|
3241
|
+
var handleServersCommand = createCommandRouter({
|
|
3124
3242
|
resource: "servers",
|
|
3125
3243
|
handlers: {
|
|
3126
3244
|
list: serversList,
|
|
@@ -3130,6 +3248,8 @@ const handleServersCommand = createCommandRouter({
|
|
|
3130
3248
|
},
|
|
3131
3249
|
writeSubcommands: ["reboot"]
|
|
3132
3250
|
});
|
|
3251
|
+
//#endregion
|
|
3252
|
+
//#region src/commands/servers/help.ts
|
|
3133
3253
|
function showServersHelp(subcommand) {
|
|
3134
3254
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3135
3255
|
${colors.bold("forge servers list")} - List all servers
|
|
@@ -3200,6 +3320,8 @@ ${colors.bold("EXAMPLES:")}
|
|
|
3200
3320
|
Run ${colors.cyan("forge servers <subcommand> --help")} for subcommand details.
|
|
3201
3321
|
`);
|
|
3202
3322
|
}
|
|
3323
|
+
//#endregion
|
|
3324
|
+
//#region src/commands/sites/handlers.ts
|
|
3203
3325
|
async function sitesList(ctx) {
|
|
3204
3326
|
const server = String(ctx.options.server ?? "");
|
|
3205
3327
|
if (!server) exitWithValidationError("server_id", "forge sites list --server <server_id>", ctx.formatter);
|
|
@@ -3275,7 +3397,9 @@ async function sitesUpdate(args, ctx) {
|
|
|
3275
3397
|
]);
|
|
3276
3398
|
}, ctx.formatter);
|
|
3277
3399
|
}
|
|
3278
|
-
|
|
3400
|
+
//#endregion
|
|
3401
|
+
//#region src/commands/sites/command.ts
|
|
3402
|
+
var handleSitesCommand = createCommandRouter({
|
|
3279
3403
|
resource: "sites",
|
|
3280
3404
|
handlers: {
|
|
3281
3405
|
list: sitesList,
|
|
@@ -3284,6 +3408,8 @@ const handleSitesCommand = createCommandRouter({
|
|
|
3284
3408
|
update: [sitesUpdate, "args"]
|
|
3285
3409
|
}
|
|
3286
3410
|
});
|
|
3411
|
+
//#endregion
|
|
3412
|
+
//#region src/commands/sites/help.ts
|
|
3287
3413
|
function showSitesHelp(subcommand) {
|
|
3288
3414
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3289
3415
|
${colors.bold("forge sites list")} - List sites on a server
|
|
@@ -3334,6 +3460,172 @@ ${colors.bold("EXAMPLES:")}
|
|
|
3334
3460
|
Run ${colors.cyan("forge sites <subcommand> --help")} for subcommand details.
|
|
3335
3461
|
`);
|
|
3336
3462
|
}
|
|
3463
|
+
/**
|
|
3464
|
+
* Resolve the concrete user/host/port to connect to.
|
|
3465
|
+
*
|
|
3466
|
+
* @throws {ValidationError} when the selected IP is not available yet, or the port override is invalid.
|
|
3467
|
+
*/
|
|
3468
|
+
function resolveSshTarget(server, options = {}) {
|
|
3469
|
+
const user = options.user?.trim() || "forge";
|
|
3470
|
+
const host = options.private ? server.private_ip_address : server.ip_address;
|
|
3471
|
+
if (!host) {
|
|
3472
|
+
const which = options.private ? "private IP address" : "IP address";
|
|
3473
|
+
const hints = [server.is_ready ? "The server is ready but no address is available — check the Forge dashboard." : "The server is still provisioning. Wait until it is ready, then try again.", options.private ? void 0 : "Use --private to connect over the private network."].filter((hint) => Boolean(hint));
|
|
3474
|
+
throw new ValidationError(`Server "${server.name}" has no ${which} available`, "server", hints);
|
|
3475
|
+
}
|
|
3476
|
+
let port = server.ssh_port;
|
|
3477
|
+
if (options.port !== void 0) {
|
|
3478
|
+
const parsed = Number(options.port);
|
|
3479
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535) throw new ValidationError(`Invalid SSH port "${options.port}"`, "port", ["Port must be an integer between 1 and 65535."]);
|
|
3480
|
+
port = parsed;
|
|
3481
|
+
}
|
|
3482
|
+
return {
|
|
3483
|
+
user,
|
|
3484
|
+
host,
|
|
3485
|
+
port
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
/**
|
|
3489
|
+
* Build the argument list passed to the `ssh` binary.
|
|
3490
|
+
*
|
|
3491
|
+
* Any {@link remoteCommand} is appended after the connection flags, so
|
|
3492
|
+
* `forge ssh web uptime` runs `uptime` remotely and exits.
|
|
3493
|
+
*/
|
|
3494
|
+
function buildSshArgs(target, remoteCommand = []) {
|
|
3495
|
+
const args = [
|
|
3496
|
+
`${target.user}@${target.host}`,
|
|
3497
|
+
"-p",
|
|
3498
|
+
String(target.port)
|
|
3499
|
+
];
|
|
3500
|
+
if (remoteCommand.length > 0) args.push(...remoteCommand);
|
|
3501
|
+
return args;
|
|
3502
|
+
}
|
|
3503
|
+
//#endregion
|
|
3504
|
+
//#region src/commands/ssh/handlers.ts
|
|
3505
|
+
/**
|
|
3506
|
+
* CLI handler for `forge ssh` — open an interactive SSH session to a server.
|
|
3507
|
+
*
|
|
3508
|
+
* Resolves the server, reads its connection details from the API, then hands
|
|
3509
|
+
* off to the local `ssh` binary with an inherited stdio (interactive) session.
|
|
3510
|
+
*/
|
|
3511
|
+
/**
|
|
3512
|
+
* Connect to a server over SSH.
|
|
3513
|
+
*
|
|
3514
|
+
* @param server - Server ID or name (resolved via {@link resolveServerId}).
|
|
3515
|
+
* @param remote - Optional remote command to run instead of an interactive shell.
|
|
3516
|
+
* @param ctx - CLI command context.
|
|
3517
|
+
*/
|
|
3518
|
+
async function sshConnect(server, remote, ctx) {
|
|
3519
|
+
if (!server) exitWithValidationError("server", "forge ssh <server> [command...]", ctx.formatter);
|
|
3520
|
+
await runCommand(async () => {
|
|
3521
|
+
const token = ctx.getToken();
|
|
3522
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
3523
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
3524
|
+
const { data } = await getServer({ server_id }, execCtx);
|
|
3525
|
+
const target = resolveSshTarget(data, {
|
|
3526
|
+
user: typeof ctx.options.user === "string" ? ctx.options.user : void 0,
|
|
3527
|
+
private: ctx.options.private === true,
|
|
3528
|
+
port: typeof ctx.options.port === "string" ? ctx.options.port : void 0
|
|
3529
|
+
});
|
|
3530
|
+
const sshArgs = buildSshArgs(target, remote);
|
|
3531
|
+
const printable = `ssh ${sshArgs.join(" ")}`;
|
|
3532
|
+
if (ctx.formatter.isJson()) {
|
|
3533
|
+
ctx.formatter.output({
|
|
3534
|
+
command: printable,
|
|
3535
|
+
...target,
|
|
3536
|
+
args: sshArgs
|
|
3537
|
+
});
|
|
3538
|
+
return;
|
|
3539
|
+
}
|
|
3540
|
+
if (ctx.options["dry-run"] === true) {
|
|
3541
|
+
console.log(printable);
|
|
3542
|
+
return;
|
|
3543
|
+
}
|
|
3544
|
+
const auditArgs = {
|
|
3545
|
+
server: server_id,
|
|
3546
|
+
user: target.user,
|
|
3547
|
+
host: target.host,
|
|
3548
|
+
port: target.port
|
|
3549
|
+
};
|
|
3550
|
+
try {
|
|
3551
|
+
const child = spawnSync("ssh", sshArgs, { stdio: "inherit" });
|
|
3552
|
+
if (child.error) throw child.error;
|
|
3553
|
+
getCliAuditLogger().log({
|
|
3554
|
+
source: "cli",
|
|
3555
|
+
resource: "ssh",
|
|
3556
|
+
action: "connect",
|
|
3557
|
+
args: auditArgs,
|
|
3558
|
+
status: "success"
|
|
3559
|
+
});
|
|
3560
|
+
if (typeof child.status === "number" && child.status !== 0) process.exit(child.status);
|
|
3561
|
+
} catch (err) {
|
|
3562
|
+
getCliAuditLogger().log({
|
|
3563
|
+
source: "cli",
|
|
3564
|
+
resource: "ssh",
|
|
3565
|
+
action: "connect",
|
|
3566
|
+
args: auditArgs,
|
|
3567
|
+
status: "error",
|
|
3568
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3569
|
+
});
|
|
3570
|
+
throw err;
|
|
3571
|
+
}
|
|
3572
|
+
}, ctx.formatter);
|
|
3573
|
+
}
|
|
3574
|
+
//#endregion
|
|
3575
|
+
//#region src/commands/ssh/command.ts
|
|
3576
|
+
/**
|
|
3577
|
+
* Route the top-level `forge ssh` command.
|
|
3578
|
+
*
|
|
3579
|
+
* Unlike resource commands there is no sub-action: the first positional is the
|
|
3580
|
+
* server, and any remaining positionals form an optional remote command.
|
|
3581
|
+
*/
|
|
3582
|
+
async function handleSshCommand(server, remote, options) {
|
|
3583
|
+
await sshConnect(server, remote, createContext(options));
|
|
3584
|
+
}
|
|
3585
|
+
//#endregion
|
|
3586
|
+
//#region src/commands/ssh/help.ts
|
|
3587
|
+
function showSshHelp() {
|
|
3588
|
+
console.log(`
|
|
3589
|
+
${colors.bold("forge ssh")} - Open an SSH session to a server
|
|
3590
|
+
|
|
3591
|
+
${colors.bold("USAGE:")}
|
|
3592
|
+
forge ssh <server> [command...] [options]
|
|
3593
|
+
|
|
3594
|
+
${colors.bold("ARGUMENTS:")}
|
|
3595
|
+
<server> Server ID or name (required)
|
|
3596
|
+
[command...] Optional remote command to run, then exit
|
|
3597
|
+
|
|
3598
|
+
${colors.bold("OPTIONS:")}
|
|
3599
|
+
--user <name> SSH user (default: forge)
|
|
3600
|
+
--private Connect over the private IP address
|
|
3601
|
+
--port <n> Override the server's SSH port
|
|
3602
|
+
--dry-run Print the ssh command instead of connecting
|
|
3603
|
+
-f, --format json Print the resolved connection details as JSON
|
|
3604
|
+
-h, --help Show this help
|
|
3605
|
+
|
|
3606
|
+
${colors.bold("EXAMPLES:")}
|
|
3607
|
+
# Interactive session (connects as forge@<ip>)
|
|
3608
|
+
forge ssh my-server
|
|
3609
|
+
|
|
3610
|
+
# Connect as a custom user
|
|
3611
|
+
forge ssh my-server --user deploy
|
|
3612
|
+
|
|
3613
|
+
# Use the private network
|
|
3614
|
+
forge ssh my-server --private
|
|
3615
|
+
|
|
3616
|
+
# Run a one-off remote command
|
|
3617
|
+
forge ssh my-server uptime
|
|
3618
|
+
|
|
3619
|
+
# Just show the command that would run
|
|
3620
|
+
forge ssh my-server --dry-run
|
|
3621
|
+
|
|
3622
|
+
${colors.bold("NOTES:")}
|
|
3623
|
+
Requires your local SSH key to be authorized on the server; this command
|
|
3624
|
+
launches ssh, it does not upload keys.
|
|
3625
|
+
`);
|
|
3626
|
+
}
|
|
3627
|
+
//#endregion
|
|
3628
|
+
//#region src/commands/ssh-keys/handlers.ts
|
|
3337
3629
|
async function sshKeysList(ctx) {
|
|
3338
3630
|
const server = String(ctx.options.server ?? "");
|
|
3339
3631
|
if (!server) exitWithValidationError("server_id", "forge ssh-keys list --server <server_id>", ctx.formatter);
|
|
@@ -3368,7 +3660,9 @@ async function sshKeysGet(args, ctx) {
|
|
|
3368
3660
|
]);
|
|
3369
3661
|
}, ctx.formatter);
|
|
3370
3662
|
}
|
|
3371
|
-
|
|
3663
|
+
//#endregion
|
|
3664
|
+
//#region src/commands/ssh-keys/command.ts
|
|
3665
|
+
var handleSshKeysCommand = createCommandRouter({
|
|
3372
3666
|
resource: "ssh-keys",
|
|
3373
3667
|
handlers: {
|
|
3374
3668
|
list: sshKeysList,
|
|
@@ -3376,6 +3670,8 @@ const handleSshKeysCommand = createCommandRouter({
|
|
|
3376
3670
|
get: [sshKeysGet, "args"]
|
|
3377
3671
|
}
|
|
3378
3672
|
});
|
|
3673
|
+
//#endregion
|
|
3674
|
+
//#region src/commands/ssh-keys/help.ts
|
|
3379
3675
|
function showSshKeysHelp(subcommand) {
|
|
3380
3676
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3381
3677
|
${colors.bold("forge ssh-keys list")} - List SSH keys on a server
|
|
@@ -3406,6 +3702,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
3406
3702
|
Run ${colors.cyan("forge ssh-keys <subcommand> --help")} for details.
|
|
3407
3703
|
`);
|
|
3408
3704
|
}
|
|
3705
|
+
//#endregion
|
|
3706
|
+
//#region src/commands/user/handlers.ts
|
|
3409
3707
|
async function userGet(ctx) {
|
|
3410
3708
|
await runCommand(async () => {
|
|
3411
3709
|
const token = ctx.getToken();
|
|
@@ -3413,10 +3711,14 @@ async function userGet(ctx) {
|
|
|
3413
3711
|
ctx.formatter.output(result.data);
|
|
3414
3712
|
}, ctx.formatter);
|
|
3415
3713
|
}
|
|
3416
|
-
|
|
3714
|
+
//#endregion
|
|
3715
|
+
//#region src/commands/user/command.ts
|
|
3716
|
+
var handleUserCommand = createCommandRouter({
|
|
3417
3717
|
resource: "user",
|
|
3418
3718
|
handlers: { get: userGet }
|
|
3419
3719
|
});
|
|
3720
|
+
//#endregion
|
|
3721
|
+
//#region src/commands/user/help.ts
|
|
3420
3722
|
function showUserHelp(subcommand) {
|
|
3421
3723
|
if (subcommand === "get") console.log(`
|
|
3422
3724
|
${colors.bold("forge user get")} - Get the authenticated user profile
|
|
@@ -3442,6 +3744,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
3442
3744
|
Run ${colors.cyan("forge user <subcommand> --help")} for details.
|
|
3443
3745
|
`);
|
|
3444
3746
|
}
|
|
3747
|
+
//#endregion
|
|
3748
|
+
//#region src/utils/args.ts
|
|
3445
3749
|
function parseArgs(argv = process.argv.slice(2)) {
|
|
3446
3750
|
const options = {};
|
|
3447
3751
|
const positional = [];
|
|
@@ -3478,7 +3782,9 @@ function parseArgs(argv = process.argv.slice(2)) {
|
|
|
3478
3782
|
positional
|
|
3479
3783
|
};
|
|
3480
3784
|
}
|
|
3481
|
-
|
|
3785
|
+
//#endregion
|
|
3786
|
+
//#region src/cli.ts
|
|
3787
|
+
var VERSION = "0.4.5";
|
|
3482
3788
|
function showHelp() {
|
|
3483
3789
|
console.log(`
|
|
3484
3790
|
${colors.bold("forge")} v${VERSION}
|
|
@@ -3537,6 +3843,9 @@ ${colors.bold("COMMANDS:")}
|
|
|
3537
3843
|
list, ls List firewall rules (requires --server)
|
|
3538
3844
|
get <id> Get firewall rule details (requires --server)
|
|
3539
3845
|
|
|
3846
|
+
ssh <server> Open an SSH session to a server
|
|
3847
|
+
--user <name> (default: forge), --private, --port <n>
|
|
3848
|
+
|
|
3540
3849
|
ssh-keys Manage SSH keys
|
|
3541
3850
|
list, ls List SSH keys (requires --server)
|
|
3542
3851
|
get <id> Get SSH key details (requires --server)
|
|
@@ -3739,6 +4048,13 @@ async function main() {
|
|
|
3739
4048
|
}
|
|
3740
4049
|
await handleFirewallRulesCommand(subcommand ?? "list", positional, options);
|
|
3741
4050
|
break;
|
|
4051
|
+
case "ssh":
|
|
4052
|
+
if (wantsHelp) {
|
|
4053
|
+
showSshHelp();
|
|
4054
|
+
process.exit(0);
|
|
4055
|
+
}
|
|
4056
|
+
await handleSshCommand(subcommand, positional, options);
|
|
4057
|
+
break;
|
|
3742
4058
|
case "ssh-keys":
|
|
3743
4059
|
if (wantsHelp) {
|
|
3744
4060
|
showSshKeysHelp(subcommand);
|
|
@@ -3830,5 +4146,6 @@ main().catch((error) => {
|
|
|
3830
4146
|
console.error(colors.red("Unhandled error:"), error);
|
|
3831
4147
|
process.exit(1);
|
|
3832
4148
|
});
|
|
4149
|
+
//#endregion
|
|
3833
4150
|
|
|
3834
4151
|
//# sourceMappingURL=cli.js.map
|