@studiometa/forge-cli 0.4.4 → 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 +345 -29
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.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, _ 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-
|
|
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 ?? "");
|
|
@@ -1811,7 +1861,9 @@ async function deploymentsDeploy(ctx) {
|
|
|
1811
1861
|
else throw new ApiError(`Deployment failed for site ${site_id} (${elapsedSec}s).`);
|
|
1812
1862
|
}, ctx.formatter);
|
|
1813
1863
|
}
|
|
1814
|
-
|
|
1864
|
+
//#endregion
|
|
1865
|
+
//#region src/commands/deployments/command.ts
|
|
1866
|
+
var handleDeploymentsCommand = createCommandRouter({
|
|
1815
1867
|
resource: "deployments",
|
|
1816
1868
|
handlers: {
|
|
1817
1869
|
list: deploymentsList,
|
|
@@ -1820,6 +1872,8 @@ const handleDeploymentsCommand = createCommandRouter({
|
|
|
1820
1872
|
},
|
|
1821
1873
|
writeSubcommands: ["deploy"]
|
|
1822
1874
|
});
|
|
1875
|
+
//#endregion
|
|
1876
|
+
//#region src/commands/deployments/help.ts
|
|
1823
1877
|
function showDeploymentsHelp(subcommand) {
|
|
1824
1878
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1825
1879
|
${colors.bold("forge deployments list")} - List deployments for a site
|
|
@@ -1865,6 +1919,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1865
1919
|
Run ${colors.cyan("forge deployments <subcommand> --help")} for details.
|
|
1866
1920
|
`);
|
|
1867
1921
|
}
|
|
1922
|
+
//#endregion
|
|
1923
|
+
//#region src/commands/env/handlers.ts
|
|
1868
1924
|
async function envGet(ctx) {
|
|
1869
1925
|
const server = String(ctx.options.server ?? "");
|
|
1870
1926
|
const site = String(ctx.options.site ?? "");
|
|
@@ -1901,7 +1957,9 @@ async function envUpdate(ctx) {
|
|
|
1901
1957
|
ctx.formatter.success("Environment variables updated.");
|
|
1902
1958
|
}, ctx.formatter);
|
|
1903
1959
|
}
|
|
1904
|
-
|
|
1960
|
+
//#endregion
|
|
1961
|
+
//#region src/commands/env/command.ts
|
|
1962
|
+
var handleEnvCommand = createCommandRouter({
|
|
1905
1963
|
resource: "env",
|
|
1906
1964
|
handlers: {
|
|
1907
1965
|
get: envGet,
|
|
@@ -1909,6 +1967,8 @@ const handleEnvCommand = createCommandRouter({
|
|
|
1909
1967
|
},
|
|
1910
1968
|
writeSubcommands: ["update"]
|
|
1911
1969
|
});
|
|
1970
|
+
//#endregion
|
|
1971
|
+
//#region src/commands/env/help.ts
|
|
1912
1972
|
function showEnvHelp(subcommand) {
|
|
1913
1973
|
if (subcommand === "get") console.log(`
|
|
1914
1974
|
${colors.bold("forge env get")} - Get environment variables
|
|
@@ -1941,6 +2001,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
1941
2001
|
Run ${colors.cyan("forge env <subcommand> --help")} for details.
|
|
1942
2002
|
`);
|
|
1943
2003
|
}
|
|
2004
|
+
//#endregion
|
|
2005
|
+
//#region src/commands/firewall-rules/handlers.ts
|
|
1944
2006
|
async function firewallRulesList(ctx) {
|
|
1945
2007
|
const server = String(ctx.options.server ?? "");
|
|
1946
2008
|
if (!server) exitWithValidationError("server_id", "forge firewall-rules list --server <server_id>", ctx.formatter);
|
|
@@ -1981,7 +2043,9 @@ async function firewallRulesGet(args, ctx) {
|
|
|
1981
2043
|
]);
|
|
1982
2044
|
}, ctx.formatter);
|
|
1983
2045
|
}
|
|
1984
|
-
|
|
2046
|
+
//#endregion
|
|
2047
|
+
//#region src/commands/firewall-rules/command.ts
|
|
2048
|
+
var handleFirewallRulesCommand = createCommandRouter({
|
|
1985
2049
|
resource: "firewall-rules",
|
|
1986
2050
|
handlers: {
|
|
1987
2051
|
list: firewallRulesList,
|
|
@@ -1989,6 +2053,8 @@ const handleFirewallRulesCommand = createCommandRouter({
|
|
|
1989
2053
|
get: [firewallRulesGet, "args"]
|
|
1990
2054
|
}
|
|
1991
2055
|
});
|
|
2056
|
+
//#endregion
|
|
2057
|
+
//#region src/commands/firewall-rules/help.ts
|
|
1992
2058
|
function showFirewallRulesHelp(subcommand) {
|
|
1993
2059
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1994
2060
|
${colors.bold("forge firewall-rules list")} - List firewall rules on a server
|
|
@@ -2022,6 +2088,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2022
2088
|
Run ${colors.cyan("forge firewall-rules <subcommand> --help")} for details.
|
|
2023
2089
|
`);
|
|
2024
2090
|
}
|
|
2091
|
+
//#endregion
|
|
2092
|
+
//#region src/commands/monitors/handlers.ts
|
|
2025
2093
|
async function monitorsList(ctx) {
|
|
2026
2094
|
const server = String(ctx.options.server ?? "");
|
|
2027
2095
|
if (!server) exitWithValidationError("server_id", "forge monitors list --server <server_id>", ctx.formatter);
|
|
@@ -2107,7 +2175,9 @@ async function monitorsDelete(args, ctx) {
|
|
|
2107
2175
|
ctx.formatter.success(`Monitor ${id} deleted.`);
|
|
2108
2176
|
}, ctx.formatter);
|
|
2109
2177
|
}
|
|
2110
|
-
|
|
2178
|
+
//#endregion
|
|
2179
|
+
//#region src/commands/monitors/command.ts
|
|
2180
|
+
var handleMonitorsCommand = createCommandRouter({
|
|
2111
2181
|
resource: "monitors",
|
|
2112
2182
|
handlers: {
|
|
2113
2183
|
list: monitorsList,
|
|
@@ -2118,6 +2188,8 @@ const handleMonitorsCommand = createCommandRouter({
|
|
|
2118
2188
|
},
|
|
2119
2189
|
writeSubcommands: ["create", "delete"]
|
|
2120
2190
|
});
|
|
2191
|
+
//#endregion
|
|
2192
|
+
//#region src/commands/monitors/help.ts
|
|
2121
2193
|
function showMonitorsHelp(subcommand) {
|
|
2122
2194
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2123
2195
|
${colors.bold("forge monitors list")} - List monitors on a server
|
|
@@ -2174,6 +2246,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2174
2246
|
Run ${colors.cyan("forge monitors <subcommand> --help")} for details.
|
|
2175
2247
|
`);
|
|
2176
2248
|
}
|
|
2249
|
+
//#endregion
|
|
2250
|
+
//#region src/commands/nginx/handlers.ts
|
|
2177
2251
|
async function nginxGet(ctx) {
|
|
2178
2252
|
const server = String(ctx.options.server ?? "");
|
|
2179
2253
|
const site = String(ctx.options.site ?? "");
|
|
@@ -2210,7 +2284,9 @@ async function nginxUpdate(ctx) {
|
|
|
2210
2284
|
ctx.formatter.success("Nginx configuration updated.");
|
|
2211
2285
|
}, ctx.formatter);
|
|
2212
2286
|
}
|
|
2213
|
-
|
|
2287
|
+
//#endregion
|
|
2288
|
+
//#region src/commands/nginx/command.ts
|
|
2289
|
+
var handleNginxCommand = createCommandRouter({
|
|
2214
2290
|
resource: "nginx",
|
|
2215
2291
|
handlers: {
|
|
2216
2292
|
get: nginxGet,
|
|
@@ -2218,6 +2294,8 @@ const handleNginxCommand = createCommandRouter({
|
|
|
2218
2294
|
},
|
|
2219
2295
|
writeSubcommands: ["update"]
|
|
2220
2296
|
});
|
|
2297
|
+
//#endregion
|
|
2298
|
+
//#region src/commands/nginx/help.ts
|
|
2221
2299
|
function showNginxHelp(subcommand) {
|
|
2222
2300
|
if (subcommand === "get") console.log(`
|
|
2223
2301
|
${colors.bold("forge nginx get")} - Get nginx configuration
|
|
@@ -2249,6 +2327,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2249
2327
|
Run ${colors.cyan("forge nginx <subcommand> --help")} for details.
|
|
2250
2328
|
`);
|
|
2251
2329
|
}
|
|
2330
|
+
//#endregion
|
|
2331
|
+
//#region src/commands/nginx-templates/handlers.ts
|
|
2252
2332
|
async function nginxTemplatesList(ctx) {
|
|
2253
2333
|
const server = String(ctx.options.server ?? "");
|
|
2254
2334
|
if (!server) exitWithValidationError("server_id", "forge nginx-templates list --server <server_id>", ctx.formatter);
|
|
@@ -2313,11 +2393,14 @@ async function nginxTemplatesUpdate(args, ctx) {
|
|
|
2313
2393
|
await runCommand(async () => {
|
|
2314
2394
|
const token = ctx.getToken();
|
|
2315
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;
|
|
2316
2399
|
const result = await updateNginxTemplate({
|
|
2317
|
-
server_id
|
|
2400
|
+
server_id,
|
|
2318
2401
|
id,
|
|
2319
|
-
name
|
|
2320
|
-
content
|
|
2402
|
+
name,
|
|
2403
|
+
content
|
|
2321
2404
|
}, execCtx);
|
|
2322
2405
|
ctx.formatter.outputOne(result.data, [
|
|
2323
2406
|
"id",
|
|
@@ -2341,7 +2424,9 @@ async function nginxTemplatesDelete(args, ctx) {
|
|
|
2341
2424
|
ctx.formatter.success(`Nginx template ${id} deleted.`);
|
|
2342
2425
|
}, ctx.formatter);
|
|
2343
2426
|
}
|
|
2344
|
-
|
|
2427
|
+
//#endregion
|
|
2428
|
+
//#region src/commands/nginx-templates/command.ts
|
|
2429
|
+
var handleNginxTemplatesCommand = createCommandRouter({
|
|
2345
2430
|
resource: "nginx-templates",
|
|
2346
2431
|
handlers: {
|
|
2347
2432
|
list: nginxTemplatesList,
|
|
@@ -2357,6 +2442,8 @@ const handleNginxTemplatesCommand = createCommandRouter({
|
|
|
2357
2442
|
"delete"
|
|
2358
2443
|
]
|
|
2359
2444
|
});
|
|
2445
|
+
//#endregion
|
|
2446
|
+
//#region src/commands/nginx-templates/help.ts
|
|
2360
2447
|
function showNginxTemplatesHelp(subcommand) {
|
|
2361
2448
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2362
2449
|
${colors.bold("forge nginx-templates list")} - List Nginx templates on a server
|
|
@@ -2424,6 +2511,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2424
2511
|
Run ${colors.cyan("forge nginx-templates <subcommand> --help")} for details.
|
|
2425
2512
|
`);
|
|
2426
2513
|
}
|
|
2514
|
+
//#endregion
|
|
2515
|
+
//#region src/commands/recipes/handlers.ts
|
|
2427
2516
|
async function recipesList(ctx) {
|
|
2428
2517
|
await runCommand(async () => {
|
|
2429
2518
|
const token = ctx.getToken();
|
|
@@ -2492,7 +2581,9 @@ async function recipesRun(args, ctx) {
|
|
|
2492
2581
|
ctx.formatter.success(`Recipe ${id} dispatched to ${servers.length} server(s).`);
|
|
2493
2582
|
}, ctx.formatter);
|
|
2494
2583
|
}
|
|
2495
|
-
|
|
2584
|
+
//#endregion
|
|
2585
|
+
//#region src/commands/recipes/command.ts
|
|
2586
|
+
var handleRecipesCommand = createCommandRouter({
|
|
2496
2587
|
resource: "recipes",
|
|
2497
2588
|
handlers: {
|
|
2498
2589
|
list: recipesList,
|
|
@@ -2503,6 +2594,8 @@ const handleRecipesCommand = createCommandRouter({
|
|
|
2503
2594
|
},
|
|
2504
2595
|
writeSubcommands: ["update", "run"]
|
|
2505
2596
|
});
|
|
2597
|
+
//#endregion
|
|
2598
|
+
//#region src/commands/recipes/help.ts
|
|
2506
2599
|
function showRecipesHelp(subcommand) {
|
|
2507
2600
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2508
2601
|
${colors.bold("forge recipes list")} - List all recipes
|
|
@@ -2554,6 +2647,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2554
2647
|
Run ${colors.cyan("forge recipes <subcommand> --help")} for details.
|
|
2555
2648
|
`);
|
|
2556
2649
|
}
|
|
2650
|
+
//#endregion
|
|
2651
|
+
//#region src/commands/redirect-rules/handlers.ts
|
|
2557
2652
|
function requireServerAndSiteRaw$1(ctx, usage) {
|
|
2558
2653
|
const server = String(ctx.options.server ?? "");
|
|
2559
2654
|
const site = String(ctx.options.site ?? "");
|
|
@@ -2644,7 +2739,9 @@ async function redirectRulesDelete(args, ctx) {
|
|
|
2644
2739
|
ctx.formatter.success(`Redirect rule ${id} deleted.`);
|
|
2645
2740
|
}, ctx.formatter);
|
|
2646
2741
|
}
|
|
2647
|
-
|
|
2742
|
+
//#endregion
|
|
2743
|
+
//#region src/commands/redirect-rules/command.ts
|
|
2744
|
+
var handleRedirectRulesCommand = createCommandRouter({
|
|
2648
2745
|
resource: "redirect-rules",
|
|
2649
2746
|
handlers: {
|
|
2650
2747
|
list: redirectRulesList,
|
|
@@ -2655,6 +2752,8 @@ const handleRedirectRulesCommand = createCommandRouter({
|
|
|
2655
2752
|
},
|
|
2656
2753
|
writeSubcommands: ["create", "delete"]
|
|
2657
2754
|
});
|
|
2755
|
+
//#endregion
|
|
2756
|
+
//#region src/commands/redirect-rules/help.ts
|
|
2658
2757
|
function showRedirectRulesHelp(subcommand) {
|
|
2659
2758
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2660
2759
|
${colors.bold("forge redirect-rules list")} - List redirect rules for a site
|
|
@@ -2712,6 +2811,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2712
2811
|
Run ${colors.cyan("forge redirect-rules <subcommand> --help")} for details.
|
|
2713
2812
|
`);
|
|
2714
2813
|
}
|
|
2814
|
+
//#endregion
|
|
2815
|
+
//#region src/commands/scheduled-jobs/handlers.ts
|
|
2715
2816
|
async function scheduledJobsList(ctx) {
|
|
2716
2817
|
const server = String(ctx.options.server ?? "");
|
|
2717
2818
|
const site = ctx.options.site ? String(ctx.options.site) : void 0;
|
|
@@ -2742,10 +2843,11 @@ async function scheduledJobsGet(args, ctx) {
|
|
|
2742
2843
|
const token = ctx.getToken();
|
|
2743
2844
|
const execCtx = ctx.createExecutorContext(token);
|
|
2744
2845
|
const server_id = await resolveServerId(server, execCtx);
|
|
2846
|
+
const site_id = site ? await resolveSiteId(site, server_id, execCtx) : void 0;
|
|
2745
2847
|
const result = await getScheduledJob({
|
|
2746
2848
|
server_id,
|
|
2747
2849
|
id,
|
|
2748
|
-
site_id
|
|
2850
|
+
site_id
|
|
2749
2851
|
}, execCtx);
|
|
2750
2852
|
ctx.formatter.outputOne(result.data, [
|
|
2751
2853
|
"id",
|
|
@@ -2800,15 +2902,18 @@ async function scheduledJobsDelete(args, ctx) {
|
|
|
2800
2902
|
const token = ctx.getToken();
|
|
2801
2903
|
const execCtx = ctx.createExecutorContext(token);
|
|
2802
2904
|
const server_id = await resolveServerId(server, execCtx);
|
|
2905
|
+
const site_id = site ? await resolveSiteId(site, server_id, execCtx) : void 0;
|
|
2803
2906
|
await deleteScheduledJob({
|
|
2804
2907
|
server_id,
|
|
2805
2908
|
id,
|
|
2806
|
-
site_id
|
|
2909
|
+
site_id
|
|
2807
2910
|
}, execCtx);
|
|
2808
2911
|
ctx.formatter.success(`Scheduled job ${id} deleted.`);
|
|
2809
2912
|
}, ctx.formatter);
|
|
2810
2913
|
}
|
|
2811
|
-
|
|
2914
|
+
//#endregion
|
|
2915
|
+
//#region src/commands/scheduled-jobs/command.ts
|
|
2916
|
+
var handleScheduledJobsCommand = createCommandRouter({
|
|
2812
2917
|
resource: "scheduled-jobs",
|
|
2813
2918
|
handlers: {
|
|
2814
2919
|
list: scheduledJobsList,
|
|
@@ -2819,6 +2924,8 @@ const handleScheduledJobsCommand = createCommandRouter({
|
|
|
2819
2924
|
},
|
|
2820
2925
|
writeSubcommands: ["create", "delete"]
|
|
2821
2926
|
});
|
|
2927
|
+
//#endregion
|
|
2928
|
+
//#region src/commands/scheduled-jobs/help.ts
|
|
2822
2929
|
function showScheduledJobsHelp(subcommand) {
|
|
2823
2930
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2824
2931
|
${colors.bold("forge scheduled-jobs list")} - List scheduled jobs on a server
|
|
@@ -2872,6 +2979,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
2872
2979
|
Run ${colors.cyan("forge scheduled-jobs <subcommand> --help")} for details.
|
|
2873
2980
|
`);
|
|
2874
2981
|
}
|
|
2982
|
+
//#endregion
|
|
2983
|
+
//#region src/commands/security-rules/handlers.ts
|
|
2875
2984
|
function requireServerAndSiteRaw(ctx, usage) {
|
|
2876
2985
|
const server = String(ctx.options.server ?? "");
|
|
2877
2986
|
const site = String(ctx.options.site ?? "");
|
|
@@ -2987,7 +3096,9 @@ async function securityRulesDelete(args, ctx) {
|
|
|
2987
3096
|
ctx.formatter.success(`Security rule ${id} deleted.`);
|
|
2988
3097
|
}, ctx.formatter);
|
|
2989
3098
|
}
|
|
2990
|
-
|
|
3099
|
+
//#endregion
|
|
3100
|
+
//#region src/commands/security-rules/command.ts
|
|
3101
|
+
var handleSecurityRulesCommand = createCommandRouter({
|
|
2991
3102
|
resource: "security-rules",
|
|
2992
3103
|
handlers: {
|
|
2993
3104
|
list: securityRulesList,
|
|
@@ -3003,6 +3114,8 @@ const handleSecurityRulesCommand = createCommandRouter({
|
|
|
3003
3114
|
"delete"
|
|
3004
3115
|
]
|
|
3005
3116
|
});
|
|
3117
|
+
//#endregion
|
|
3118
|
+
//#region src/commands/security-rules/help.ts
|
|
3006
3119
|
function showSecurityRulesHelp(subcommand) {
|
|
3007
3120
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3008
3121
|
${colors.bold("forge security-rules list")} - List security rules for a site
|
|
@@ -3072,6 +3185,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
3072
3185
|
Run ${colors.cyan("forge security-rules <subcommand> --help")} for details.
|
|
3073
3186
|
`);
|
|
3074
3187
|
}
|
|
3188
|
+
//#endregion
|
|
3189
|
+
//#region src/commands/servers/handlers.ts
|
|
3075
3190
|
/**
|
|
3076
3191
|
* CLI handlers for servers commands.
|
|
3077
3192
|
* Delegates all HTTP logic to forge-core executors.
|
|
@@ -3121,7 +3236,9 @@ async function serversReboot(args, ctx) {
|
|
|
3121
3236
|
ctx.formatter.success(`Server ${server_id} reboot initiated.`);
|
|
3122
3237
|
}, ctx.formatter);
|
|
3123
3238
|
}
|
|
3124
|
-
|
|
3239
|
+
//#endregion
|
|
3240
|
+
//#region src/commands/servers/command.ts
|
|
3241
|
+
var handleServersCommand = createCommandRouter({
|
|
3125
3242
|
resource: "servers",
|
|
3126
3243
|
handlers: {
|
|
3127
3244
|
list: serversList,
|
|
@@ -3131,6 +3248,8 @@ const handleServersCommand = createCommandRouter({
|
|
|
3131
3248
|
},
|
|
3132
3249
|
writeSubcommands: ["reboot"]
|
|
3133
3250
|
});
|
|
3251
|
+
//#endregion
|
|
3252
|
+
//#region src/commands/servers/help.ts
|
|
3134
3253
|
function showServersHelp(subcommand) {
|
|
3135
3254
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3136
3255
|
${colors.bold("forge servers list")} - List all servers
|
|
@@ -3201,6 +3320,8 @@ ${colors.bold("EXAMPLES:")}
|
|
|
3201
3320
|
Run ${colors.cyan("forge servers <subcommand> --help")} for subcommand details.
|
|
3202
3321
|
`);
|
|
3203
3322
|
}
|
|
3323
|
+
//#endregion
|
|
3324
|
+
//#region src/commands/sites/handlers.ts
|
|
3204
3325
|
async function sitesList(ctx) {
|
|
3205
3326
|
const server = String(ctx.options.server ?? "");
|
|
3206
3327
|
if (!server) exitWithValidationError("server_id", "forge sites list --server <server_id>", ctx.formatter);
|
|
@@ -3276,7 +3397,9 @@ async function sitesUpdate(args, ctx) {
|
|
|
3276
3397
|
]);
|
|
3277
3398
|
}, ctx.formatter);
|
|
3278
3399
|
}
|
|
3279
|
-
|
|
3400
|
+
//#endregion
|
|
3401
|
+
//#region src/commands/sites/command.ts
|
|
3402
|
+
var handleSitesCommand = createCommandRouter({
|
|
3280
3403
|
resource: "sites",
|
|
3281
3404
|
handlers: {
|
|
3282
3405
|
list: sitesList,
|
|
@@ -3285,6 +3408,8 @@ const handleSitesCommand = createCommandRouter({
|
|
|
3285
3408
|
update: [sitesUpdate, "args"]
|
|
3286
3409
|
}
|
|
3287
3410
|
});
|
|
3411
|
+
//#endregion
|
|
3412
|
+
//#region src/commands/sites/help.ts
|
|
3288
3413
|
function showSitesHelp(subcommand) {
|
|
3289
3414
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3290
3415
|
${colors.bold("forge sites list")} - List sites on a server
|
|
@@ -3335,6 +3460,172 @@ ${colors.bold("EXAMPLES:")}
|
|
|
3335
3460
|
Run ${colors.cyan("forge sites <subcommand> --help")} for subcommand details.
|
|
3336
3461
|
`);
|
|
3337
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
|
|
3338
3629
|
async function sshKeysList(ctx) {
|
|
3339
3630
|
const server = String(ctx.options.server ?? "");
|
|
3340
3631
|
if (!server) exitWithValidationError("server_id", "forge ssh-keys list --server <server_id>", ctx.formatter);
|
|
@@ -3369,7 +3660,9 @@ async function sshKeysGet(args, ctx) {
|
|
|
3369
3660
|
]);
|
|
3370
3661
|
}, ctx.formatter);
|
|
3371
3662
|
}
|
|
3372
|
-
|
|
3663
|
+
//#endregion
|
|
3664
|
+
//#region src/commands/ssh-keys/command.ts
|
|
3665
|
+
var handleSshKeysCommand = createCommandRouter({
|
|
3373
3666
|
resource: "ssh-keys",
|
|
3374
3667
|
handlers: {
|
|
3375
3668
|
list: sshKeysList,
|
|
@@ -3377,6 +3670,8 @@ const handleSshKeysCommand = createCommandRouter({
|
|
|
3377
3670
|
get: [sshKeysGet, "args"]
|
|
3378
3671
|
}
|
|
3379
3672
|
});
|
|
3673
|
+
//#endregion
|
|
3674
|
+
//#region src/commands/ssh-keys/help.ts
|
|
3380
3675
|
function showSshKeysHelp(subcommand) {
|
|
3381
3676
|
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
3382
3677
|
${colors.bold("forge ssh-keys list")} - List SSH keys on a server
|
|
@@ -3407,6 +3702,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
3407
3702
|
Run ${colors.cyan("forge ssh-keys <subcommand> --help")} for details.
|
|
3408
3703
|
`);
|
|
3409
3704
|
}
|
|
3705
|
+
//#endregion
|
|
3706
|
+
//#region src/commands/user/handlers.ts
|
|
3410
3707
|
async function userGet(ctx) {
|
|
3411
3708
|
await runCommand(async () => {
|
|
3412
3709
|
const token = ctx.getToken();
|
|
@@ -3414,10 +3711,14 @@ async function userGet(ctx) {
|
|
|
3414
3711
|
ctx.formatter.output(result.data);
|
|
3415
3712
|
}, ctx.formatter);
|
|
3416
3713
|
}
|
|
3417
|
-
|
|
3714
|
+
//#endregion
|
|
3715
|
+
//#region src/commands/user/command.ts
|
|
3716
|
+
var handleUserCommand = createCommandRouter({
|
|
3418
3717
|
resource: "user",
|
|
3419
3718
|
handlers: { get: userGet }
|
|
3420
3719
|
});
|
|
3720
|
+
//#endregion
|
|
3721
|
+
//#region src/commands/user/help.ts
|
|
3421
3722
|
function showUserHelp(subcommand) {
|
|
3422
3723
|
if (subcommand === "get") console.log(`
|
|
3423
3724
|
${colors.bold("forge user get")} - Get the authenticated user profile
|
|
@@ -3443,6 +3744,8 @@ ${colors.bold("OPTIONS:")}
|
|
|
3443
3744
|
Run ${colors.cyan("forge user <subcommand> --help")} for details.
|
|
3444
3745
|
`);
|
|
3445
3746
|
}
|
|
3747
|
+
//#endregion
|
|
3748
|
+
//#region src/utils/args.ts
|
|
3446
3749
|
function parseArgs(argv = process.argv.slice(2)) {
|
|
3447
3750
|
const options = {};
|
|
3448
3751
|
const positional = [];
|
|
@@ -3479,7 +3782,9 @@ function parseArgs(argv = process.argv.slice(2)) {
|
|
|
3479
3782
|
positional
|
|
3480
3783
|
};
|
|
3481
3784
|
}
|
|
3482
|
-
|
|
3785
|
+
//#endregion
|
|
3786
|
+
//#region src/cli.ts
|
|
3787
|
+
var VERSION = "0.4.5";
|
|
3483
3788
|
function showHelp() {
|
|
3484
3789
|
console.log(`
|
|
3485
3790
|
${colors.bold("forge")} v${VERSION}
|
|
@@ -3538,6 +3843,9 @@ ${colors.bold("COMMANDS:")}
|
|
|
3538
3843
|
list, ls List firewall rules (requires --server)
|
|
3539
3844
|
get <id> Get firewall rule details (requires --server)
|
|
3540
3845
|
|
|
3846
|
+
ssh <server> Open an SSH session to a server
|
|
3847
|
+
--user <name> (default: forge), --private, --port <n>
|
|
3848
|
+
|
|
3541
3849
|
ssh-keys Manage SSH keys
|
|
3542
3850
|
list, ls List SSH keys (requires --server)
|
|
3543
3851
|
get <id> Get SSH key details (requires --server)
|
|
@@ -3740,6 +4048,13 @@ async function main() {
|
|
|
3740
4048
|
}
|
|
3741
4049
|
await handleFirewallRulesCommand(subcommand ?? "list", positional, options);
|
|
3742
4050
|
break;
|
|
4051
|
+
case "ssh":
|
|
4052
|
+
if (wantsHelp) {
|
|
4053
|
+
showSshHelp();
|
|
4054
|
+
process.exit(0);
|
|
4055
|
+
}
|
|
4056
|
+
await handleSshCommand(subcommand, positional, options);
|
|
4057
|
+
break;
|
|
3743
4058
|
case "ssh-keys":
|
|
3744
4059
|
if (wantsHelp) {
|
|
3745
4060
|
showSshKeysHelp(subcommand);
|
|
@@ -3831,5 +4146,6 @@ main().catch((error) => {
|
|
|
3831
4146
|
console.error(colors.red("Unhandled error:"), error);
|
|
3832
4147
|
process.exit(1);
|
|
3833
4148
|
});
|
|
4149
|
+
//#endregion
|
|
3834
4150
|
|
|
3835
4151
|
//# sourceMappingURL=cli.js.map
|