@studiometa/forge-cli 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2746 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/backups/command.d.ts +2 -0
- package/dist/commands/backups/command.d.ts.map +1 -0
- package/dist/commands/backups/handlers.d.ts +6 -0
- package/dist/commands/backups/handlers.d.ts.map +1 -0
- package/dist/commands/backups/help.d.ts +2 -0
- package/dist/commands/backups/help.d.ts.map +1 -0
- package/dist/commands/backups/index.d.ts +3 -0
- package/dist/commands/backups/index.d.ts.map +1 -0
- package/dist/commands/certificates/command.d.ts +2 -0
- package/dist/commands/certificates/command.d.ts.map +1 -0
- package/dist/commands/certificates/handlers.d.ts +5 -0
- package/dist/commands/certificates/handlers.d.ts.map +1 -0
- package/dist/commands/certificates/help.d.ts +2 -0
- package/dist/commands/certificates/help.d.ts.map +1 -0
- package/dist/commands/certificates/index.d.ts +3 -0
- package/dist/commands/certificates/index.d.ts.map +1 -0
- package/dist/commands/commands/command.d.ts +2 -0
- package/dist/commands/commands/command.d.ts.map +1 -0
- package/dist/commands/commands/handlers.d.ts +5 -0
- package/dist/commands/commands/handlers.d.ts.map +1 -0
- package/dist/commands/commands/help.d.ts +2 -0
- package/dist/commands/commands/help.d.ts.map +1 -0
- package/dist/commands/commands/index.d.ts +3 -0
- package/dist/commands/commands/index.d.ts.map +1 -0
- package/dist/commands/config.d.ts +6 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/daemons/command.d.ts +2 -0
- package/dist/commands/daemons/command.d.ts.map +1 -0
- package/dist/commands/daemons/handlers.d.ts +5 -0
- package/dist/commands/daemons/handlers.d.ts.map +1 -0
- package/dist/commands/daemons/help.d.ts +2 -0
- package/dist/commands/daemons/help.d.ts.map +1 -0
- package/dist/commands/daemons/index.d.ts +3 -0
- package/dist/commands/daemons/index.d.ts.map +1 -0
- package/dist/commands/database-users/command.d.ts +2 -0
- package/dist/commands/database-users/command.d.ts.map +1 -0
- package/dist/commands/database-users/handlers.d.ts +6 -0
- package/dist/commands/database-users/handlers.d.ts.map +1 -0
- package/dist/commands/database-users/help.d.ts +2 -0
- package/dist/commands/database-users/help.d.ts.map +1 -0
- package/dist/commands/database-users/index.d.ts +3 -0
- package/dist/commands/database-users/index.d.ts.map +1 -0
- package/dist/commands/databases/command.d.ts +2 -0
- package/dist/commands/databases/command.d.ts.map +1 -0
- package/dist/commands/databases/handlers.d.ts +4 -0
- package/dist/commands/databases/handlers.d.ts.map +1 -0
- package/dist/commands/databases/help.d.ts +2 -0
- package/dist/commands/databases/help.d.ts.map +1 -0
- package/dist/commands/databases/index.d.ts +3 -0
- package/dist/commands/databases/index.d.ts.map +1 -0
- package/dist/commands/deployments/command.d.ts +2 -0
- package/dist/commands/deployments/command.d.ts.map +1 -0
- package/dist/commands/deployments/handlers.d.ts +4 -0
- package/dist/commands/deployments/handlers.d.ts.map +1 -0
- package/dist/commands/deployments/help.d.ts +2 -0
- package/dist/commands/deployments/help.d.ts.map +1 -0
- package/dist/commands/deployments/index.d.ts +3 -0
- package/dist/commands/deployments/index.d.ts.map +1 -0
- package/dist/commands/env/command.d.ts +2 -0
- package/dist/commands/env/command.d.ts.map +1 -0
- package/dist/commands/env/handlers.d.ts +4 -0
- package/dist/commands/env/handlers.d.ts.map +1 -0
- package/dist/commands/env/help.d.ts +2 -0
- package/dist/commands/env/help.d.ts.map +1 -0
- package/dist/commands/env/index.d.ts +3 -0
- package/dist/commands/env/index.d.ts.map +1 -0
- package/dist/commands/firewall-rules/command.d.ts +2 -0
- package/dist/commands/firewall-rules/command.d.ts.map +1 -0
- package/dist/commands/firewall-rules/handlers.d.ts +4 -0
- package/dist/commands/firewall-rules/handlers.d.ts.map +1 -0
- package/dist/commands/firewall-rules/help.d.ts +2 -0
- package/dist/commands/firewall-rules/help.d.ts.map +1 -0
- package/dist/commands/firewall-rules/index.d.ts +3 -0
- package/dist/commands/firewall-rules/index.d.ts.map +1 -0
- package/dist/commands/monitors/command.d.ts +2 -0
- package/dist/commands/monitors/command.d.ts.map +1 -0
- package/dist/commands/monitors/handlers.d.ts +6 -0
- package/dist/commands/monitors/handlers.d.ts.map +1 -0
- package/dist/commands/monitors/help.d.ts +2 -0
- package/dist/commands/monitors/help.d.ts.map +1 -0
- package/dist/commands/monitors/index.d.ts +3 -0
- package/dist/commands/monitors/index.d.ts.map +1 -0
- package/dist/commands/nginx/command.d.ts +2 -0
- package/dist/commands/nginx/command.d.ts.map +1 -0
- package/dist/commands/nginx/handlers.d.ts +4 -0
- package/dist/commands/nginx/handlers.d.ts.map +1 -0
- package/dist/commands/nginx/help.d.ts +2 -0
- package/dist/commands/nginx/help.d.ts.map +1 -0
- package/dist/commands/nginx/index.d.ts +3 -0
- package/dist/commands/nginx/index.d.ts.map +1 -0
- package/dist/commands/nginx-templates/command.d.ts +2 -0
- package/dist/commands/nginx-templates/command.d.ts.map +1 -0
- package/dist/commands/nginx-templates/handlers.d.ts +7 -0
- package/dist/commands/nginx-templates/handlers.d.ts.map +1 -0
- package/dist/commands/nginx-templates/help.d.ts +2 -0
- package/dist/commands/nginx-templates/help.d.ts.map +1 -0
- package/dist/commands/nginx-templates/index.d.ts +3 -0
- package/dist/commands/nginx-templates/index.d.ts.map +1 -0
- package/dist/commands/recipes/command.d.ts +2 -0
- package/dist/commands/recipes/command.d.ts.map +1 -0
- package/dist/commands/recipes/handlers.d.ts +5 -0
- package/dist/commands/recipes/handlers.d.ts.map +1 -0
- package/dist/commands/recipes/help.d.ts +2 -0
- package/dist/commands/recipes/help.d.ts.map +1 -0
- package/dist/commands/recipes/index.d.ts +3 -0
- package/dist/commands/recipes/index.d.ts.map +1 -0
- package/dist/commands/redirect-rules/command.d.ts +2 -0
- package/dist/commands/redirect-rules/command.d.ts.map +1 -0
- package/dist/commands/redirect-rules/handlers.d.ts +6 -0
- package/dist/commands/redirect-rules/handlers.d.ts.map +1 -0
- package/dist/commands/redirect-rules/help.d.ts +2 -0
- package/dist/commands/redirect-rules/help.d.ts.map +1 -0
- package/dist/commands/redirect-rules/index.d.ts +3 -0
- package/dist/commands/redirect-rules/index.d.ts.map +1 -0
- package/dist/commands/scheduled-jobs/command.d.ts +2 -0
- package/dist/commands/scheduled-jobs/command.d.ts.map +1 -0
- package/dist/commands/scheduled-jobs/handlers.d.ts +6 -0
- package/dist/commands/scheduled-jobs/handlers.d.ts.map +1 -0
- package/dist/commands/scheduled-jobs/help.d.ts +2 -0
- package/dist/commands/scheduled-jobs/help.d.ts.map +1 -0
- package/dist/commands/scheduled-jobs/index.d.ts +3 -0
- package/dist/commands/scheduled-jobs/index.d.ts.map +1 -0
- package/dist/commands/security-rules/command.d.ts +2 -0
- package/dist/commands/security-rules/command.d.ts.map +1 -0
- package/dist/commands/security-rules/handlers.d.ts +6 -0
- package/dist/commands/security-rules/handlers.d.ts.map +1 -0
- package/dist/commands/security-rules/help.d.ts +2 -0
- package/dist/commands/security-rules/help.d.ts.map +1 -0
- package/dist/commands/security-rules/index.d.ts +3 -0
- package/dist/commands/security-rules/index.d.ts.map +1 -0
- package/dist/commands/servers/command.d.ts +2 -0
- package/dist/commands/servers/command.d.ts.map +1 -0
- package/dist/commands/servers/handlers.d.ts +18 -0
- package/dist/commands/servers/handlers.d.ts.map +1 -0
- package/dist/commands/servers/help.d.ts +2 -0
- package/dist/commands/servers/help.d.ts.map +1 -0
- package/dist/commands/servers/index.d.ts +3 -0
- package/dist/commands/servers/index.d.ts.map +1 -0
- package/dist/commands/sites/command.d.ts +2 -0
- package/dist/commands/sites/command.d.ts.map +1 -0
- package/dist/commands/sites/handlers.d.ts +4 -0
- package/dist/commands/sites/handlers.d.ts.map +1 -0
- package/dist/commands/sites/help.d.ts +2 -0
- package/dist/commands/sites/help.d.ts.map +1 -0
- package/dist/commands/sites/index.d.ts +3 -0
- package/dist/commands/sites/index.d.ts.map +1 -0
- package/dist/commands/ssh-keys/command.d.ts +2 -0
- package/dist/commands/ssh-keys/command.d.ts.map +1 -0
- package/dist/commands/ssh-keys/handlers.d.ts +4 -0
- package/dist/commands/ssh-keys/handlers.d.ts.map +1 -0
- package/dist/commands/ssh-keys/help.d.ts +2 -0
- package/dist/commands/ssh-keys/help.d.ts.map +1 -0
- package/dist/commands/ssh-keys/index.d.ts +3 -0
- package/dist/commands/ssh-keys/index.d.ts.map +1 -0
- package/dist/commands/user/command.d.ts +2 -0
- package/dist/commands/user/command.d.ts.map +1 -0
- package/dist/commands/user/handlers.d.ts +3 -0
- package/dist/commands/user/handlers.d.ts.map +1 -0
- package/dist/commands/user/help.d.ts +2 -0
- package/dist/commands/user/help.d.ts.map +1 -0
- package/dist/commands/user/index.d.ts +3 -0
- package/dist/commands/user/index.d.ts.map +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/context.d.ts +50 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/error-handler-BahHMt6t.js +396 -0
- package/dist/error-handler-BahHMt6t.js.map +1 -0
- package/dist/error-handler.d.ts +39 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/errors.d.ts +45 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/output.d.ts +47 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/args.d.ts +14 -0
- package/dist/utils/args.d.ts.map +1 -0
- package/dist/utils/colors.d.ts +17 -0
- package/dist/utils/colors.d.ts.map +1 -0
- package/dist/utils/command-router.d.ts +47 -0
- package/dist/utils/command-router.d.ts.map +1 -0
- package/dist/utils/resolve.d.ts +25 -0
- package/dist/utils/resolve.d.ts.map +1 -0
- package/package.json +41 -1
package/dist/cli.js
ADDED
|
@@ -0,0 +1,2746 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { a as createContext, c as colors, d as deleteToken, i as runCommand, l as setColorEnabled, m as setToken, n as exitWithValidationError, p as getToken, s as OutputFormatter, u as createConfigStore, v as ValidationError } from "./error-handler-BahHMt6t.js";
|
|
3
|
+
import { activateCertificate, createBackupConfig, createCommand, createDatabaseUser, createMonitor, createNginxTemplate, createRedirectRule, createScheduledJob, createSecurityRule, deleteBackupConfig, deleteDatabaseUser, deleteMonitor, deleteNginxTemplate, deleteRedirectRule, deleteScheduledJob, deleteSecurityRule, deploySite, getBackupConfig, getCertificate, getCommand, getDaemon, getDatabase, getDatabaseUser, getEnv, getFirewallRule, getMonitor, getNginxConfig, getNginxTemplate, getRecipe, getRedirectRule, getScheduledJob, getSecurityRule, getServer, getSite, getSshKey, getUser, listBackupConfigs, listCertificates, listCommands, listDaemons, listDatabaseUsers, listDatabases, listDeployments, listFirewallRules, listMonitors, listNginxTemplates, listRecipes, listRedirectRules, listScheduledJobs, listSecurityRules, listServers, listSites, listSshKeys, rebootServer, restartDaemon, runRecipe, updateEnv, updateNginxConfig, updateNginxTemplate } from "@studiometa/forge-core";
|
|
4
|
+
/**
|
|
5
|
+
* Creates a command router function that dispatches to the appropriate handler.
|
|
6
|
+
*/
|
|
7
|
+
function createCommandRouter(config) {
|
|
8
|
+
return async function(subcommand, args, options) {
|
|
9
|
+
const formatter = new OutputFormatter(options.format ?? options.f ?? "human", options["no-color"] === true);
|
|
10
|
+
const ctx = createContext(options);
|
|
11
|
+
const handler = config.handlers[subcommand];
|
|
12
|
+
if (!handler) {
|
|
13
|
+
formatter.error(`Unknown ${config.resource} subcommand: ${subcommand}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(handler)) await handler[0](args, ctx);
|
|
18
|
+
else await handler(ctx);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Smart resolution utilities for --server and --site options.
|
|
23
|
+
*
|
|
24
|
+
* Accepts numeric IDs (used as-is) or plain strings (resolved by name/partial match).
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a --server value to a numeric server ID string.
|
|
28
|
+
*
|
|
29
|
+
* - Numeric string → returned as-is (no API call)
|
|
30
|
+
* - Plain string → fetch all servers, exact match first, then partial match
|
|
31
|
+
* - 0 matches → ValidationError listing available servers
|
|
32
|
+
* - 2+ matches → ValidationError listing ambiguous matches
|
|
33
|
+
*/
|
|
34
|
+
async function resolveServerId(value, execCtx) {
|
|
35
|
+
if (/^\d+$/.test(value)) return value;
|
|
36
|
+
const servers = (await listServers({}, execCtx)).data;
|
|
37
|
+
const lower = value.toLowerCase();
|
|
38
|
+
const exact = servers.filter((s) => s.name.toLowerCase() === lower);
|
|
39
|
+
if (exact.length === 1) return String(exact[0].id);
|
|
40
|
+
const partial = servers.filter((s) => s.name.toLowerCase().includes(lower));
|
|
41
|
+
if (partial.length === 0) {
|
|
42
|
+
const available = servers.map((s) => ` ${s.name} (${s.id})`).join("\n");
|
|
43
|
+
throw new ValidationError(`No server found matching "${value}"`, "server", [`Available servers:\n${available}`]);
|
|
44
|
+
}
|
|
45
|
+
if (partial.length > 1) {
|
|
46
|
+
const matches = partial.map((s) => ` ${s.name} (${s.id})`).join("\n");
|
|
47
|
+
throw new ValidationError(`Ambiguous server name "${value}" — ${partial.length} matches found`, "server", [`Matching servers:\n${matches}`, "Use a more specific name or pass the numeric ID"]);
|
|
48
|
+
}
|
|
49
|
+
return String(partial[0].id);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a --site value to a numeric site ID string.
|
|
53
|
+
*
|
|
54
|
+
* - Numeric string → returned as-is (no API call)
|
|
55
|
+
* - Plain string → fetch all sites for the server, exact domain match first, then partial
|
|
56
|
+
* - 0 matches → ValidationError listing available sites
|
|
57
|
+
* - 2+ matches → ValidationError listing ambiguous matches
|
|
58
|
+
*/
|
|
59
|
+
async function resolveSiteId(value, serverId, execCtx) {
|
|
60
|
+
if (/^\d+$/.test(value)) return value;
|
|
61
|
+
const sites = (await listSites({ server_id: serverId }, execCtx)).data;
|
|
62
|
+
const lower = value.toLowerCase();
|
|
63
|
+
const exact = sites.filter((s) => s.name.toLowerCase() === lower);
|
|
64
|
+
if (exact.length === 1) return String(exact[0].id);
|
|
65
|
+
const partial = sites.filter((s) => s.name.toLowerCase().includes(lower));
|
|
66
|
+
if (partial.length === 0) {
|
|
67
|
+
const available = sites.map((s) => ` ${s.name} (${s.id})`).join("\n");
|
|
68
|
+
throw new ValidationError(`No site found matching "${value}" on server ${serverId}`, "site", [`Available sites:\n${available}`]);
|
|
69
|
+
}
|
|
70
|
+
if (partial.length > 1) {
|
|
71
|
+
const matches = partial.map((s) => ` ${s.name} (${s.id})`).join("\n");
|
|
72
|
+
throw new ValidationError(`Ambiguous site name "${value}" — ${partial.length} matches found`, "site", [`Matching sites:\n${matches}`, "Use a more specific name or pass the numeric ID"]);
|
|
73
|
+
}
|
|
74
|
+
return String(partial[0].id);
|
|
75
|
+
}
|
|
76
|
+
async function backupsList(ctx) {
|
|
77
|
+
const server = String(ctx.options.server ?? "");
|
|
78
|
+
if (!server) exitWithValidationError("server_id", "forge-cli backups list --server <server_id>", ctx.formatter);
|
|
79
|
+
await runCommand(async () => {
|
|
80
|
+
const token = ctx.getToken();
|
|
81
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
82
|
+
const result = await listBackupConfigs({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
83
|
+
ctx.formatter.outputList(result.data, [
|
|
84
|
+
"id",
|
|
85
|
+
"provider_name",
|
|
86
|
+
"frequency",
|
|
87
|
+
"status"
|
|
88
|
+
], "No backup configurations found.", (b) => `${String(b.id).padEnd(8)} ${b.provider_name.padEnd(20)} ${b.frequency.padEnd(12)} ${b.status}`);
|
|
89
|
+
}, ctx.formatter);
|
|
90
|
+
}
|
|
91
|
+
async function backupsGet(args, ctx) {
|
|
92
|
+
const [id] = args;
|
|
93
|
+
const server = String(ctx.options.server ?? "");
|
|
94
|
+
if (!id) exitWithValidationError("backup_id", "forge-cli backups get <backup_id> --server <server_id>", ctx.formatter);
|
|
95
|
+
if (!server) exitWithValidationError("server_id", "forge-cli backups get <backup_id> --server <server_id>", ctx.formatter);
|
|
96
|
+
await runCommand(async () => {
|
|
97
|
+
const token = ctx.getToken();
|
|
98
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
99
|
+
const result = await getBackupConfig({
|
|
100
|
+
server_id: await resolveServerId(server, execCtx),
|
|
101
|
+
id
|
|
102
|
+
}, execCtx);
|
|
103
|
+
ctx.formatter.outputOne(result.data, [
|
|
104
|
+
"id",
|
|
105
|
+
"provider",
|
|
106
|
+
"provider_name",
|
|
107
|
+
"frequency",
|
|
108
|
+
"retention",
|
|
109
|
+
"status",
|
|
110
|
+
"last_backup_time"
|
|
111
|
+
]);
|
|
112
|
+
}, ctx.formatter);
|
|
113
|
+
}
|
|
114
|
+
async function backupsCreate(ctx) {
|
|
115
|
+
const server = String(ctx.options.server ?? "");
|
|
116
|
+
const provider = String(ctx.options.provider ?? "");
|
|
117
|
+
const frequency = String(ctx.options.frequency ?? "");
|
|
118
|
+
const databasesRaw = ctx.options.databases;
|
|
119
|
+
const databases = Array.isArray(databasesRaw) ? databasesRaw.map(Number) : databasesRaw ? [Number(databasesRaw)] : [];
|
|
120
|
+
if (!server) exitWithValidationError("server_id", "forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
|
|
121
|
+
if (!provider) exitWithValidationError("provider", "forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
|
|
122
|
+
if (!frequency) exitWithValidationError("frequency", "forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
|
|
123
|
+
await runCommand(async () => {
|
|
124
|
+
const token = ctx.getToken();
|
|
125
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
126
|
+
const result = await createBackupConfig({
|
|
127
|
+
server_id: await resolveServerId(server, execCtx),
|
|
128
|
+
provider,
|
|
129
|
+
frequency,
|
|
130
|
+
credentials: {},
|
|
131
|
+
databases
|
|
132
|
+
}, execCtx);
|
|
133
|
+
ctx.formatter.outputOne(result.data, [
|
|
134
|
+
"id",
|
|
135
|
+
"provider",
|
|
136
|
+
"provider_name",
|
|
137
|
+
"frequency",
|
|
138
|
+
"retention",
|
|
139
|
+
"status"
|
|
140
|
+
]);
|
|
141
|
+
}, ctx.formatter);
|
|
142
|
+
}
|
|
143
|
+
async function backupsDelete(args, ctx) {
|
|
144
|
+
const [id] = args;
|
|
145
|
+
const server = String(ctx.options.server ?? "");
|
|
146
|
+
if (!id) exitWithValidationError("backup_id", "forge-cli backups delete <backup_id> --server <server_id>", ctx.formatter);
|
|
147
|
+
if (!server) exitWithValidationError("server_id", "forge-cli backups delete <backup_id> --server <server_id>", ctx.formatter);
|
|
148
|
+
await runCommand(async () => {
|
|
149
|
+
const token = ctx.getToken();
|
|
150
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
151
|
+
await deleteBackupConfig({
|
|
152
|
+
server_id: await resolveServerId(server, execCtx),
|
|
153
|
+
id
|
|
154
|
+
}, execCtx);
|
|
155
|
+
ctx.formatter.success(`Backup configuration ${id} deleted.`);
|
|
156
|
+
}, ctx.formatter);
|
|
157
|
+
}
|
|
158
|
+
const handleBackupsCommand = createCommandRouter({
|
|
159
|
+
resource: "backups",
|
|
160
|
+
handlers: {
|
|
161
|
+
list: backupsList,
|
|
162
|
+
ls: backupsList,
|
|
163
|
+
get: [backupsGet, "args"],
|
|
164
|
+
create: backupsCreate,
|
|
165
|
+
delete: [backupsDelete, "args"]
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
function showBackupsHelp(subcommand) {
|
|
169
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
170
|
+
${colors.bold("forge-cli backups list")} - List backup configurations on a server
|
|
171
|
+
|
|
172
|
+
${colors.bold("USAGE:")}
|
|
173
|
+
forge-cli backups list --server <server_id> [options]
|
|
174
|
+
|
|
175
|
+
${colors.bold("OPTIONS:")}
|
|
176
|
+
--server <id> Server ID (required)
|
|
177
|
+
-f, --format <fmt> Output format: json, human, table
|
|
178
|
+
`);
|
|
179
|
+
else if (subcommand === "get") console.log(`
|
|
180
|
+
${colors.bold("forge-cli backups get")} - Get backup configuration details
|
|
181
|
+
|
|
182
|
+
${colors.bold("USAGE:")}
|
|
183
|
+
forge-cli backups get <backup_id> --server <server_id> [options]
|
|
184
|
+
`);
|
|
185
|
+
else if (subcommand === "create") console.log(`
|
|
186
|
+
${colors.bold("forge-cli backups create")} - Create a new backup configuration
|
|
187
|
+
|
|
188
|
+
${colors.bold("USAGE:")}
|
|
189
|
+
forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency> [options]
|
|
190
|
+
|
|
191
|
+
${colors.bold("OPTIONS:")}
|
|
192
|
+
--server <id> Server ID (required)
|
|
193
|
+
--provider <name> Backup provider (required)
|
|
194
|
+
--frequency <freq> Backup frequency (required)
|
|
195
|
+
--databases <ids> Comma-separated database IDs to back up (optional)
|
|
196
|
+
-f, --format <fmt> Output format: json, human, table
|
|
197
|
+
`);
|
|
198
|
+
else if (subcommand === "delete") console.log(`
|
|
199
|
+
${colors.bold("forge-cli backups delete")} - Delete a backup configuration
|
|
200
|
+
|
|
201
|
+
${colors.bold("USAGE:")}
|
|
202
|
+
forge-cli backups delete <backup_id> --server <server_id> [options]
|
|
203
|
+
`);
|
|
204
|
+
else console.log(`
|
|
205
|
+
${colors.bold("forge-cli backups")} - Manage backup configurations
|
|
206
|
+
|
|
207
|
+
${colors.bold("USAGE:")}
|
|
208
|
+
forge-cli backups <subcommand> [options]
|
|
209
|
+
|
|
210
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
211
|
+
list, ls List backup configurations
|
|
212
|
+
get <id> Get backup configuration details
|
|
213
|
+
create Create a new backup configuration
|
|
214
|
+
delete <id> Delete a backup configuration
|
|
215
|
+
|
|
216
|
+
${colors.bold("OPTIONS:")}
|
|
217
|
+
--server <id> Server ID (required)
|
|
218
|
+
-f, --format <fmt> Output format: json, human, table
|
|
219
|
+
|
|
220
|
+
Run ${colors.cyan("forge-cli backups <subcommand> --help")} for details.
|
|
221
|
+
`);
|
|
222
|
+
}
|
|
223
|
+
function requireServerAndSiteRaw$3(ctx, usage) {
|
|
224
|
+
const server = String(ctx.options.server ?? "");
|
|
225
|
+
const site = String(ctx.options.site ?? "");
|
|
226
|
+
if (!server) exitWithValidationError("server_id", usage, ctx.formatter);
|
|
227
|
+
if (!site) exitWithValidationError("site_id", usage, ctx.formatter);
|
|
228
|
+
return {
|
|
229
|
+
server,
|
|
230
|
+
site
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async function certificatesList(ctx) {
|
|
234
|
+
const { server, site } = requireServerAndSiteRaw$3(ctx, "forge-cli certificates list --server <server_id> --site <site_id>");
|
|
235
|
+
await runCommand(async () => {
|
|
236
|
+
const token = ctx.getToken();
|
|
237
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
238
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
239
|
+
const result = await listCertificates({
|
|
240
|
+
server_id,
|
|
241
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
242
|
+
}, execCtx);
|
|
243
|
+
ctx.formatter.outputList(result.data, [
|
|
244
|
+
"id",
|
|
245
|
+
"domain",
|
|
246
|
+
"type",
|
|
247
|
+
"status",
|
|
248
|
+
"active"
|
|
249
|
+
], "No certificates found.", (c) => `${String(c.id).padEnd(8)} ${c.domain.padEnd(40)} ${c.type.padEnd(10)} ${c.status.padEnd(12)} ${c.active ? "active" : "—"}`);
|
|
250
|
+
}, ctx.formatter);
|
|
251
|
+
}
|
|
252
|
+
async function certificatesGet(args, ctx) {
|
|
253
|
+
const [id] = args;
|
|
254
|
+
const usage = "forge-cli certificates get <cert_id> --server <server_id> --site <site_id>";
|
|
255
|
+
if (!id) exitWithValidationError("certificate_id", usage, ctx.formatter);
|
|
256
|
+
const { server, site } = requireServerAndSiteRaw$3(ctx, usage);
|
|
257
|
+
await runCommand(async () => {
|
|
258
|
+
const token = ctx.getToken();
|
|
259
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
260
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
261
|
+
const result = await getCertificate({
|
|
262
|
+
server_id,
|
|
263
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
264
|
+
id
|
|
265
|
+
}, execCtx);
|
|
266
|
+
ctx.formatter.outputOne(result.data, [
|
|
267
|
+
"id",
|
|
268
|
+
"domain",
|
|
269
|
+
"type",
|
|
270
|
+
"status",
|
|
271
|
+
"request_status",
|
|
272
|
+
"active",
|
|
273
|
+
"existing",
|
|
274
|
+
"created_at"
|
|
275
|
+
]);
|
|
276
|
+
}, ctx.formatter);
|
|
277
|
+
}
|
|
278
|
+
async function certificatesActivate(args, ctx) {
|
|
279
|
+
const [id] = args;
|
|
280
|
+
const usage = "forge-cli certificates activate <cert_id> --server <server_id> --site <site_id>";
|
|
281
|
+
if (!id) exitWithValidationError("certificate_id", usage, ctx.formatter);
|
|
282
|
+
const { server, site } = requireServerAndSiteRaw$3(ctx, usage);
|
|
283
|
+
await runCommand(async () => {
|
|
284
|
+
const token = ctx.getToken();
|
|
285
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
286
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
287
|
+
await activateCertificate({
|
|
288
|
+
server_id,
|
|
289
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
290
|
+
id
|
|
291
|
+
}, execCtx);
|
|
292
|
+
ctx.formatter.success(`Certificate ${id} activated.`);
|
|
293
|
+
}, ctx.formatter);
|
|
294
|
+
}
|
|
295
|
+
const handleCertificatesCommand = createCommandRouter({
|
|
296
|
+
resource: "certificates",
|
|
297
|
+
handlers: {
|
|
298
|
+
list: certificatesList,
|
|
299
|
+
ls: certificatesList,
|
|
300
|
+
get: [certificatesGet, "args"],
|
|
301
|
+
activate: [certificatesActivate, "args"]
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
function showCertificatesHelp(subcommand) {
|
|
305
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
306
|
+
${colors.bold("forge-cli certificates list")} - List certificates for a site
|
|
307
|
+
|
|
308
|
+
${colors.bold("USAGE:")}
|
|
309
|
+
forge-cli certificates list --server <server_id> --site <site_id> [options]
|
|
310
|
+
`);
|
|
311
|
+
else if (subcommand === "get") console.log(`
|
|
312
|
+
${colors.bold("forge-cli certificates get")} - Get certificate details
|
|
313
|
+
|
|
314
|
+
${colors.bold("USAGE:")}
|
|
315
|
+
forge-cli certificates get <cert_id> --server <server_id> --site <site_id>
|
|
316
|
+
`);
|
|
317
|
+
else if (subcommand === "activate") console.log(`
|
|
318
|
+
${colors.bold("forge-cli certificates activate")} - Activate a certificate
|
|
319
|
+
|
|
320
|
+
${colors.bold("USAGE:")}
|
|
321
|
+
forge-cli certificates activate <cert_id> --server <server_id> --site <site_id>
|
|
322
|
+
`);
|
|
323
|
+
else console.log(`
|
|
324
|
+
${colors.bold("forge-cli certificates")} - Manage SSL certificates
|
|
325
|
+
|
|
326
|
+
${colors.bold("USAGE:")}
|
|
327
|
+
forge-cli certificates <subcommand> [options]
|
|
328
|
+
|
|
329
|
+
${colors.bold("ALIASES:")}
|
|
330
|
+
forge-cli certs
|
|
331
|
+
|
|
332
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
333
|
+
list, ls List certificates
|
|
334
|
+
get <id> Get certificate details
|
|
335
|
+
activate <id> Activate a certificate
|
|
336
|
+
|
|
337
|
+
${colors.bold("OPTIONS:")}
|
|
338
|
+
--server <id> Server ID (required)
|
|
339
|
+
--site <id> Site ID (required)
|
|
340
|
+
-f, --format <fmt> Output format: json, human, table
|
|
341
|
+
|
|
342
|
+
Run ${colors.cyan("forge-cli certificates <subcommand> --help")} for details.
|
|
343
|
+
`);
|
|
344
|
+
}
|
|
345
|
+
function requireServerAndSiteRaw$2(ctx, usage) {
|
|
346
|
+
const server = String(ctx.options.server ?? "");
|
|
347
|
+
const site = String(ctx.options.site ?? "");
|
|
348
|
+
if (!server) exitWithValidationError("server_id", usage, ctx.formatter);
|
|
349
|
+
if (!site) exitWithValidationError("site_id", usage, ctx.formatter);
|
|
350
|
+
return {
|
|
351
|
+
server,
|
|
352
|
+
site
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
async function commandsList(ctx) {
|
|
356
|
+
const { server, site } = requireServerAndSiteRaw$2(ctx, "forge-cli commands list --server <server_id> --site <site_id>");
|
|
357
|
+
await runCommand(async () => {
|
|
358
|
+
const token = ctx.getToken();
|
|
359
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
360
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
361
|
+
const result = await listCommands({
|
|
362
|
+
server_id,
|
|
363
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
364
|
+
}, execCtx);
|
|
365
|
+
ctx.formatter.outputList(result.data, [
|
|
366
|
+
"id",
|
|
367
|
+
"command",
|
|
368
|
+
"status",
|
|
369
|
+
"created_at"
|
|
370
|
+
], "No commands found.", (c) => `${String(c.id).padEnd(8)} ${c.command.padEnd(50)} ${c.status.padEnd(12)} ${c.created_at}`);
|
|
371
|
+
}, ctx.formatter);
|
|
372
|
+
}
|
|
373
|
+
async function commandsGet(args, ctx) {
|
|
374
|
+
const [id] = args;
|
|
375
|
+
const usage = "forge-cli commands get <command_id> --server <server_id> --site <site_id>";
|
|
376
|
+
if (!id) exitWithValidationError("command_id", usage, ctx.formatter);
|
|
377
|
+
const { server, site } = requireServerAndSiteRaw$2(ctx, usage);
|
|
378
|
+
await runCommand(async () => {
|
|
379
|
+
const token = ctx.getToken();
|
|
380
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
381
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
382
|
+
const result = await getCommand({
|
|
383
|
+
server_id,
|
|
384
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
385
|
+
id
|
|
386
|
+
}, execCtx);
|
|
387
|
+
ctx.formatter.outputOne(result.data, [
|
|
388
|
+
"id",
|
|
389
|
+
"command",
|
|
390
|
+
"status",
|
|
391
|
+
"user_name",
|
|
392
|
+
"created_at"
|
|
393
|
+
]);
|
|
394
|
+
}, ctx.formatter);
|
|
395
|
+
}
|
|
396
|
+
async function commandsCreate(ctx) {
|
|
397
|
+
const usage = "forge-cli commands create --server <server_id> --site <site_id> --command <command>";
|
|
398
|
+
const { server, site } = requireServerAndSiteRaw$2(ctx, usage);
|
|
399
|
+
const command = String(ctx.options.command ?? "");
|
|
400
|
+
if (!command) exitWithValidationError("command", usage, ctx.formatter);
|
|
401
|
+
await runCommand(async () => {
|
|
402
|
+
const token = ctx.getToken();
|
|
403
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
404
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
405
|
+
const result = await createCommand({
|
|
406
|
+
server_id,
|
|
407
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
408
|
+
command
|
|
409
|
+
}, execCtx);
|
|
410
|
+
ctx.formatter.outputOne(result.data, [
|
|
411
|
+
"id",
|
|
412
|
+
"command",
|
|
413
|
+
"status",
|
|
414
|
+
"created_at"
|
|
415
|
+
]);
|
|
416
|
+
}, ctx.formatter);
|
|
417
|
+
}
|
|
418
|
+
const handleCommandsCommand = createCommandRouter({
|
|
419
|
+
resource: "commands",
|
|
420
|
+
handlers: {
|
|
421
|
+
list: commandsList,
|
|
422
|
+
ls: commandsList,
|
|
423
|
+
get: [commandsGet, "args"],
|
|
424
|
+
create: commandsCreate
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
function showCommandsHelp(subcommand) {
|
|
428
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
429
|
+
${colors.bold("forge-cli commands list")} - List commands executed on a site
|
|
430
|
+
|
|
431
|
+
${colors.bold("USAGE:")}
|
|
432
|
+
forge-cli commands list --server <server_id> --site <site_id> [options]
|
|
433
|
+
|
|
434
|
+
${colors.bold("OPTIONS:")}
|
|
435
|
+
--server <id> Server ID (required)
|
|
436
|
+
--site <id> Site ID (required)
|
|
437
|
+
-f, --format <fmt> Output format: json, human, table
|
|
438
|
+
`);
|
|
439
|
+
else if (subcommand === "get") console.log(`
|
|
440
|
+
${colors.bold("forge-cli commands get")} - Get command details
|
|
441
|
+
|
|
442
|
+
${colors.bold("USAGE:")}
|
|
443
|
+
forge-cli commands get <command_id> --server <server_id> --site <site_id> [options]
|
|
444
|
+
`);
|
|
445
|
+
else if (subcommand === "create") console.log(`
|
|
446
|
+
${colors.bold("forge-cli commands create")} - Execute a command on a site
|
|
447
|
+
|
|
448
|
+
${colors.bold("USAGE:")}
|
|
449
|
+
forge-cli commands create --server <server_id> --site <site_id> --command <command> [options]
|
|
450
|
+
|
|
451
|
+
${colors.bold("OPTIONS:")}
|
|
452
|
+
--server <id> Server ID (required)
|
|
453
|
+
--site <id> Site ID (required)
|
|
454
|
+
--command <cmd> Command to execute (required)
|
|
455
|
+
-f, --format <fmt> Output format: json, human, table
|
|
456
|
+
`);
|
|
457
|
+
else console.log(`
|
|
458
|
+
${colors.bold("forge-cli commands")} - Manage site commands
|
|
459
|
+
|
|
460
|
+
${colors.bold("USAGE:")}
|
|
461
|
+
forge-cli commands <subcommand> [options]
|
|
462
|
+
|
|
463
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
464
|
+
list, ls List commands
|
|
465
|
+
get <id> Get command details
|
|
466
|
+
create Execute a command on a site
|
|
467
|
+
|
|
468
|
+
${colors.bold("OPTIONS:")}
|
|
469
|
+
--server <id> Server ID (required)
|
|
470
|
+
--site <id> Site ID (required)
|
|
471
|
+
-f, --format <fmt> Output format: json, human, table
|
|
472
|
+
|
|
473
|
+
Run ${colors.cyan("forge-cli commands <subcommand> --help")} for details.
|
|
474
|
+
`);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Config command — manage forge-cli configuration
|
|
478
|
+
*/
|
|
479
|
+
function showConfigHelp() {
|
|
480
|
+
console.log(`
|
|
481
|
+
${colors.bold("forge-cli config")} - Manage CLI configuration
|
|
482
|
+
|
|
483
|
+
${colors.bold("USAGE:")}
|
|
484
|
+
forge-cli config <subcommand> [options]
|
|
485
|
+
|
|
486
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
487
|
+
set <token> Save API token to config file
|
|
488
|
+
get Show current API token (masked)
|
|
489
|
+
delete Delete stored API token
|
|
490
|
+
|
|
491
|
+
${colors.bold("EXAMPLES:")}
|
|
492
|
+
forge-cli config set YOUR_FORGE_TOKEN
|
|
493
|
+
forge-cli config get
|
|
494
|
+
forge-cli config delete
|
|
495
|
+
`);
|
|
496
|
+
}
|
|
497
|
+
function handleConfigCommand(subcommand, args, options) {
|
|
498
|
+
const format = String(options.format ?? options.f ?? "human");
|
|
499
|
+
const formatter = new OutputFormatter(format, options["no-color"] === true);
|
|
500
|
+
const store = createConfigStore();
|
|
501
|
+
switch (subcommand) {
|
|
502
|
+
case "set": {
|
|
503
|
+
const [token] = args;
|
|
504
|
+
if (!token) {
|
|
505
|
+
formatter.error("Token is required. Usage: forge-cli config set <token>");
|
|
506
|
+
process.exit(1);
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
setToken(token, store);
|
|
510
|
+
formatter.success("API token saved.");
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
case "get": {
|
|
514
|
+
const token = getToken(store);
|
|
515
|
+
if (!token) {
|
|
516
|
+
formatter.warning("No API token configured.");
|
|
517
|
+
formatter.info("Run: forge-cli config set <token>");
|
|
518
|
+
} else {
|
|
519
|
+
const masked = token.length > 8 ? `${token.slice(0, 4)}${"*".repeat(token.length - 8)}${token.slice(-4)}` : "****";
|
|
520
|
+
if (format === "json") formatter.output({ apiToken: masked });
|
|
521
|
+
else console.log(`apiToken: ${masked}`);
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
case "delete":
|
|
526
|
+
deleteToken(store);
|
|
527
|
+
formatter.success("API token deleted.");
|
|
528
|
+
break;
|
|
529
|
+
default:
|
|
530
|
+
showConfigHelp();
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
async function daemonsList(ctx) {
|
|
535
|
+
const server = String(ctx.options.server ?? "");
|
|
536
|
+
if (!server) exitWithValidationError("server_id", "forge-cli daemons list --server <server_id>", ctx.formatter);
|
|
537
|
+
await runCommand(async () => {
|
|
538
|
+
const token = ctx.getToken();
|
|
539
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
540
|
+
const result = await listDaemons({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
541
|
+
ctx.formatter.outputList(result.data, [
|
|
542
|
+
"id",
|
|
543
|
+
"command",
|
|
544
|
+
"user",
|
|
545
|
+
"status"
|
|
546
|
+
], "No daemons found.", (d) => `${String(d.id).padEnd(8)} ${d.command.padEnd(50)} ${d.user.padEnd(16)} ${d.status}`);
|
|
547
|
+
}, ctx.formatter);
|
|
548
|
+
}
|
|
549
|
+
async function daemonsGet(args, ctx) {
|
|
550
|
+
const [id] = args;
|
|
551
|
+
const server = String(ctx.options.server ?? "");
|
|
552
|
+
if (!id) exitWithValidationError("daemon_id", "forge-cli daemons get <daemon_id> --server <server_id>", ctx.formatter);
|
|
553
|
+
if (!server) exitWithValidationError("server_id", "forge-cli daemons get <daemon_id> --server <server_id>", ctx.formatter);
|
|
554
|
+
await runCommand(async () => {
|
|
555
|
+
const token = ctx.getToken();
|
|
556
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
557
|
+
const result = await getDaemon({
|
|
558
|
+
server_id: await resolveServerId(server, execCtx),
|
|
559
|
+
id
|
|
560
|
+
}, execCtx);
|
|
561
|
+
ctx.formatter.outputOne(result.data, [
|
|
562
|
+
"id",
|
|
563
|
+
"command",
|
|
564
|
+
"user",
|
|
565
|
+
"directory",
|
|
566
|
+
"processes",
|
|
567
|
+
"status",
|
|
568
|
+
"created_at"
|
|
569
|
+
]);
|
|
570
|
+
}, ctx.formatter);
|
|
571
|
+
}
|
|
572
|
+
async function daemonsRestart(args, ctx) {
|
|
573
|
+
const [id] = args;
|
|
574
|
+
const server = String(ctx.options.server ?? "");
|
|
575
|
+
if (!id) exitWithValidationError("daemon_id", "forge-cli daemons restart <daemon_id> --server <server_id>", ctx.formatter);
|
|
576
|
+
if (!server) exitWithValidationError("server_id", "forge-cli daemons restart <daemon_id> --server <server_id>", ctx.formatter);
|
|
577
|
+
await runCommand(async () => {
|
|
578
|
+
const token = ctx.getToken();
|
|
579
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
580
|
+
await restartDaemon({
|
|
581
|
+
server_id: await resolveServerId(server, execCtx),
|
|
582
|
+
id
|
|
583
|
+
}, execCtx);
|
|
584
|
+
ctx.formatter.success(`Daemon ${id} restarted.`);
|
|
585
|
+
}, ctx.formatter);
|
|
586
|
+
}
|
|
587
|
+
const handleDaemonsCommand = createCommandRouter({
|
|
588
|
+
resource: "daemons",
|
|
589
|
+
handlers: {
|
|
590
|
+
list: daemonsList,
|
|
591
|
+
ls: daemonsList,
|
|
592
|
+
get: [daemonsGet, "args"],
|
|
593
|
+
restart: [daemonsRestart, "args"]
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
function showDaemonsHelp(subcommand) {
|
|
597
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
598
|
+
${colors.bold("forge-cli daemons list")} - List daemons on a server
|
|
599
|
+
|
|
600
|
+
${colors.bold("USAGE:")}
|
|
601
|
+
forge-cli daemons list --server <server_id> [options]
|
|
602
|
+
`);
|
|
603
|
+
else if (subcommand === "get") console.log(`
|
|
604
|
+
${colors.bold("forge-cli daemons get")} - Get daemon details
|
|
605
|
+
|
|
606
|
+
${colors.bold("USAGE:")}
|
|
607
|
+
forge-cli daemons get <daemon_id> --server <server_id>
|
|
608
|
+
`);
|
|
609
|
+
else if (subcommand === "restart") console.log(`
|
|
610
|
+
${colors.bold("forge-cli daemons restart")} - Restart a daemon
|
|
611
|
+
|
|
612
|
+
${colors.bold("USAGE:")}
|
|
613
|
+
forge-cli daemons restart <daemon_id> --server <server_id>
|
|
614
|
+
`);
|
|
615
|
+
else console.log(`
|
|
616
|
+
${colors.bold("forge-cli daemons")} - Manage daemons
|
|
617
|
+
|
|
618
|
+
${colors.bold("USAGE:")}
|
|
619
|
+
forge-cli daemons <subcommand> [options]
|
|
620
|
+
|
|
621
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
622
|
+
list, ls List daemons
|
|
623
|
+
get <id> Get daemon details
|
|
624
|
+
restart <id> Restart a daemon
|
|
625
|
+
|
|
626
|
+
${colors.bold("OPTIONS:")}
|
|
627
|
+
--server <id> Server ID (required)
|
|
628
|
+
-f, --format <fmt> Output format: json, human, table
|
|
629
|
+
|
|
630
|
+
Run ${colors.cyan("forge-cli daemons <subcommand> --help")} for details.
|
|
631
|
+
`);
|
|
632
|
+
}
|
|
633
|
+
async function databasesList(ctx) {
|
|
634
|
+
const server = String(ctx.options.server ?? "");
|
|
635
|
+
if (!server) exitWithValidationError("server_id", "forge-cli databases list --server <server_id>", ctx.formatter);
|
|
636
|
+
await runCommand(async () => {
|
|
637
|
+
const token = ctx.getToken();
|
|
638
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
639
|
+
const result = await listDatabases({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
640
|
+
ctx.formatter.outputList(result.data, [
|
|
641
|
+
"id",
|
|
642
|
+
"name",
|
|
643
|
+
"status"
|
|
644
|
+
], "No databases found.", (db) => `${String(db.id).padEnd(8)} ${db.name.padEnd(30)} ${db.status}`);
|
|
645
|
+
}, ctx.formatter);
|
|
646
|
+
}
|
|
647
|
+
async function databasesGet(args, ctx) {
|
|
648
|
+
const [id] = args;
|
|
649
|
+
const server = String(ctx.options.server ?? "");
|
|
650
|
+
if (!id) exitWithValidationError("database_id", "forge-cli databases get <database_id> --server <server_id>", ctx.formatter);
|
|
651
|
+
if (!server) exitWithValidationError("server_id", "forge-cli databases get <database_id> --server <server_id>", ctx.formatter);
|
|
652
|
+
await runCommand(async () => {
|
|
653
|
+
const token = ctx.getToken();
|
|
654
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
655
|
+
const result = await getDatabase({
|
|
656
|
+
server_id: await resolveServerId(server, execCtx),
|
|
657
|
+
id
|
|
658
|
+
}, execCtx);
|
|
659
|
+
ctx.formatter.outputOne(result.data, [
|
|
660
|
+
"id",
|
|
661
|
+
"name",
|
|
662
|
+
"status",
|
|
663
|
+
"created_at"
|
|
664
|
+
]);
|
|
665
|
+
}, ctx.formatter);
|
|
666
|
+
}
|
|
667
|
+
const handleDatabasesCommand = createCommandRouter({
|
|
668
|
+
resource: "databases",
|
|
669
|
+
handlers: {
|
|
670
|
+
list: databasesList,
|
|
671
|
+
ls: databasesList,
|
|
672
|
+
get: [databasesGet, "args"]
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
function showDatabasesHelp(subcommand) {
|
|
676
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
677
|
+
${colors.bold("forge-cli databases list")} - List databases on a server
|
|
678
|
+
|
|
679
|
+
${colors.bold("USAGE:")}
|
|
680
|
+
forge-cli databases list --server <server_id> [options]
|
|
681
|
+
|
|
682
|
+
${colors.bold("OPTIONS:")}
|
|
683
|
+
--server <id> Server ID (required)
|
|
684
|
+
-f, --format <fmt> Output format: json, human, table
|
|
685
|
+
`);
|
|
686
|
+
else if (subcommand === "get") console.log(`
|
|
687
|
+
${colors.bold("forge-cli databases get")} - Get database details
|
|
688
|
+
|
|
689
|
+
${colors.bold("USAGE:")}
|
|
690
|
+
forge-cli databases get <database_id> --server <server_id> [options]
|
|
691
|
+
`);
|
|
692
|
+
else console.log(`
|
|
693
|
+
${colors.bold("forge-cli databases")} - Manage databases
|
|
694
|
+
|
|
695
|
+
${colors.bold("USAGE:")}
|
|
696
|
+
forge-cli databases <subcommand> [options]
|
|
697
|
+
|
|
698
|
+
${colors.bold("ALIASES:")}
|
|
699
|
+
forge-cli db
|
|
700
|
+
|
|
701
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
702
|
+
list, ls List databases
|
|
703
|
+
get <id> Get database details
|
|
704
|
+
|
|
705
|
+
${colors.bold("OPTIONS:")}
|
|
706
|
+
--server <id> Server ID (required)
|
|
707
|
+
-f, --format <fmt> Output format: json, human, table
|
|
708
|
+
|
|
709
|
+
Run ${colors.cyan("forge-cli databases <subcommand> --help")} for details.
|
|
710
|
+
`);
|
|
711
|
+
}
|
|
712
|
+
async function databaseUsersList(ctx) {
|
|
713
|
+
const server = String(ctx.options.server ?? "");
|
|
714
|
+
if (!server) exitWithValidationError("server_id", "forge-cli database-users list --server <server_id>", ctx.formatter);
|
|
715
|
+
await runCommand(async () => {
|
|
716
|
+
const token = ctx.getToken();
|
|
717
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
718
|
+
const result = await listDatabaseUsers({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
719
|
+
ctx.formatter.outputList(result.data, [
|
|
720
|
+
"id",
|
|
721
|
+
"name",
|
|
722
|
+
"status"
|
|
723
|
+
], "No database users found.", (u) => `${String(u.id).padEnd(8)} ${u.name.padEnd(30)} ${u.status}`);
|
|
724
|
+
}, ctx.formatter);
|
|
725
|
+
}
|
|
726
|
+
async function databaseUsersGet(args, ctx) {
|
|
727
|
+
const [id] = args;
|
|
728
|
+
const server = String(ctx.options.server ?? "");
|
|
729
|
+
if (!id) exitWithValidationError("user_id", "forge-cli database-users get <user_id> --server <server_id>", ctx.formatter);
|
|
730
|
+
if (!server) exitWithValidationError("server_id", "forge-cli database-users get <user_id> --server <server_id>", ctx.formatter);
|
|
731
|
+
await runCommand(async () => {
|
|
732
|
+
const token = ctx.getToken();
|
|
733
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
734
|
+
const result = await getDatabaseUser({
|
|
735
|
+
server_id: await resolveServerId(server, execCtx),
|
|
736
|
+
id
|
|
737
|
+
}, execCtx);
|
|
738
|
+
ctx.formatter.outputOne(result.data, [
|
|
739
|
+
"id",
|
|
740
|
+
"name",
|
|
741
|
+
"status",
|
|
742
|
+
"databases",
|
|
743
|
+
"created_at"
|
|
744
|
+
]);
|
|
745
|
+
}, ctx.formatter);
|
|
746
|
+
}
|
|
747
|
+
async function databaseUsersCreate(ctx) {
|
|
748
|
+
const server = String(ctx.options.server ?? "");
|
|
749
|
+
const name = String(ctx.options.name ?? "");
|
|
750
|
+
const password = String(ctx.options.password ?? "");
|
|
751
|
+
const databasesRaw = ctx.options.databases;
|
|
752
|
+
const databases = Array.isArray(databasesRaw) ? databasesRaw.map(Number) : databasesRaw ? [Number(databasesRaw)] : void 0;
|
|
753
|
+
if (!server) exitWithValidationError("server_id", "forge-cli database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
|
|
754
|
+
if (!name) exitWithValidationError("name", "forge-cli database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
|
|
755
|
+
if (!password) exitWithValidationError("password", "forge-cli database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
|
|
756
|
+
await runCommand(async () => {
|
|
757
|
+
const token = ctx.getToken();
|
|
758
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
759
|
+
const result = await createDatabaseUser({
|
|
760
|
+
server_id: await resolveServerId(server, execCtx),
|
|
761
|
+
name,
|
|
762
|
+
password,
|
|
763
|
+
...databases ? { databases } : {}
|
|
764
|
+
}, execCtx);
|
|
765
|
+
ctx.formatter.outputOne(result.data, [
|
|
766
|
+
"id",
|
|
767
|
+
"name",
|
|
768
|
+
"status",
|
|
769
|
+
"databases",
|
|
770
|
+
"created_at"
|
|
771
|
+
]);
|
|
772
|
+
}, ctx.formatter);
|
|
773
|
+
}
|
|
774
|
+
async function databaseUsersDelete(args, ctx) {
|
|
775
|
+
const [id] = args;
|
|
776
|
+
const server = String(ctx.options.server ?? "");
|
|
777
|
+
if (!id) exitWithValidationError("user_id", "forge-cli database-users delete <user_id> --server <server_id>", ctx.formatter);
|
|
778
|
+
if (!server) exitWithValidationError("server_id", "forge-cli database-users delete <user_id> --server <server_id>", ctx.formatter);
|
|
779
|
+
await runCommand(async () => {
|
|
780
|
+
const token = ctx.getToken();
|
|
781
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
782
|
+
await deleteDatabaseUser({
|
|
783
|
+
server_id: await resolveServerId(server, execCtx),
|
|
784
|
+
id
|
|
785
|
+
}, execCtx);
|
|
786
|
+
ctx.formatter.success(`Database user ${id} deleted.`);
|
|
787
|
+
}, ctx.formatter);
|
|
788
|
+
}
|
|
789
|
+
const handleDatabaseUsersCommand = createCommandRouter({
|
|
790
|
+
resource: "database-users",
|
|
791
|
+
handlers: {
|
|
792
|
+
list: databaseUsersList,
|
|
793
|
+
ls: databaseUsersList,
|
|
794
|
+
get: [databaseUsersGet, "args"],
|
|
795
|
+
create: databaseUsersCreate,
|
|
796
|
+
delete: [databaseUsersDelete, "args"]
|
|
797
|
+
}
|
|
798
|
+
});
|
|
799
|
+
function showDatabaseUsersHelp(subcommand) {
|
|
800
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
801
|
+
${colors.bold("forge-cli database-users list")} - List database users on a server
|
|
802
|
+
|
|
803
|
+
${colors.bold("USAGE:")}
|
|
804
|
+
forge-cli database-users list --server <server_id> [options]
|
|
805
|
+
|
|
806
|
+
${colors.bold("OPTIONS:")}
|
|
807
|
+
--server <id> Server ID (required)
|
|
808
|
+
-f, --format <fmt> Output format: json, human, table
|
|
809
|
+
`);
|
|
810
|
+
else if (subcommand === "get") console.log(`
|
|
811
|
+
${colors.bold("forge-cli database-users get")} - Get database user details
|
|
812
|
+
|
|
813
|
+
${colors.bold("USAGE:")}
|
|
814
|
+
forge-cli database-users get <user_id> --server <server_id> [options]
|
|
815
|
+
`);
|
|
816
|
+
else if (subcommand === "create") console.log(`
|
|
817
|
+
${colors.bold("forge-cli database-users create")} - Create a new database user
|
|
818
|
+
|
|
819
|
+
${colors.bold("USAGE:")}
|
|
820
|
+
forge-cli database-users create --server <server_id> --name <name> --password <password> [options]
|
|
821
|
+
|
|
822
|
+
${colors.bold("OPTIONS:")}
|
|
823
|
+
--server <id> Server ID (required)
|
|
824
|
+
--name <name> Database user name (required)
|
|
825
|
+
--password <pass> User password (required)
|
|
826
|
+
--databases <ids> Comma-separated database IDs to grant access to (optional)
|
|
827
|
+
-f, --format <fmt> Output format: json, human, table
|
|
828
|
+
`);
|
|
829
|
+
else if (subcommand === "delete") console.log(`
|
|
830
|
+
${colors.bold("forge-cli database-users delete")} - Delete a database user
|
|
831
|
+
|
|
832
|
+
${colors.bold("USAGE:")}
|
|
833
|
+
forge-cli database-users delete <user_id> --server <server_id> [options]
|
|
834
|
+
`);
|
|
835
|
+
else console.log(`
|
|
836
|
+
${colors.bold("forge-cli database-users")} - Manage database users
|
|
837
|
+
|
|
838
|
+
${colors.bold("USAGE:")}
|
|
839
|
+
forge-cli database-users <subcommand> [options]
|
|
840
|
+
|
|
841
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
842
|
+
list, ls List database users
|
|
843
|
+
get <id> Get database user details
|
|
844
|
+
create Create a new database user
|
|
845
|
+
delete <id> Delete a database user
|
|
846
|
+
|
|
847
|
+
${colors.bold("OPTIONS:")}
|
|
848
|
+
--server <id> Server ID (required)
|
|
849
|
+
-f, --format <fmt> Output format: json, human, table
|
|
850
|
+
|
|
851
|
+
Run ${colors.cyan("forge-cli database-users <subcommand> --help")} for details.
|
|
852
|
+
`);
|
|
853
|
+
}
|
|
854
|
+
async function deploymentsList(ctx) {
|
|
855
|
+
const server = String(ctx.options.server ?? "");
|
|
856
|
+
const site = String(ctx.options.site ?? "");
|
|
857
|
+
if (!server) exitWithValidationError("server_id", "forge-cli deployments list --server <server_id> --site <site_id>", ctx.formatter);
|
|
858
|
+
if (!site) exitWithValidationError("site_id", "forge-cli deployments list --server <server_id> --site <site_id>", ctx.formatter);
|
|
859
|
+
await runCommand(async () => {
|
|
860
|
+
const token = ctx.getToken();
|
|
861
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
862
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
863
|
+
const result = await listDeployments({
|
|
864
|
+
server_id,
|
|
865
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
866
|
+
}, execCtx);
|
|
867
|
+
ctx.formatter.outputList(result.data, [
|
|
868
|
+
"id",
|
|
869
|
+
"status",
|
|
870
|
+
"commit_hash",
|
|
871
|
+
"started_at"
|
|
872
|
+
], "No deployments found.", (d) => `${String(d.id).padEnd(8)} ${d.status.padEnd(12)} ${(d.commit_hash ?? "—").padEnd(10)} ${d.started_at}`);
|
|
873
|
+
}, ctx.formatter);
|
|
874
|
+
}
|
|
875
|
+
async function deploymentsDeploy(ctx) {
|
|
876
|
+
const server = String(ctx.options.server ?? "");
|
|
877
|
+
const site = String(ctx.options.site ?? "");
|
|
878
|
+
if (!server) exitWithValidationError("server_id", "forge-cli deployments deploy --server <server_id> --site <site_id>", ctx.formatter);
|
|
879
|
+
if (!site) exitWithValidationError("site_id", "forge-cli deployments deploy --server <server_id> --site <site_id>", ctx.formatter);
|
|
880
|
+
await runCommand(async () => {
|
|
881
|
+
const token = ctx.getToken();
|
|
882
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
883
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
884
|
+
const site_id = await resolveSiteId(site, server_id, execCtx);
|
|
885
|
+
await deploySite({
|
|
886
|
+
server_id,
|
|
887
|
+
site_id
|
|
888
|
+
}, execCtx);
|
|
889
|
+
ctx.formatter.success(`Deployment triggered for site ${site_id}.`);
|
|
890
|
+
}, ctx.formatter);
|
|
891
|
+
}
|
|
892
|
+
const handleDeploymentsCommand = createCommandRouter({
|
|
893
|
+
resource: "deployments",
|
|
894
|
+
handlers: {
|
|
895
|
+
list: deploymentsList,
|
|
896
|
+
ls: deploymentsList,
|
|
897
|
+
deploy: deploymentsDeploy
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
function showDeploymentsHelp(subcommand) {
|
|
901
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
902
|
+
${colors.bold("forge-cli deployments list")} - List deployments for a site
|
|
903
|
+
|
|
904
|
+
${colors.bold("USAGE:")}
|
|
905
|
+
forge-cli deployments list --server <server_id> --site <site_id> [options]
|
|
906
|
+
|
|
907
|
+
${colors.bold("OPTIONS:")}
|
|
908
|
+
--server <id> Server ID (required)
|
|
909
|
+
--site <id> Site ID (required)
|
|
910
|
+
-f, --format <fmt> Output format: json, human, table
|
|
911
|
+
`);
|
|
912
|
+
else if (subcommand === "deploy") console.log(`
|
|
913
|
+
${colors.bold("forge-cli deployments deploy")} - Trigger a deployment
|
|
914
|
+
|
|
915
|
+
${colors.bold("USAGE:")}
|
|
916
|
+
forge-cli deployments deploy --server <server_id> --site <site_id>
|
|
917
|
+
`);
|
|
918
|
+
else console.log(`
|
|
919
|
+
${colors.bold("forge-cli deployments")} - Manage deployments
|
|
920
|
+
|
|
921
|
+
${colors.bold("USAGE:")}
|
|
922
|
+
forge-cli deployments <subcommand> [options]
|
|
923
|
+
|
|
924
|
+
${colors.bold("ALIASES:")}
|
|
925
|
+
forge-cli d
|
|
926
|
+
|
|
927
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
928
|
+
list, ls List deployments for a site
|
|
929
|
+
deploy Trigger a deployment
|
|
930
|
+
|
|
931
|
+
${colors.bold("OPTIONS:")}
|
|
932
|
+
--server <id> Server ID (required)
|
|
933
|
+
--site <id> Site ID (required)
|
|
934
|
+
-f, --format <fmt> Output format: json, human, table
|
|
935
|
+
|
|
936
|
+
Run ${colors.cyan("forge-cli deployments <subcommand> --help")} for details.
|
|
937
|
+
`);
|
|
938
|
+
}
|
|
939
|
+
async function envGet(ctx) {
|
|
940
|
+
const server = String(ctx.options.server ?? "");
|
|
941
|
+
const site = String(ctx.options.site ?? "");
|
|
942
|
+
if (!server) exitWithValidationError("server_id", "forge-cli env get --server <server_id> --site <site_id>", ctx.formatter);
|
|
943
|
+
if (!site) exitWithValidationError("site_id", "forge-cli env get --server <server_id> --site <site_id>", ctx.formatter);
|
|
944
|
+
await runCommand(async () => {
|
|
945
|
+
const token = ctx.getToken();
|
|
946
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
947
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
948
|
+
const result = await getEnv({
|
|
949
|
+
server_id,
|
|
950
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
951
|
+
}, execCtx);
|
|
952
|
+
if (ctx.formatter.isJson()) console.log(JSON.stringify({ content: result.data }));
|
|
953
|
+
else console.log(result.data);
|
|
954
|
+
}, ctx.formatter);
|
|
955
|
+
}
|
|
956
|
+
async function envUpdate(ctx) {
|
|
957
|
+
const server = String(ctx.options.server ?? "");
|
|
958
|
+
const site = String(ctx.options.site ?? "");
|
|
959
|
+
const content = String(ctx.options.content ?? "");
|
|
960
|
+
if (!server) exitWithValidationError("server_id", "forge-cli env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
|
|
961
|
+
if (!site) exitWithValidationError("site_id", "forge-cli env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
|
|
962
|
+
if (!content) exitWithValidationError("content", "forge-cli env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
|
|
963
|
+
await runCommand(async () => {
|
|
964
|
+
const token = ctx.getToken();
|
|
965
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
966
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
967
|
+
await updateEnv({
|
|
968
|
+
server_id,
|
|
969
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
970
|
+
content
|
|
971
|
+
}, execCtx);
|
|
972
|
+
ctx.formatter.success("Environment variables updated.");
|
|
973
|
+
}, ctx.formatter);
|
|
974
|
+
}
|
|
975
|
+
const handleEnvCommand = createCommandRouter({
|
|
976
|
+
resource: "env",
|
|
977
|
+
handlers: {
|
|
978
|
+
get: envGet,
|
|
979
|
+
update: envUpdate
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
function showEnvHelp(subcommand) {
|
|
983
|
+
if (subcommand === "get") console.log(`
|
|
984
|
+
${colors.bold("forge-cli env get")} - Get environment variables
|
|
985
|
+
|
|
986
|
+
${colors.bold("USAGE:")}
|
|
987
|
+
forge-cli env get --server <server_id> --site <site_id>
|
|
988
|
+
`);
|
|
989
|
+
else if (subcommand === "update") console.log(`
|
|
990
|
+
${colors.bold("forge-cli env update")} - Update environment variables
|
|
991
|
+
|
|
992
|
+
${colors.bold("USAGE:")}
|
|
993
|
+
forge-cli env update --server <server_id> --site <site_id> --content <env_content>
|
|
994
|
+
`);
|
|
995
|
+
else console.log(`
|
|
996
|
+
${colors.bold("forge-cli env")} - Manage environment variables
|
|
997
|
+
|
|
998
|
+
${colors.bold("USAGE:")}
|
|
999
|
+
forge-cli env <subcommand> [options]
|
|
1000
|
+
|
|
1001
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1002
|
+
get Get environment variables
|
|
1003
|
+
update Update environment variables
|
|
1004
|
+
|
|
1005
|
+
${colors.bold("OPTIONS:")}
|
|
1006
|
+
--server <id> Server ID (required)
|
|
1007
|
+
--site <id> Site ID (required)
|
|
1008
|
+
--content <str> New env content (for update)
|
|
1009
|
+
-f, --format <fmt> Output format: json, human
|
|
1010
|
+
|
|
1011
|
+
Run ${colors.cyan("forge-cli env <subcommand> --help")} for details.
|
|
1012
|
+
`);
|
|
1013
|
+
}
|
|
1014
|
+
async function firewallRulesList(ctx) {
|
|
1015
|
+
const server = String(ctx.options.server ?? "");
|
|
1016
|
+
if (!server) exitWithValidationError("server_id", "forge-cli firewall-rules list --server <server_id>", ctx.formatter);
|
|
1017
|
+
await runCommand(async () => {
|
|
1018
|
+
const token = ctx.getToken();
|
|
1019
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1020
|
+
const result = await listFirewallRules({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
1021
|
+
ctx.formatter.outputList(result.data, [
|
|
1022
|
+
"id",
|
|
1023
|
+
"name",
|
|
1024
|
+
"port",
|
|
1025
|
+
"type",
|
|
1026
|
+
"ip_address",
|
|
1027
|
+
"status"
|
|
1028
|
+
], "No firewall rules found.", (r) => `${String(r.id).padEnd(8)} ${r.name.padEnd(20)} ${String(r.port).padEnd(8)} ${r.type.padEnd(8)} ${(r.ip_address ?? "any").padEnd(16)} ${r.status}`);
|
|
1029
|
+
}, ctx.formatter);
|
|
1030
|
+
}
|
|
1031
|
+
async function firewallRulesGet(args, ctx) {
|
|
1032
|
+
const [id] = args;
|
|
1033
|
+
const server = String(ctx.options.server ?? "");
|
|
1034
|
+
if (!id) exitWithValidationError("firewall_rule_id", "forge-cli firewall-rules get <rule_id> --server <server_id>", ctx.formatter);
|
|
1035
|
+
if (!server) exitWithValidationError("server_id", "forge-cli firewall-rules get <rule_id> --server <server_id>", ctx.formatter);
|
|
1036
|
+
await runCommand(async () => {
|
|
1037
|
+
const token = ctx.getToken();
|
|
1038
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1039
|
+
const result = await getFirewallRule({
|
|
1040
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1041
|
+
id
|
|
1042
|
+
}, execCtx);
|
|
1043
|
+
ctx.formatter.outputOne(result.data, [
|
|
1044
|
+
"id",
|
|
1045
|
+
"name",
|
|
1046
|
+
"port",
|
|
1047
|
+
"type",
|
|
1048
|
+
"ip_address",
|
|
1049
|
+
"status",
|
|
1050
|
+
"created_at"
|
|
1051
|
+
]);
|
|
1052
|
+
}, ctx.formatter);
|
|
1053
|
+
}
|
|
1054
|
+
const handleFirewallRulesCommand = createCommandRouter({
|
|
1055
|
+
resource: "firewall-rules",
|
|
1056
|
+
handlers: {
|
|
1057
|
+
list: firewallRulesList,
|
|
1058
|
+
ls: firewallRulesList,
|
|
1059
|
+
get: [firewallRulesGet, "args"]
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
function showFirewallRulesHelp(subcommand) {
|
|
1063
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1064
|
+
${colors.bold("forge-cli firewall-rules list")} - List firewall rules on a server
|
|
1065
|
+
|
|
1066
|
+
${colors.bold("USAGE:")}
|
|
1067
|
+
forge-cli firewall-rules list --server <server_id> [options]
|
|
1068
|
+
`);
|
|
1069
|
+
else if (subcommand === "get") console.log(`
|
|
1070
|
+
${colors.bold("forge-cli firewall-rules get")} - Get firewall rule details
|
|
1071
|
+
|
|
1072
|
+
${colors.bold("USAGE:")}
|
|
1073
|
+
forge-cli firewall-rules get <rule_id> --server <server_id>
|
|
1074
|
+
`);
|
|
1075
|
+
else console.log(`
|
|
1076
|
+
${colors.bold("forge-cli firewall-rules")} - Manage firewall rules
|
|
1077
|
+
|
|
1078
|
+
${colors.bold("USAGE:")}
|
|
1079
|
+
forge-cli firewall-rules <subcommand> [options]
|
|
1080
|
+
|
|
1081
|
+
${colors.bold("ALIASES:")}
|
|
1082
|
+
forge-cli fw
|
|
1083
|
+
|
|
1084
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1085
|
+
list, ls List firewall rules
|
|
1086
|
+
get <id> Get firewall rule details
|
|
1087
|
+
|
|
1088
|
+
${colors.bold("OPTIONS:")}
|
|
1089
|
+
--server <id> Server ID (required)
|
|
1090
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1091
|
+
|
|
1092
|
+
Run ${colors.cyan("forge-cli firewall-rules <subcommand> --help")} for details.
|
|
1093
|
+
`);
|
|
1094
|
+
}
|
|
1095
|
+
async function monitorsList(ctx) {
|
|
1096
|
+
const server = String(ctx.options.server ?? "");
|
|
1097
|
+
if (!server) exitWithValidationError("server_id", "forge-cli monitors list --server <server_id>", ctx.formatter);
|
|
1098
|
+
await runCommand(async () => {
|
|
1099
|
+
const token = ctx.getToken();
|
|
1100
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1101
|
+
const result = await listMonitors({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
1102
|
+
ctx.formatter.outputList(result.data, [
|
|
1103
|
+
"id",
|
|
1104
|
+
"type",
|
|
1105
|
+
"operator",
|
|
1106
|
+
"threshold",
|
|
1107
|
+
"state"
|
|
1108
|
+
], "No monitors found.", (m) => `${String(m.id).padEnd(8)} ${m.type.padEnd(20)} ${m.operator.padEnd(8)} ${String(m.threshold).padEnd(6)} ${m.state}`);
|
|
1109
|
+
}, ctx.formatter);
|
|
1110
|
+
}
|
|
1111
|
+
async function monitorsGet(args, ctx) {
|
|
1112
|
+
const [id] = args;
|
|
1113
|
+
const server = String(ctx.options.server ?? "");
|
|
1114
|
+
if (!id) exitWithValidationError("monitor_id", "forge-cli monitors get <monitor_id> --server <server_id>", ctx.formatter);
|
|
1115
|
+
if (!server) exitWithValidationError("server_id", "forge-cli monitors get <monitor_id> --server <server_id>", ctx.formatter);
|
|
1116
|
+
await runCommand(async () => {
|
|
1117
|
+
const token = ctx.getToken();
|
|
1118
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1119
|
+
const result = await getMonitor({
|
|
1120
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1121
|
+
id
|
|
1122
|
+
}, execCtx);
|
|
1123
|
+
ctx.formatter.outputOne(result.data, [
|
|
1124
|
+
"id",
|
|
1125
|
+
"type",
|
|
1126
|
+
"operator",
|
|
1127
|
+
"threshold",
|
|
1128
|
+
"minutes",
|
|
1129
|
+
"state",
|
|
1130
|
+
"state_changed_at"
|
|
1131
|
+
]);
|
|
1132
|
+
}, ctx.formatter);
|
|
1133
|
+
}
|
|
1134
|
+
async function monitorsCreate(ctx) {
|
|
1135
|
+
const server = String(ctx.options.server ?? "");
|
|
1136
|
+
const type = String(ctx.options.type ?? "");
|
|
1137
|
+
const operator = String(ctx.options.operator ?? "");
|
|
1138
|
+
const threshold = Number(ctx.options.threshold ?? 0);
|
|
1139
|
+
const minutes = Number(ctx.options.minutes ?? 0);
|
|
1140
|
+
if (!server) exitWithValidationError("server_id", "forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
|
|
1141
|
+
if (!type) exitWithValidationError("type", "forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
|
|
1142
|
+
if (!operator) exitWithValidationError("operator", "forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
|
|
1143
|
+
await runCommand(async () => {
|
|
1144
|
+
const token = ctx.getToken();
|
|
1145
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1146
|
+
const result = await createMonitor({
|
|
1147
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1148
|
+
type,
|
|
1149
|
+
operator,
|
|
1150
|
+
threshold,
|
|
1151
|
+
minutes
|
|
1152
|
+
}, execCtx);
|
|
1153
|
+
ctx.formatter.outputOne(result.data, [
|
|
1154
|
+
"id",
|
|
1155
|
+
"type",
|
|
1156
|
+
"operator",
|
|
1157
|
+
"threshold",
|
|
1158
|
+
"minutes",
|
|
1159
|
+
"state"
|
|
1160
|
+
]);
|
|
1161
|
+
}, ctx.formatter);
|
|
1162
|
+
}
|
|
1163
|
+
async function monitorsDelete(args, ctx) {
|
|
1164
|
+
const [id] = args;
|
|
1165
|
+
const server = String(ctx.options.server ?? "");
|
|
1166
|
+
if (!id) exitWithValidationError("monitor_id", "forge-cli monitors delete <monitor_id> --server <server_id>", ctx.formatter);
|
|
1167
|
+
if (!server) exitWithValidationError("server_id", "forge-cli monitors delete <monitor_id> --server <server_id>", ctx.formatter);
|
|
1168
|
+
await runCommand(async () => {
|
|
1169
|
+
const token = ctx.getToken();
|
|
1170
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1171
|
+
await deleteMonitor({
|
|
1172
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1173
|
+
id
|
|
1174
|
+
}, execCtx);
|
|
1175
|
+
ctx.formatter.success(`Monitor ${id} deleted.`);
|
|
1176
|
+
}, ctx.formatter);
|
|
1177
|
+
}
|
|
1178
|
+
const handleMonitorsCommand = createCommandRouter({
|
|
1179
|
+
resource: "monitors",
|
|
1180
|
+
handlers: {
|
|
1181
|
+
list: monitorsList,
|
|
1182
|
+
ls: monitorsList,
|
|
1183
|
+
get: [monitorsGet, "args"],
|
|
1184
|
+
create: monitorsCreate,
|
|
1185
|
+
delete: [monitorsDelete, "args"]
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
function showMonitorsHelp(subcommand) {
|
|
1189
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1190
|
+
${colors.bold("forge-cli monitors list")} - List monitors on a server
|
|
1191
|
+
|
|
1192
|
+
${colors.bold("USAGE:")}
|
|
1193
|
+
forge-cli monitors list --server <server_id> [options]
|
|
1194
|
+
|
|
1195
|
+
${colors.bold("OPTIONS:")}
|
|
1196
|
+
--server <id> Server ID (required)
|
|
1197
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1198
|
+
`);
|
|
1199
|
+
else if (subcommand === "get") console.log(`
|
|
1200
|
+
${colors.bold("forge-cli monitors get")} - Get monitor details
|
|
1201
|
+
|
|
1202
|
+
${colors.bold("USAGE:")}
|
|
1203
|
+
forge-cli monitors get <monitor_id> --server <server_id> [options]
|
|
1204
|
+
`);
|
|
1205
|
+
else if (subcommand === "create") console.log(`
|
|
1206
|
+
${colors.bold("forge-cli monitors create")} - Create a new monitor
|
|
1207
|
+
|
|
1208
|
+
${colors.bold("USAGE:")}
|
|
1209
|
+
forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes> [options]
|
|
1210
|
+
|
|
1211
|
+
${colors.bold("OPTIONS:")}
|
|
1212
|
+
--server <id> Server ID (required)
|
|
1213
|
+
--type <type> Monitor type (required)
|
|
1214
|
+
--operator <op> Comparison operator (required)
|
|
1215
|
+
--threshold <num> Alert threshold value (required)
|
|
1216
|
+
--minutes <num> Duration in minutes (required)
|
|
1217
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1218
|
+
`);
|
|
1219
|
+
else if (subcommand === "delete") console.log(`
|
|
1220
|
+
${colors.bold("forge-cli monitors delete")} - Delete a monitor
|
|
1221
|
+
|
|
1222
|
+
${colors.bold("USAGE:")}
|
|
1223
|
+
forge-cli monitors delete <monitor_id> --server <server_id> [options]
|
|
1224
|
+
`);
|
|
1225
|
+
else console.log(`
|
|
1226
|
+
${colors.bold("forge-cli monitors")} - Manage server monitors
|
|
1227
|
+
|
|
1228
|
+
${colors.bold("USAGE:")}
|
|
1229
|
+
forge-cli monitors <subcommand> [options]
|
|
1230
|
+
|
|
1231
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1232
|
+
list, ls List monitors
|
|
1233
|
+
get <id> Get monitor details
|
|
1234
|
+
create Create a new monitor
|
|
1235
|
+
delete <id> Delete a monitor
|
|
1236
|
+
|
|
1237
|
+
${colors.bold("OPTIONS:")}
|
|
1238
|
+
--server <id> Server ID (required)
|
|
1239
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1240
|
+
|
|
1241
|
+
Run ${colors.cyan("forge-cli monitors <subcommand> --help")} for details.
|
|
1242
|
+
`);
|
|
1243
|
+
}
|
|
1244
|
+
async function nginxGet(ctx) {
|
|
1245
|
+
const server = String(ctx.options.server ?? "");
|
|
1246
|
+
const site = String(ctx.options.site ?? "");
|
|
1247
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx get --server <server_id> --site <site_id>", ctx.formatter);
|
|
1248
|
+
if (!site) exitWithValidationError("site_id", "forge-cli nginx get --server <server_id> --site <site_id>", ctx.formatter);
|
|
1249
|
+
await runCommand(async () => {
|
|
1250
|
+
const token = ctx.getToken();
|
|
1251
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1252
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1253
|
+
const result = await getNginxConfig({
|
|
1254
|
+
server_id,
|
|
1255
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
1256
|
+
}, execCtx);
|
|
1257
|
+
if (ctx.formatter.isJson()) console.log(JSON.stringify({ content: result.data }));
|
|
1258
|
+
else console.log(result.data);
|
|
1259
|
+
}, ctx.formatter);
|
|
1260
|
+
}
|
|
1261
|
+
async function nginxUpdate(ctx) {
|
|
1262
|
+
const server = String(ctx.options.server ?? "");
|
|
1263
|
+
const site = String(ctx.options.site ?? "");
|
|
1264
|
+
const content = String(ctx.options.content ?? "");
|
|
1265
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
|
|
1266
|
+
if (!site) exitWithValidationError("site_id", "forge-cli nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
|
|
1267
|
+
if (!content) exitWithValidationError("content", "forge-cli nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
|
|
1268
|
+
await runCommand(async () => {
|
|
1269
|
+
const token = ctx.getToken();
|
|
1270
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1271
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1272
|
+
await updateNginxConfig({
|
|
1273
|
+
server_id,
|
|
1274
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1275
|
+
content
|
|
1276
|
+
}, execCtx);
|
|
1277
|
+
ctx.formatter.success("Nginx configuration updated.");
|
|
1278
|
+
}, ctx.formatter);
|
|
1279
|
+
}
|
|
1280
|
+
const handleNginxCommand = createCommandRouter({
|
|
1281
|
+
resource: "nginx",
|
|
1282
|
+
handlers: {
|
|
1283
|
+
get: nginxGet,
|
|
1284
|
+
update: nginxUpdate
|
|
1285
|
+
}
|
|
1286
|
+
});
|
|
1287
|
+
function showNginxHelp(subcommand) {
|
|
1288
|
+
if (subcommand === "get") console.log(`
|
|
1289
|
+
${colors.bold("forge-cli nginx get")} - Get nginx configuration
|
|
1290
|
+
|
|
1291
|
+
${colors.bold("USAGE:")}
|
|
1292
|
+
forge-cli nginx get --server <server_id> --site <site_id>
|
|
1293
|
+
`);
|
|
1294
|
+
else if (subcommand === "update") console.log(`
|
|
1295
|
+
${colors.bold("forge-cli nginx update")} - Update nginx configuration
|
|
1296
|
+
|
|
1297
|
+
${colors.bold("USAGE:")}
|
|
1298
|
+
forge-cli nginx update --server <server_id> --site <site_id> --content <nginx_config>
|
|
1299
|
+
`);
|
|
1300
|
+
else console.log(`
|
|
1301
|
+
${colors.bold("forge-cli nginx")} - Manage nginx configuration
|
|
1302
|
+
|
|
1303
|
+
${colors.bold("USAGE:")}
|
|
1304
|
+
forge-cli nginx <subcommand> [options]
|
|
1305
|
+
|
|
1306
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1307
|
+
get Get nginx configuration
|
|
1308
|
+
update Update nginx configuration
|
|
1309
|
+
|
|
1310
|
+
${colors.bold("OPTIONS:")}
|
|
1311
|
+
--server <id> Server ID (required)
|
|
1312
|
+
--site <id> Site ID (required)
|
|
1313
|
+
--content <str> New nginx config (for update)
|
|
1314
|
+
|
|
1315
|
+
Run ${colors.cyan("forge-cli nginx <subcommand> --help")} for details.
|
|
1316
|
+
`);
|
|
1317
|
+
}
|
|
1318
|
+
async function nginxTemplatesList(ctx) {
|
|
1319
|
+
const server = String(ctx.options.server ?? "");
|
|
1320
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates list --server <server_id>", ctx.formatter);
|
|
1321
|
+
await runCommand(async () => {
|
|
1322
|
+
const token = ctx.getToken();
|
|
1323
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1324
|
+
const result = await listNginxTemplates({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
1325
|
+
ctx.formatter.outputList(result.data, [
|
|
1326
|
+
"id",
|
|
1327
|
+
"name",
|
|
1328
|
+
"created_at"
|
|
1329
|
+
], "No Nginx templates found.", (t) => `${String(t.id).padEnd(8)} ${t.name.padEnd(40)} ${t.created_at}`);
|
|
1330
|
+
}, ctx.formatter);
|
|
1331
|
+
}
|
|
1332
|
+
async function nginxTemplatesGet(args, ctx) {
|
|
1333
|
+
const [id] = args;
|
|
1334
|
+
const server = String(ctx.options.server ?? "");
|
|
1335
|
+
if (!id) exitWithValidationError("template_id", "forge-cli nginx-templates get <template_id> --server <server_id>", ctx.formatter);
|
|
1336
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates get <template_id> --server <server_id>", ctx.formatter);
|
|
1337
|
+
await runCommand(async () => {
|
|
1338
|
+
const token = ctx.getToken();
|
|
1339
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1340
|
+
const result = await getNginxTemplate({
|
|
1341
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1342
|
+
id
|
|
1343
|
+
}, execCtx);
|
|
1344
|
+
ctx.formatter.outputOne(result.data, [
|
|
1345
|
+
"id",
|
|
1346
|
+
"name",
|
|
1347
|
+
"created_at",
|
|
1348
|
+
"content"
|
|
1349
|
+
]);
|
|
1350
|
+
}, ctx.formatter);
|
|
1351
|
+
}
|
|
1352
|
+
async function nginxTemplatesCreate(ctx) {
|
|
1353
|
+
const server = String(ctx.options.server ?? "");
|
|
1354
|
+
const name = String(ctx.options.name ?? "");
|
|
1355
|
+
const content = String(ctx.options.content ?? "");
|
|
1356
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
|
|
1357
|
+
if (!name) exitWithValidationError("name", "forge-cli nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
|
|
1358
|
+
if (!content) exitWithValidationError("content", "forge-cli nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
|
|
1359
|
+
await runCommand(async () => {
|
|
1360
|
+
const token = ctx.getToken();
|
|
1361
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1362
|
+
const result = await createNginxTemplate({
|
|
1363
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1364
|
+
name,
|
|
1365
|
+
content
|
|
1366
|
+
}, execCtx);
|
|
1367
|
+
ctx.formatter.outputOne(result.data, [
|
|
1368
|
+
"id",
|
|
1369
|
+
"name",
|
|
1370
|
+
"created_at"
|
|
1371
|
+
]);
|
|
1372
|
+
}, ctx.formatter);
|
|
1373
|
+
}
|
|
1374
|
+
async function nginxTemplatesUpdate(args, ctx) {
|
|
1375
|
+
const [id] = args;
|
|
1376
|
+
const server = String(ctx.options.server ?? "");
|
|
1377
|
+
if (!id) exitWithValidationError("template_id", "forge-cli nginx-templates update <template_id> --server <server_id>", ctx.formatter);
|
|
1378
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates update <template_id> --server <server_id>", ctx.formatter);
|
|
1379
|
+
await runCommand(async () => {
|
|
1380
|
+
const token = ctx.getToken();
|
|
1381
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1382
|
+
const result = await updateNginxTemplate({
|
|
1383
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1384
|
+
id,
|
|
1385
|
+
name: ctx.options.name ? String(ctx.options.name) : void 0,
|
|
1386
|
+
content: ctx.options.content ? String(ctx.options.content) : void 0
|
|
1387
|
+
}, execCtx);
|
|
1388
|
+
ctx.formatter.outputOne(result.data, [
|
|
1389
|
+
"id",
|
|
1390
|
+
"name",
|
|
1391
|
+
"created_at"
|
|
1392
|
+
]);
|
|
1393
|
+
}, ctx.formatter);
|
|
1394
|
+
}
|
|
1395
|
+
async function nginxTemplatesDelete(args, ctx) {
|
|
1396
|
+
const [id] = args;
|
|
1397
|
+
const server = String(ctx.options.server ?? "");
|
|
1398
|
+
if (!id) exitWithValidationError("template_id", "forge-cli nginx-templates delete <template_id> --server <server_id>", ctx.formatter);
|
|
1399
|
+
if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates delete <template_id> --server <server_id>", ctx.formatter);
|
|
1400
|
+
await runCommand(async () => {
|
|
1401
|
+
const token = ctx.getToken();
|
|
1402
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1403
|
+
await deleteNginxTemplate({
|
|
1404
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1405
|
+
id
|
|
1406
|
+
}, execCtx);
|
|
1407
|
+
ctx.formatter.success(`Nginx template ${id} deleted.`);
|
|
1408
|
+
}, ctx.formatter);
|
|
1409
|
+
}
|
|
1410
|
+
const handleNginxTemplatesCommand = createCommandRouter({
|
|
1411
|
+
resource: "nginx-templates",
|
|
1412
|
+
handlers: {
|
|
1413
|
+
list: nginxTemplatesList,
|
|
1414
|
+
ls: nginxTemplatesList,
|
|
1415
|
+
get: [nginxTemplatesGet, "args"],
|
|
1416
|
+
create: nginxTemplatesCreate,
|
|
1417
|
+
update: [nginxTemplatesUpdate, "args"],
|
|
1418
|
+
delete: [nginxTemplatesDelete, "args"]
|
|
1419
|
+
}
|
|
1420
|
+
});
|
|
1421
|
+
function showNginxTemplatesHelp(subcommand) {
|
|
1422
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1423
|
+
${colors.bold("forge-cli nginx-templates list")} - List Nginx templates on a server
|
|
1424
|
+
|
|
1425
|
+
${colors.bold("USAGE:")}
|
|
1426
|
+
forge-cli nginx-templates list --server <server_id> [options]
|
|
1427
|
+
|
|
1428
|
+
${colors.bold("OPTIONS:")}
|
|
1429
|
+
--server <id> Server ID (required)
|
|
1430
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1431
|
+
`);
|
|
1432
|
+
else if (subcommand === "get") console.log(`
|
|
1433
|
+
${colors.bold("forge-cli nginx-templates get")} - Get Nginx template details
|
|
1434
|
+
|
|
1435
|
+
${colors.bold("USAGE:")}
|
|
1436
|
+
forge-cli nginx-templates get <template_id> --server <server_id> [options]
|
|
1437
|
+
`);
|
|
1438
|
+
else if (subcommand === "create") console.log(`
|
|
1439
|
+
${colors.bold("forge-cli nginx-templates create")} - Create a new Nginx template
|
|
1440
|
+
|
|
1441
|
+
${colors.bold("USAGE:")}
|
|
1442
|
+
forge-cli nginx-templates create --server <server_id> --name <name> --content <content> [options]
|
|
1443
|
+
|
|
1444
|
+
${colors.bold("OPTIONS:")}
|
|
1445
|
+
--server <id> Server ID (required)
|
|
1446
|
+
--name <name> Template name (required)
|
|
1447
|
+
--content <text> Template content (required)
|
|
1448
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1449
|
+
`);
|
|
1450
|
+
else if (subcommand === "update") console.log(`
|
|
1451
|
+
${colors.bold("forge-cli nginx-templates update")} - Update an Nginx template
|
|
1452
|
+
|
|
1453
|
+
${colors.bold("USAGE:")}
|
|
1454
|
+
forge-cli nginx-templates update <template_id> --server <server_id> [options]
|
|
1455
|
+
|
|
1456
|
+
${colors.bold("OPTIONS:")}
|
|
1457
|
+
--server <id> Server ID (required)
|
|
1458
|
+
--name <name> New template name (optional)
|
|
1459
|
+
--content <text> New template content (optional)
|
|
1460
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1461
|
+
`);
|
|
1462
|
+
else if (subcommand === "delete") console.log(`
|
|
1463
|
+
${colors.bold("forge-cli nginx-templates delete")} - Delete an Nginx template
|
|
1464
|
+
|
|
1465
|
+
${colors.bold("USAGE:")}
|
|
1466
|
+
forge-cli nginx-templates delete <template_id> --server <server_id> [options]
|
|
1467
|
+
`);
|
|
1468
|
+
else console.log(`
|
|
1469
|
+
${colors.bold("forge-cli nginx-templates")} - Manage Nginx templates
|
|
1470
|
+
|
|
1471
|
+
${colors.bold("USAGE:")}
|
|
1472
|
+
forge-cli nginx-templates <subcommand> [options]
|
|
1473
|
+
|
|
1474
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1475
|
+
list, ls List Nginx templates
|
|
1476
|
+
get <id> Get Nginx template details
|
|
1477
|
+
create Create a new Nginx template
|
|
1478
|
+
update <id> Update an Nginx template
|
|
1479
|
+
delete <id> Delete an Nginx template
|
|
1480
|
+
|
|
1481
|
+
${colors.bold("OPTIONS:")}
|
|
1482
|
+
--server <id> Server ID (required)
|
|
1483
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1484
|
+
|
|
1485
|
+
Run ${colors.cyan("forge-cli nginx-templates <subcommand> --help")} for details.
|
|
1486
|
+
`);
|
|
1487
|
+
}
|
|
1488
|
+
async function recipesList(ctx) {
|
|
1489
|
+
await runCommand(async () => {
|
|
1490
|
+
const token = ctx.getToken();
|
|
1491
|
+
const result = await listRecipes({}, ctx.createExecutorContext(token));
|
|
1492
|
+
ctx.formatter.outputList(result.data, [
|
|
1493
|
+
"id",
|
|
1494
|
+
"name",
|
|
1495
|
+
"user",
|
|
1496
|
+
"created_at"
|
|
1497
|
+
], "No recipes found.", (r) => `${String(r.id).padEnd(8)} ${r.name.padEnd(40)} ${r.user.padEnd(16)} ${r.created_at}`);
|
|
1498
|
+
}, ctx.formatter);
|
|
1499
|
+
}
|
|
1500
|
+
async function recipesGet(args, ctx) {
|
|
1501
|
+
const [id] = args;
|
|
1502
|
+
if (!id) exitWithValidationError("id", "forge-cli recipes get <recipe_id>", ctx.formatter);
|
|
1503
|
+
await runCommand(async () => {
|
|
1504
|
+
const token = ctx.getToken();
|
|
1505
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1506
|
+
const result = await getRecipe({ id }, execCtx);
|
|
1507
|
+
ctx.formatter.outputOne(result.data, [
|
|
1508
|
+
"id",
|
|
1509
|
+
"name",
|
|
1510
|
+
"user",
|
|
1511
|
+
"created_at",
|
|
1512
|
+
"script"
|
|
1513
|
+
]);
|
|
1514
|
+
}, ctx.formatter);
|
|
1515
|
+
}
|
|
1516
|
+
async function recipesRun(args, ctx) {
|
|
1517
|
+
const [id] = args;
|
|
1518
|
+
const serversRaw = String(ctx.options.servers ?? "");
|
|
1519
|
+
if (!id) exitWithValidationError("id", "forge-cli recipes run <recipe_id> --servers <ids>", ctx.formatter);
|
|
1520
|
+
if (!serversRaw) exitWithValidationError("servers", "forge-cli recipes run <recipe_id> --servers <server_id1,server_id2,...>", ctx.formatter);
|
|
1521
|
+
const servers = serversRaw.split(",").map((s) => Number(s.trim())).filter((n) => !isNaN(n));
|
|
1522
|
+
await runCommand(async () => {
|
|
1523
|
+
const token = ctx.getToken();
|
|
1524
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1525
|
+
await runRecipe({
|
|
1526
|
+
id,
|
|
1527
|
+
servers
|
|
1528
|
+
}, execCtx);
|
|
1529
|
+
ctx.formatter.success(`Recipe ${id} dispatched to ${servers.length} server(s).`);
|
|
1530
|
+
}, ctx.formatter);
|
|
1531
|
+
}
|
|
1532
|
+
const handleRecipesCommand = createCommandRouter({
|
|
1533
|
+
resource: "recipes",
|
|
1534
|
+
handlers: {
|
|
1535
|
+
list: recipesList,
|
|
1536
|
+
ls: recipesList,
|
|
1537
|
+
get: [recipesGet, "args"],
|
|
1538
|
+
run: [recipesRun, "args"]
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
function showRecipesHelp(subcommand) {
|
|
1542
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1543
|
+
${colors.bold("forge-cli recipes list")} - List all recipes
|
|
1544
|
+
|
|
1545
|
+
${colors.bold("USAGE:")}
|
|
1546
|
+
forge-cli recipes list [options]
|
|
1547
|
+
`);
|
|
1548
|
+
else if (subcommand === "get") console.log(`
|
|
1549
|
+
${colors.bold("forge-cli recipes get")} - Get recipe details
|
|
1550
|
+
|
|
1551
|
+
${colors.bold("USAGE:")}
|
|
1552
|
+
forge-cli recipes get <recipe_id>
|
|
1553
|
+
`);
|
|
1554
|
+
else if (subcommand === "run") console.log(`
|
|
1555
|
+
${colors.bold("forge-cli recipes run")} - Run a recipe on servers
|
|
1556
|
+
|
|
1557
|
+
${colors.bold("USAGE:")}
|
|
1558
|
+
forge-cli recipes run <recipe_id> --servers <server_id1,server_id2,...>
|
|
1559
|
+
|
|
1560
|
+
${colors.bold("OPTIONS:")}
|
|
1561
|
+
--servers <ids> Comma-separated server IDs to run recipe on
|
|
1562
|
+
`);
|
|
1563
|
+
else console.log(`
|
|
1564
|
+
${colors.bold("forge-cli recipes")} - Manage recipes
|
|
1565
|
+
|
|
1566
|
+
${colors.bold("USAGE:")}
|
|
1567
|
+
forge-cli recipes <subcommand> [options]
|
|
1568
|
+
|
|
1569
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1570
|
+
list, ls List all recipes
|
|
1571
|
+
get <id> Get recipe details
|
|
1572
|
+
run <id> Run a recipe on servers
|
|
1573
|
+
|
|
1574
|
+
${colors.bold("OPTIONS:")}
|
|
1575
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1576
|
+
|
|
1577
|
+
Run ${colors.cyan("forge-cli recipes <subcommand> --help")} for details.
|
|
1578
|
+
`);
|
|
1579
|
+
}
|
|
1580
|
+
function requireServerAndSiteRaw$1(ctx, usage) {
|
|
1581
|
+
const server = String(ctx.options.server ?? "");
|
|
1582
|
+
const site = String(ctx.options.site ?? "");
|
|
1583
|
+
if (!server) exitWithValidationError("server_id", usage, ctx.formatter);
|
|
1584
|
+
if (!site) exitWithValidationError("site_id", usage, ctx.formatter);
|
|
1585
|
+
return {
|
|
1586
|
+
server,
|
|
1587
|
+
site
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
async function redirectRulesList(ctx) {
|
|
1591
|
+
const { server, site } = requireServerAndSiteRaw$1(ctx, "forge-cli redirect-rules list --server <server_id> --site <site_id>");
|
|
1592
|
+
await runCommand(async () => {
|
|
1593
|
+
const token = ctx.getToken();
|
|
1594
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1595
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1596
|
+
const result = await listRedirectRules({
|
|
1597
|
+
server_id,
|
|
1598
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
1599
|
+
}, execCtx);
|
|
1600
|
+
ctx.formatter.outputList(result.data, [
|
|
1601
|
+
"id",
|
|
1602
|
+
"from",
|
|
1603
|
+
"to",
|
|
1604
|
+
"type"
|
|
1605
|
+
], "No redirect rules found.", (r) => `${String(r.id).padEnd(8)} ${r.from.padEnd(30)} ${r.to.padEnd(30)} ${r.type}`);
|
|
1606
|
+
}, ctx.formatter);
|
|
1607
|
+
}
|
|
1608
|
+
async function redirectRulesGet(args, ctx) {
|
|
1609
|
+
const [id] = args;
|
|
1610
|
+
const usage = "forge-cli redirect-rules get <rule_id> --server <server_id> --site <site_id>";
|
|
1611
|
+
if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
|
|
1612
|
+
const { server, site } = requireServerAndSiteRaw$1(ctx, usage);
|
|
1613
|
+
await runCommand(async () => {
|
|
1614
|
+
const token = ctx.getToken();
|
|
1615
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1616
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1617
|
+
const result = await getRedirectRule({
|
|
1618
|
+
server_id,
|
|
1619
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1620
|
+
id
|
|
1621
|
+
}, execCtx);
|
|
1622
|
+
ctx.formatter.outputOne(result.data, [
|
|
1623
|
+
"id",
|
|
1624
|
+
"from",
|
|
1625
|
+
"to",
|
|
1626
|
+
"type",
|
|
1627
|
+
"created_at"
|
|
1628
|
+
]);
|
|
1629
|
+
}, ctx.formatter);
|
|
1630
|
+
}
|
|
1631
|
+
async function redirectRulesCreate(ctx) {
|
|
1632
|
+
const usage = "forge-cli redirect-rules create --server <server_id> --site <site_id> --from <from> --to <to>";
|
|
1633
|
+
const { server, site } = requireServerAndSiteRaw$1(ctx, usage);
|
|
1634
|
+
const from = String(ctx.options.from ?? "");
|
|
1635
|
+
const to = String(ctx.options.to ?? "");
|
|
1636
|
+
if (!from) exitWithValidationError("from", usage, ctx.formatter);
|
|
1637
|
+
if (!to) exitWithValidationError("to", usage, ctx.formatter);
|
|
1638
|
+
await runCommand(async () => {
|
|
1639
|
+
const token = ctx.getToken();
|
|
1640
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1641
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1642
|
+
const result = await createRedirectRule({
|
|
1643
|
+
server_id,
|
|
1644
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1645
|
+
from,
|
|
1646
|
+
to
|
|
1647
|
+
}, execCtx);
|
|
1648
|
+
ctx.formatter.outputOne(result.data, [
|
|
1649
|
+
"id",
|
|
1650
|
+
"from",
|
|
1651
|
+
"to",
|
|
1652
|
+
"type",
|
|
1653
|
+
"created_at"
|
|
1654
|
+
]);
|
|
1655
|
+
}, ctx.formatter);
|
|
1656
|
+
}
|
|
1657
|
+
async function redirectRulesDelete(args, ctx) {
|
|
1658
|
+
const [id] = args;
|
|
1659
|
+
const usage = "forge-cli redirect-rules delete <rule_id> --server <server_id> --site <site_id>";
|
|
1660
|
+
if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
|
|
1661
|
+
const { server, site } = requireServerAndSiteRaw$1(ctx, usage);
|
|
1662
|
+
await runCommand(async () => {
|
|
1663
|
+
const token = ctx.getToken();
|
|
1664
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1665
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1666
|
+
await deleteRedirectRule({
|
|
1667
|
+
server_id,
|
|
1668
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1669
|
+
id
|
|
1670
|
+
}, execCtx);
|
|
1671
|
+
ctx.formatter.success(`Redirect rule ${id} deleted.`);
|
|
1672
|
+
}, ctx.formatter);
|
|
1673
|
+
}
|
|
1674
|
+
const handleRedirectRulesCommand = createCommandRouter({
|
|
1675
|
+
resource: "redirect-rules",
|
|
1676
|
+
handlers: {
|
|
1677
|
+
list: redirectRulesList,
|
|
1678
|
+
ls: redirectRulesList,
|
|
1679
|
+
get: [redirectRulesGet, "args"],
|
|
1680
|
+
create: redirectRulesCreate,
|
|
1681
|
+
delete: [redirectRulesDelete, "args"]
|
|
1682
|
+
}
|
|
1683
|
+
});
|
|
1684
|
+
function showRedirectRulesHelp(subcommand) {
|
|
1685
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1686
|
+
${colors.bold("forge-cli redirect-rules list")} - List redirect rules for a site
|
|
1687
|
+
|
|
1688
|
+
${colors.bold("USAGE:")}
|
|
1689
|
+
forge-cli redirect-rules list --server <server_id> --site <site_id> [options]
|
|
1690
|
+
|
|
1691
|
+
${colors.bold("OPTIONS:")}
|
|
1692
|
+
--server <id> Server ID (required)
|
|
1693
|
+
--site <id> Site ID (required)
|
|
1694
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1695
|
+
`);
|
|
1696
|
+
else if (subcommand === "get") console.log(`
|
|
1697
|
+
${colors.bold("forge-cli redirect-rules get")} - Get redirect rule details
|
|
1698
|
+
|
|
1699
|
+
${colors.bold("USAGE:")}
|
|
1700
|
+
forge-cli redirect-rules get <rule_id> --server <server_id> --site <site_id> [options]
|
|
1701
|
+
`);
|
|
1702
|
+
else if (subcommand === "create") console.log(`
|
|
1703
|
+
${colors.bold("forge-cli redirect-rules create")} - Create a new redirect rule
|
|
1704
|
+
|
|
1705
|
+
${colors.bold("USAGE:")}
|
|
1706
|
+
forge-cli redirect-rules create --server <server_id> --site <site_id> --from <from> --to <to> [options]
|
|
1707
|
+
|
|
1708
|
+
${colors.bold("OPTIONS:")}
|
|
1709
|
+
--server <id> Server ID (required)
|
|
1710
|
+
--site <id> Site ID (required)
|
|
1711
|
+
--from <path> Source path to redirect from (required)
|
|
1712
|
+
--to <path> Destination path to redirect to (required)
|
|
1713
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1714
|
+
`);
|
|
1715
|
+
else if (subcommand === "delete") console.log(`
|
|
1716
|
+
${colors.bold("forge-cli redirect-rules delete")} - Delete a redirect rule
|
|
1717
|
+
|
|
1718
|
+
${colors.bold("USAGE:")}
|
|
1719
|
+
forge-cli redirect-rules delete <rule_id> --server <server_id> --site <site_id> [options]
|
|
1720
|
+
`);
|
|
1721
|
+
else console.log(`
|
|
1722
|
+
${colors.bold("forge-cli redirect-rules")} - Manage site redirect rules
|
|
1723
|
+
|
|
1724
|
+
${colors.bold("USAGE:")}
|
|
1725
|
+
forge-cli redirect-rules <subcommand> [options]
|
|
1726
|
+
|
|
1727
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1728
|
+
list, ls List redirect rules
|
|
1729
|
+
get <id> Get redirect rule details
|
|
1730
|
+
create Create a new redirect rule
|
|
1731
|
+
delete <id> Delete a redirect rule
|
|
1732
|
+
|
|
1733
|
+
${colors.bold("OPTIONS:")}
|
|
1734
|
+
--server <id> Server ID (required)
|
|
1735
|
+
--site <id> Site ID (required)
|
|
1736
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1737
|
+
|
|
1738
|
+
Run ${colors.cyan("forge-cli redirect-rules <subcommand> --help")} for details.
|
|
1739
|
+
`);
|
|
1740
|
+
}
|
|
1741
|
+
async function scheduledJobsList(ctx) {
|
|
1742
|
+
const server = String(ctx.options.server ?? "");
|
|
1743
|
+
if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs list --server <server_id>", ctx.formatter);
|
|
1744
|
+
await runCommand(async () => {
|
|
1745
|
+
const token = ctx.getToken();
|
|
1746
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1747
|
+
const result = await listScheduledJobs({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
1748
|
+
ctx.formatter.outputList(result.data, [
|
|
1749
|
+
"id",
|
|
1750
|
+
"command",
|
|
1751
|
+
"frequency",
|
|
1752
|
+
"status"
|
|
1753
|
+
], "No scheduled jobs found.", (j) => `${String(j.id).padEnd(8)} ${j.command.padEnd(50)} ${j.frequency.padEnd(12)} ${j.status}`);
|
|
1754
|
+
}, ctx.formatter);
|
|
1755
|
+
}
|
|
1756
|
+
async function scheduledJobsGet(args, ctx) {
|
|
1757
|
+
const [id] = args;
|
|
1758
|
+
const server = String(ctx.options.server ?? "");
|
|
1759
|
+
if (!id) exitWithValidationError("job_id", "forge-cli scheduled-jobs get <job_id> --server <server_id>", ctx.formatter);
|
|
1760
|
+
if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs get <job_id> --server <server_id>", ctx.formatter);
|
|
1761
|
+
await runCommand(async () => {
|
|
1762
|
+
const token = ctx.getToken();
|
|
1763
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1764
|
+
const result = await getScheduledJob({
|
|
1765
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1766
|
+
id
|
|
1767
|
+
}, execCtx);
|
|
1768
|
+
ctx.formatter.outputOne(result.data, [
|
|
1769
|
+
"id",
|
|
1770
|
+
"command",
|
|
1771
|
+
"user",
|
|
1772
|
+
"frequency",
|
|
1773
|
+
"cron",
|
|
1774
|
+
"status",
|
|
1775
|
+
"created_at"
|
|
1776
|
+
]);
|
|
1777
|
+
}, ctx.formatter);
|
|
1778
|
+
}
|
|
1779
|
+
async function scheduledJobsCreate(ctx) {
|
|
1780
|
+
const server = String(ctx.options.server ?? "");
|
|
1781
|
+
const command = String(ctx.options.command ?? "");
|
|
1782
|
+
if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs create --server <server_id> --command <command>", ctx.formatter);
|
|
1783
|
+
if (!command) exitWithValidationError("command", "forge-cli scheduled-jobs create --server <server_id> --command <command>", ctx.formatter);
|
|
1784
|
+
await runCommand(async () => {
|
|
1785
|
+
const token = ctx.getToken();
|
|
1786
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1787
|
+
const result = await createScheduledJob({
|
|
1788
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1789
|
+
command
|
|
1790
|
+
}, execCtx);
|
|
1791
|
+
ctx.formatter.outputOne(result.data, [
|
|
1792
|
+
"id",
|
|
1793
|
+
"command",
|
|
1794
|
+
"user",
|
|
1795
|
+
"frequency",
|
|
1796
|
+
"cron",
|
|
1797
|
+
"status",
|
|
1798
|
+
"created_at"
|
|
1799
|
+
]);
|
|
1800
|
+
}, ctx.formatter);
|
|
1801
|
+
}
|
|
1802
|
+
async function scheduledJobsDelete(args, ctx) {
|
|
1803
|
+
const [id] = args;
|
|
1804
|
+
const server = String(ctx.options.server ?? "");
|
|
1805
|
+
if (!id) exitWithValidationError("job_id", "forge-cli scheduled-jobs delete <job_id> --server <server_id>", ctx.formatter);
|
|
1806
|
+
if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs delete <job_id> --server <server_id>", ctx.formatter);
|
|
1807
|
+
await runCommand(async () => {
|
|
1808
|
+
const token = ctx.getToken();
|
|
1809
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1810
|
+
await deleteScheduledJob({
|
|
1811
|
+
server_id: await resolveServerId(server, execCtx),
|
|
1812
|
+
id
|
|
1813
|
+
}, execCtx);
|
|
1814
|
+
ctx.formatter.success(`Scheduled job ${id} deleted.`);
|
|
1815
|
+
}, ctx.formatter);
|
|
1816
|
+
}
|
|
1817
|
+
const handleScheduledJobsCommand = createCommandRouter({
|
|
1818
|
+
resource: "scheduled-jobs",
|
|
1819
|
+
handlers: {
|
|
1820
|
+
list: scheduledJobsList,
|
|
1821
|
+
ls: scheduledJobsList,
|
|
1822
|
+
get: [scheduledJobsGet, "args"],
|
|
1823
|
+
create: scheduledJobsCreate,
|
|
1824
|
+
delete: [scheduledJobsDelete, "args"]
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
function showScheduledJobsHelp(subcommand) {
|
|
1828
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1829
|
+
${colors.bold("forge-cli scheduled-jobs list")} - List scheduled jobs on a server
|
|
1830
|
+
|
|
1831
|
+
${colors.bold("USAGE:")}
|
|
1832
|
+
forge-cli scheduled-jobs list --server <server_id> [options]
|
|
1833
|
+
|
|
1834
|
+
${colors.bold("OPTIONS:")}
|
|
1835
|
+
--server <id> Server ID (required)
|
|
1836
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1837
|
+
`);
|
|
1838
|
+
else if (subcommand === "get") console.log(`
|
|
1839
|
+
${colors.bold("forge-cli scheduled-jobs get")} - Get scheduled job details
|
|
1840
|
+
|
|
1841
|
+
${colors.bold("USAGE:")}
|
|
1842
|
+
forge-cli scheduled-jobs get <job_id> --server <server_id> [options]
|
|
1843
|
+
`);
|
|
1844
|
+
else if (subcommand === "create") console.log(`
|
|
1845
|
+
${colors.bold("forge-cli scheduled-jobs create")} - Create a new scheduled job
|
|
1846
|
+
|
|
1847
|
+
${colors.bold("USAGE:")}
|
|
1848
|
+
forge-cli scheduled-jobs create --server <server_id> --command <command> [options]
|
|
1849
|
+
|
|
1850
|
+
${colors.bold("OPTIONS:")}
|
|
1851
|
+
--server <id> Server ID (required)
|
|
1852
|
+
--command <cmd> Command to run (required)
|
|
1853
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1854
|
+
`);
|
|
1855
|
+
else if (subcommand === "delete") console.log(`
|
|
1856
|
+
${colors.bold("forge-cli scheduled-jobs delete")} - Delete a scheduled job
|
|
1857
|
+
|
|
1858
|
+
${colors.bold("USAGE:")}
|
|
1859
|
+
forge-cli scheduled-jobs delete <job_id> --server <server_id> [options]
|
|
1860
|
+
`);
|
|
1861
|
+
else console.log(`
|
|
1862
|
+
${colors.bold("forge-cli scheduled-jobs")} - Manage scheduled jobs (cron)
|
|
1863
|
+
|
|
1864
|
+
${colors.bold("USAGE:")}
|
|
1865
|
+
forge-cli scheduled-jobs <subcommand> [options]
|
|
1866
|
+
|
|
1867
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
1868
|
+
list, ls List scheduled jobs
|
|
1869
|
+
get <id> Get scheduled job details
|
|
1870
|
+
create Create a new scheduled job
|
|
1871
|
+
delete <id> Delete a scheduled job
|
|
1872
|
+
|
|
1873
|
+
${colors.bold("OPTIONS:")}
|
|
1874
|
+
--server <id> Server ID (required)
|
|
1875
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1876
|
+
|
|
1877
|
+
Run ${colors.cyan("forge-cli scheduled-jobs <subcommand> --help")} for details.
|
|
1878
|
+
`);
|
|
1879
|
+
}
|
|
1880
|
+
function requireServerAndSiteRaw(ctx, usage) {
|
|
1881
|
+
const server = String(ctx.options.server ?? "");
|
|
1882
|
+
const site = String(ctx.options.site ?? "");
|
|
1883
|
+
if (!server) exitWithValidationError("server_id", usage, ctx.formatter);
|
|
1884
|
+
if (!site) exitWithValidationError("site_id", usage, ctx.formatter);
|
|
1885
|
+
return {
|
|
1886
|
+
server,
|
|
1887
|
+
site
|
|
1888
|
+
};
|
|
1889
|
+
}
|
|
1890
|
+
async function securityRulesList(ctx) {
|
|
1891
|
+
const { server, site } = requireServerAndSiteRaw(ctx, "forge-cli security-rules list --server <server_id> --site <site_id>");
|
|
1892
|
+
await runCommand(async () => {
|
|
1893
|
+
const token = ctx.getToken();
|
|
1894
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1895
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1896
|
+
const result = await listSecurityRules({
|
|
1897
|
+
server_id,
|
|
1898
|
+
site_id: await resolveSiteId(site, server_id, execCtx)
|
|
1899
|
+
}, execCtx);
|
|
1900
|
+
ctx.formatter.outputList(result.data, [
|
|
1901
|
+
"id",
|
|
1902
|
+
"name",
|
|
1903
|
+
"path"
|
|
1904
|
+
], "No security rules found.", (r) => `${String(r.id).padEnd(8)} ${r.name.padEnd(30)} ${r.path ?? "—"}`);
|
|
1905
|
+
}, ctx.formatter);
|
|
1906
|
+
}
|
|
1907
|
+
async function securityRulesGet(args, ctx) {
|
|
1908
|
+
const [id] = args;
|
|
1909
|
+
const usage = "forge-cli security-rules get <rule_id> --server <server_id> --site <site_id>";
|
|
1910
|
+
if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
|
|
1911
|
+
const { server, site } = requireServerAndSiteRaw(ctx, usage);
|
|
1912
|
+
await runCommand(async () => {
|
|
1913
|
+
const token = ctx.getToken();
|
|
1914
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1915
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1916
|
+
const result = await getSecurityRule({
|
|
1917
|
+
server_id,
|
|
1918
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1919
|
+
id
|
|
1920
|
+
}, execCtx);
|
|
1921
|
+
ctx.formatter.outputOne(result.data, [
|
|
1922
|
+
"id",
|
|
1923
|
+
"name",
|
|
1924
|
+
"path",
|
|
1925
|
+
"credentials",
|
|
1926
|
+
"created_at"
|
|
1927
|
+
]);
|
|
1928
|
+
}, ctx.formatter);
|
|
1929
|
+
}
|
|
1930
|
+
async function securityRulesCreate(ctx) {
|
|
1931
|
+
const usage = "forge-cli security-rules create --server <server_id> --site <site_id> --name <name>";
|
|
1932
|
+
const { server, site } = requireServerAndSiteRaw(ctx, usage);
|
|
1933
|
+
const name = String(ctx.options.name ?? "");
|
|
1934
|
+
if (!name) exitWithValidationError("name", usage, ctx.formatter);
|
|
1935
|
+
await runCommand(async () => {
|
|
1936
|
+
const token = ctx.getToken();
|
|
1937
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1938
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1939
|
+
const result = await createSecurityRule({
|
|
1940
|
+
server_id,
|
|
1941
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1942
|
+
name,
|
|
1943
|
+
credentials: []
|
|
1944
|
+
}, execCtx);
|
|
1945
|
+
ctx.formatter.outputOne(result.data, [
|
|
1946
|
+
"id",
|
|
1947
|
+
"name",
|
|
1948
|
+
"path",
|
|
1949
|
+
"created_at"
|
|
1950
|
+
]);
|
|
1951
|
+
}, ctx.formatter);
|
|
1952
|
+
}
|
|
1953
|
+
async function securityRulesDelete(args, ctx) {
|
|
1954
|
+
const [id] = args;
|
|
1955
|
+
const usage = "forge-cli security-rules delete <rule_id> --server <server_id> --site <site_id>";
|
|
1956
|
+
if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
|
|
1957
|
+
const { server, site } = requireServerAndSiteRaw(ctx, usage);
|
|
1958
|
+
await runCommand(async () => {
|
|
1959
|
+
const token = ctx.getToken();
|
|
1960
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
1961
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
1962
|
+
await deleteSecurityRule({
|
|
1963
|
+
server_id,
|
|
1964
|
+
site_id: await resolveSiteId(site, server_id, execCtx),
|
|
1965
|
+
id
|
|
1966
|
+
}, execCtx);
|
|
1967
|
+
ctx.formatter.success(`Security rule ${id} deleted.`);
|
|
1968
|
+
}, ctx.formatter);
|
|
1969
|
+
}
|
|
1970
|
+
const handleSecurityRulesCommand = createCommandRouter({
|
|
1971
|
+
resource: "security-rules",
|
|
1972
|
+
handlers: {
|
|
1973
|
+
list: securityRulesList,
|
|
1974
|
+
ls: securityRulesList,
|
|
1975
|
+
get: [securityRulesGet, "args"],
|
|
1976
|
+
create: securityRulesCreate,
|
|
1977
|
+
delete: [securityRulesDelete, "args"]
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
function showSecurityRulesHelp(subcommand) {
|
|
1981
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
1982
|
+
${colors.bold("forge-cli security-rules list")} - List security rules for a site
|
|
1983
|
+
|
|
1984
|
+
${colors.bold("USAGE:")}
|
|
1985
|
+
forge-cli security-rules list --server <server_id> --site <site_id> [options]
|
|
1986
|
+
|
|
1987
|
+
${colors.bold("OPTIONS:")}
|
|
1988
|
+
--server <id> Server ID (required)
|
|
1989
|
+
--site <id> Site ID (required)
|
|
1990
|
+
-f, --format <fmt> Output format: json, human, table
|
|
1991
|
+
`);
|
|
1992
|
+
else if (subcommand === "get") console.log(`
|
|
1993
|
+
${colors.bold("forge-cli security-rules get")} - Get security rule details
|
|
1994
|
+
|
|
1995
|
+
${colors.bold("USAGE:")}
|
|
1996
|
+
forge-cli security-rules get <rule_id> --server <server_id> --site <site_id> [options]
|
|
1997
|
+
`);
|
|
1998
|
+
else if (subcommand === "create") console.log(`
|
|
1999
|
+
${colors.bold("forge-cli security-rules create")} - Create a new security rule
|
|
2000
|
+
|
|
2001
|
+
${colors.bold("USAGE:")}
|
|
2002
|
+
forge-cli security-rules create --server <server_id> --site <site_id> --name <name> [options]
|
|
2003
|
+
|
|
2004
|
+
${colors.bold("OPTIONS:")}
|
|
2005
|
+
--server <id> Server ID (required)
|
|
2006
|
+
--site <id> Site ID (required)
|
|
2007
|
+
--name <name> Security rule name (required)
|
|
2008
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2009
|
+
`);
|
|
2010
|
+
else if (subcommand === "delete") console.log(`
|
|
2011
|
+
${colors.bold("forge-cli security-rules delete")} - Delete a security rule
|
|
2012
|
+
|
|
2013
|
+
${colors.bold("USAGE:")}
|
|
2014
|
+
forge-cli security-rules delete <rule_id> --server <server_id> --site <site_id> [options]
|
|
2015
|
+
`);
|
|
2016
|
+
else console.log(`
|
|
2017
|
+
${colors.bold("forge-cli security-rules")} - Manage site security rules
|
|
2018
|
+
|
|
2019
|
+
${colors.bold("USAGE:")}
|
|
2020
|
+
forge-cli security-rules <subcommand> [options]
|
|
2021
|
+
|
|
2022
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
2023
|
+
list, ls List security rules
|
|
2024
|
+
get <id> Get security rule details
|
|
2025
|
+
create Create a new security rule
|
|
2026
|
+
delete <id> Delete a security rule
|
|
2027
|
+
|
|
2028
|
+
${colors.bold("OPTIONS:")}
|
|
2029
|
+
--server <id> Server ID (required)
|
|
2030
|
+
--site <id> Site ID (required)
|
|
2031
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2032
|
+
|
|
2033
|
+
Run ${colors.cyan("forge-cli security-rules <subcommand> --help")} for details.
|
|
2034
|
+
`);
|
|
2035
|
+
}
|
|
2036
|
+
/**
|
|
2037
|
+
* CLI handlers for servers commands.
|
|
2038
|
+
* Delegates all HTTP logic to forge-core executors.
|
|
2039
|
+
*/
|
|
2040
|
+
/**
|
|
2041
|
+
* List all servers.
|
|
2042
|
+
*/
|
|
2043
|
+
async function serversList(ctx) {
|
|
2044
|
+
await runCommand(async () => {
|
|
2045
|
+
const token = ctx.getToken();
|
|
2046
|
+
const result = await listServers({}, ctx.createExecutorContext(token));
|
|
2047
|
+
const format = String(ctx.options.format ?? ctx.options.f ?? "human");
|
|
2048
|
+
if (format === "table" || format === "json") ctx.formatter.output(result.data);
|
|
2049
|
+
else {
|
|
2050
|
+
if (result.data.length === 0) {
|
|
2051
|
+
ctx.formatter.info("No servers found.");
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
for (const server of result.data) console.log(`${String(server.id).padEnd(8)} ${server.name.padEnd(30)} ${server.ip_address.padEnd(16)} ${server.is_ready ? "ready" : "provisioning"}`);
|
|
2055
|
+
}
|
|
2056
|
+
}, ctx.formatter);
|
|
2057
|
+
}
|
|
2058
|
+
/**
|
|
2059
|
+
* Get a single server by ID or name.
|
|
2060
|
+
*/
|
|
2061
|
+
async function serversGet(args, ctx) {
|
|
2062
|
+
const [server] = args;
|
|
2063
|
+
if (!server) exitWithValidationError("server_id", "forge-cli servers get <server_id>", ctx.formatter);
|
|
2064
|
+
await runCommand(async () => {
|
|
2065
|
+
const token = ctx.getToken();
|
|
2066
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
2067
|
+
const result = await getServer({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
2068
|
+
ctx.formatter.output(result.data);
|
|
2069
|
+
}, ctx.formatter);
|
|
2070
|
+
}
|
|
2071
|
+
/**
|
|
2072
|
+
* Reboot a server by ID or name.
|
|
2073
|
+
*/
|
|
2074
|
+
async function serversReboot(args, ctx) {
|
|
2075
|
+
const [server] = args;
|
|
2076
|
+
if (!server) exitWithValidationError("server_id", "forge-cli servers reboot <server_id>", ctx.formatter);
|
|
2077
|
+
await runCommand(async () => {
|
|
2078
|
+
const token = ctx.getToken();
|
|
2079
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
2080
|
+
const server_id = await resolveServerId(server, execCtx);
|
|
2081
|
+
await rebootServer({ server_id }, execCtx);
|
|
2082
|
+
ctx.formatter.success(`Server ${server_id} reboot initiated.`);
|
|
2083
|
+
}, ctx.formatter);
|
|
2084
|
+
}
|
|
2085
|
+
const handleServersCommand = createCommandRouter({
|
|
2086
|
+
resource: "servers",
|
|
2087
|
+
handlers: {
|
|
2088
|
+
list: serversList,
|
|
2089
|
+
ls: serversList,
|
|
2090
|
+
get: [serversGet, "args"],
|
|
2091
|
+
reboot: [serversReboot, "args"]
|
|
2092
|
+
}
|
|
2093
|
+
});
|
|
2094
|
+
function showServersHelp(subcommand) {
|
|
2095
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2096
|
+
${colors.bold("forge-cli servers list")} - List all servers
|
|
2097
|
+
|
|
2098
|
+
${colors.bold("USAGE:")}
|
|
2099
|
+
forge-cli servers list [options]
|
|
2100
|
+
|
|
2101
|
+
${colors.bold("OPTIONS:")}
|
|
2102
|
+
--token <token> Forge API token
|
|
2103
|
+
-f, --format <fmt> Output format: json, human, table (default: human)
|
|
2104
|
+
--no-color Disable colored output
|
|
2105
|
+
-h, --help Show this help
|
|
2106
|
+
|
|
2107
|
+
${colors.bold("EXAMPLES:")}
|
|
2108
|
+
forge-cli servers list
|
|
2109
|
+
forge-cli servers list --format json
|
|
2110
|
+
`);
|
|
2111
|
+
else if (subcommand === "get") console.log(`
|
|
2112
|
+
${colors.bold("forge-cli servers get")} - Get server details
|
|
2113
|
+
|
|
2114
|
+
${colors.bold("USAGE:")}
|
|
2115
|
+
forge-cli servers get <server_id> [options]
|
|
2116
|
+
|
|
2117
|
+
${colors.bold("ARGUMENTS:")}
|
|
2118
|
+
<server_id> Server ID (required)
|
|
2119
|
+
|
|
2120
|
+
${colors.bold("OPTIONS:")}
|
|
2121
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2122
|
+
|
|
2123
|
+
${colors.bold("EXAMPLES:")}
|
|
2124
|
+
forge-cli servers get 123
|
|
2125
|
+
forge-cli servers get 123 --format json
|
|
2126
|
+
`);
|
|
2127
|
+
else if (subcommand === "reboot") console.log(`
|
|
2128
|
+
${colors.bold("forge-cli servers reboot")} - Reboot a server
|
|
2129
|
+
|
|
2130
|
+
${colors.bold("USAGE:")}
|
|
2131
|
+
forge-cli servers reboot <server_id> [options]
|
|
2132
|
+
|
|
2133
|
+
${colors.bold("ARGUMENTS:")}
|
|
2134
|
+
<server_id> Server ID (required)
|
|
2135
|
+
|
|
2136
|
+
${colors.bold("EXAMPLES:")}
|
|
2137
|
+
forge-cli servers reboot 123
|
|
2138
|
+
`);
|
|
2139
|
+
else console.log(`
|
|
2140
|
+
${colors.bold("forge-cli servers")} - Manage servers
|
|
2141
|
+
|
|
2142
|
+
${colors.bold("USAGE:")}
|
|
2143
|
+
forge-cli servers <subcommand> [options]
|
|
2144
|
+
|
|
2145
|
+
${colors.bold("ALIASES:")}
|
|
2146
|
+
forge-cli s
|
|
2147
|
+
|
|
2148
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
2149
|
+
list, ls List all servers
|
|
2150
|
+
get <id> Get server details
|
|
2151
|
+
reboot <id> Reboot a server
|
|
2152
|
+
|
|
2153
|
+
${colors.bold("OPTIONS:")}
|
|
2154
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2155
|
+
-h, --help Show help for a subcommand
|
|
2156
|
+
|
|
2157
|
+
${colors.bold("EXAMPLES:")}
|
|
2158
|
+
forge-cli servers list
|
|
2159
|
+
forge-cli servers get 123
|
|
2160
|
+
|
|
2161
|
+
Run ${colors.cyan("forge-cli servers <subcommand> --help")} for subcommand details.
|
|
2162
|
+
`);
|
|
2163
|
+
}
|
|
2164
|
+
async function sitesList(ctx) {
|
|
2165
|
+
const server = String(ctx.options.server ?? "");
|
|
2166
|
+
if (!server) exitWithValidationError("server_id", "forge-cli sites list --server <server_id>", ctx.formatter);
|
|
2167
|
+
await runCommand(async () => {
|
|
2168
|
+
const token = ctx.getToken();
|
|
2169
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
2170
|
+
const result = await listSites({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
2171
|
+
ctx.formatter.outputList(result.data, [
|
|
2172
|
+
"id",
|
|
2173
|
+
"name",
|
|
2174
|
+
"status",
|
|
2175
|
+
"php_version"
|
|
2176
|
+
], "No sites found.", (s) => `${String(s.id).padEnd(8)} ${s.name.padEnd(40)} ${s.status.padEnd(12)} ${s.php_version}`);
|
|
2177
|
+
}, ctx.formatter);
|
|
2178
|
+
}
|
|
2179
|
+
async function sitesGet(args, ctx) {
|
|
2180
|
+
const [site_id] = args;
|
|
2181
|
+
const server = String(ctx.options.server ?? "");
|
|
2182
|
+
if (!site_id) exitWithValidationError("site_id", "forge-cli sites get <site_id> --server <server_id>", ctx.formatter);
|
|
2183
|
+
if (!server) exitWithValidationError("server_id", "forge-cli sites get <site_id> --server <server_id>", ctx.formatter);
|
|
2184
|
+
await runCommand(async () => {
|
|
2185
|
+
const token = ctx.getToken();
|
|
2186
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
2187
|
+
const result = await getSite({
|
|
2188
|
+
server_id: await resolveServerId(server, execCtx),
|
|
2189
|
+
site_id
|
|
2190
|
+
}, execCtx);
|
|
2191
|
+
ctx.formatter.outputOne(result.data, [
|
|
2192
|
+
"id",
|
|
2193
|
+
"name",
|
|
2194
|
+
"status",
|
|
2195
|
+
"php_version",
|
|
2196
|
+
"project_type",
|
|
2197
|
+
"repository",
|
|
2198
|
+
"repository_branch",
|
|
2199
|
+
"quick_deploy",
|
|
2200
|
+
"deployment_status",
|
|
2201
|
+
"is_secured",
|
|
2202
|
+
"created_at"
|
|
2203
|
+
]);
|
|
2204
|
+
}, ctx.formatter);
|
|
2205
|
+
}
|
|
2206
|
+
const handleSitesCommand = createCommandRouter({
|
|
2207
|
+
resource: "sites",
|
|
2208
|
+
handlers: {
|
|
2209
|
+
list: sitesList,
|
|
2210
|
+
ls: sitesList,
|
|
2211
|
+
get: [sitesGet, "args"]
|
|
2212
|
+
}
|
|
2213
|
+
});
|
|
2214
|
+
function showSitesHelp(subcommand) {
|
|
2215
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2216
|
+
${colors.bold("forge-cli sites list")} - List sites on a server
|
|
2217
|
+
|
|
2218
|
+
${colors.bold("USAGE:")}
|
|
2219
|
+
forge-cli sites list --server <server_id> [options]
|
|
2220
|
+
|
|
2221
|
+
${colors.bold("OPTIONS:")}
|
|
2222
|
+
--server <id> Server ID (required)
|
|
2223
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2224
|
+
|
|
2225
|
+
${colors.bold("EXAMPLES:")}
|
|
2226
|
+
forge-cli sites list --server 123
|
|
2227
|
+
forge-cli sites list --server 123 --format json
|
|
2228
|
+
`);
|
|
2229
|
+
else if (subcommand === "get") console.log(`
|
|
2230
|
+
${colors.bold("forge-cli sites get")} - Get site details
|
|
2231
|
+
|
|
2232
|
+
${colors.bold("USAGE:")}
|
|
2233
|
+
forge-cli sites get <site_id> --server <server_id> [options]
|
|
2234
|
+
|
|
2235
|
+
${colors.bold("ARGUMENTS:")}
|
|
2236
|
+
<site_id> Site ID (required)
|
|
2237
|
+
|
|
2238
|
+
${colors.bold("OPTIONS:")}
|
|
2239
|
+
--server <id> Server ID (required)
|
|
2240
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2241
|
+
`);
|
|
2242
|
+
else console.log(`
|
|
2243
|
+
${colors.bold("forge-cli sites")} - Manage sites
|
|
2244
|
+
|
|
2245
|
+
${colors.bold("USAGE:")}
|
|
2246
|
+
forge-cli sites <subcommand> [options]
|
|
2247
|
+
|
|
2248
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
2249
|
+
list, ls List sites on a server
|
|
2250
|
+
get <id> Get site details
|
|
2251
|
+
|
|
2252
|
+
${colors.bold("OPTIONS:")}
|
|
2253
|
+
--server <id> Server ID (required for most commands)
|
|
2254
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2255
|
+
-h, --help Show help for a subcommand
|
|
2256
|
+
|
|
2257
|
+
${colors.bold("EXAMPLES:")}
|
|
2258
|
+
forge-cli sites list --server 123
|
|
2259
|
+
forge-cli sites get 456 --server 123
|
|
2260
|
+
|
|
2261
|
+
Run ${colors.cyan("forge-cli sites <subcommand> --help")} for subcommand details.
|
|
2262
|
+
`);
|
|
2263
|
+
}
|
|
2264
|
+
async function sshKeysList(ctx) {
|
|
2265
|
+
const server = String(ctx.options.server ?? "");
|
|
2266
|
+
if (!server) exitWithValidationError("server_id", "forge-cli ssh-keys list --server <server_id>", ctx.formatter);
|
|
2267
|
+
await runCommand(async () => {
|
|
2268
|
+
const token = ctx.getToken();
|
|
2269
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
2270
|
+
const result = await listSshKeys({ server_id: await resolveServerId(server, execCtx) }, execCtx);
|
|
2271
|
+
ctx.formatter.outputList(result.data, [
|
|
2272
|
+
"id",
|
|
2273
|
+
"name",
|
|
2274
|
+
"status"
|
|
2275
|
+
], "No SSH keys found.", (k) => `${String(k.id).padEnd(8)} ${k.name.padEnd(30)} ${k.status}`);
|
|
2276
|
+
}, ctx.formatter);
|
|
2277
|
+
}
|
|
2278
|
+
async function sshKeysGet(args, ctx) {
|
|
2279
|
+
const [id] = args;
|
|
2280
|
+
const server = String(ctx.options.server ?? "");
|
|
2281
|
+
if (!id) exitWithValidationError("ssh_key_id", "forge-cli ssh-keys get <key_id> --server <server_id>", ctx.formatter);
|
|
2282
|
+
if (!server) exitWithValidationError("server_id", "forge-cli ssh-keys get <key_id> --server <server_id>", ctx.formatter);
|
|
2283
|
+
await runCommand(async () => {
|
|
2284
|
+
const token = ctx.getToken();
|
|
2285
|
+
const execCtx = ctx.createExecutorContext(token);
|
|
2286
|
+
const result = await getSshKey({
|
|
2287
|
+
server_id: await resolveServerId(server, execCtx),
|
|
2288
|
+
id
|
|
2289
|
+
}, execCtx);
|
|
2290
|
+
ctx.formatter.outputOne(result.data, [
|
|
2291
|
+
"id",
|
|
2292
|
+
"name",
|
|
2293
|
+
"status",
|
|
2294
|
+
"created_at"
|
|
2295
|
+
]);
|
|
2296
|
+
}, ctx.formatter);
|
|
2297
|
+
}
|
|
2298
|
+
const handleSshKeysCommand = createCommandRouter({
|
|
2299
|
+
resource: "ssh-keys",
|
|
2300
|
+
handlers: {
|
|
2301
|
+
list: sshKeysList,
|
|
2302
|
+
ls: sshKeysList,
|
|
2303
|
+
get: [sshKeysGet, "args"]
|
|
2304
|
+
}
|
|
2305
|
+
});
|
|
2306
|
+
function showSshKeysHelp(subcommand) {
|
|
2307
|
+
if (subcommand === "list" || subcommand === "ls") console.log(`
|
|
2308
|
+
${colors.bold("forge-cli ssh-keys list")} - List SSH keys on a server
|
|
2309
|
+
|
|
2310
|
+
${colors.bold("USAGE:")}
|
|
2311
|
+
forge-cli ssh-keys list --server <server_id> [options]
|
|
2312
|
+
`);
|
|
2313
|
+
else if (subcommand === "get") console.log(`
|
|
2314
|
+
${colors.bold("forge-cli ssh-keys get")} - Get SSH key details
|
|
2315
|
+
|
|
2316
|
+
${colors.bold("USAGE:")}
|
|
2317
|
+
forge-cli ssh-keys get <key_id> --server <server_id>
|
|
2318
|
+
`);
|
|
2319
|
+
else console.log(`
|
|
2320
|
+
${colors.bold("forge-cli ssh-keys")} - Manage SSH keys
|
|
2321
|
+
|
|
2322
|
+
${colors.bold("USAGE:")}
|
|
2323
|
+
forge-cli ssh-keys <subcommand> [options]
|
|
2324
|
+
|
|
2325
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
2326
|
+
list, ls List SSH keys
|
|
2327
|
+
get <id> Get SSH key details
|
|
2328
|
+
|
|
2329
|
+
${colors.bold("OPTIONS:")}
|
|
2330
|
+
--server <id> Server ID (required)
|
|
2331
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2332
|
+
|
|
2333
|
+
Run ${colors.cyan("forge-cli ssh-keys <subcommand> --help")} for details.
|
|
2334
|
+
`);
|
|
2335
|
+
}
|
|
2336
|
+
async function userGet(ctx) {
|
|
2337
|
+
await runCommand(async () => {
|
|
2338
|
+
const token = ctx.getToken();
|
|
2339
|
+
const result = await getUser({}, ctx.createExecutorContext(token));
|
|
2340
|
+
ctx.formatter.output(result.data);
|
|
2341
|
+
}, ctx.formatter);
|
|
2342
|
+
}
|
|
2343
|
+
const handleUserCommand = createCommandRouter({
|
|
2344
|
+
resource: "user",
|
|
2345
|
+
handlers: { get: userGet }
|
|
2346
|
+
});
|
|
2347
|
+
function showUserHelp(subcommand) {
|
|
2348
|
+
if (subcommand === "get") console.log(`
|
|
2349
|
+
${colors.bold("forge-cli user get")} - Get the authenticated user profile
|
|
2350
|
+
|
|
2351
|
+
${colors.bold("USAGE:")}
|
|
2352
|
+
forge-cli user get [options]
|
|
2353
|
+
|
|
2354
|
+
${colors.bold("OPTIONS:")}
|
|
2355
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2356
|
+
`);
|
|
2357
|
+
else console.log(`
|
|
2358
|
+
${colors.bold("forge-cli user")} - Display authenticated user profile
|
|
2359
|
+
|
|
2360
|
+
${colors.bold("USAGE:")}
|
|
2361
|
+
forge-cli user [subcommand] [options]
|
|
2362
|
+
|
|
2363
|
+
${colors.bold("SUBCOMMANDS:")}
|
|
2364
|
+
get Get the authenticated user profile
|
|
2365
|
+
|
|
2366
|
+
${colors.bold("OPTIONS:")}
|
|
2367
|
+
-f, --format <fmt> Output format: json, human, table
|
|
2368
|
+
|
|
2369
|
+
Run ${colors.cyan("forge-cli user <subcommand> --help")} for details.
|
|
2370
|
+
`);
|
|
2371
|
+
}
|
|
2372
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
2373
|
+
const options = {};
|
|
2374
|
+
const positional = [];
|
|
2375
|
+
const command = [];
|
|
2376
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2377
|
+
const arg = argv[i];
|
|
2378
|
+
if (arg.startsWith("--")) {
|
|
2379
|
+
const equalIndex = arg.indexOf("=");
|
|
2380
|
+
if (equalIndex > -1) {
|
|
2381
|
+
const key = arg.slice(2, equalIndex);
|
|
2382
|
+
options[key] = arg.slice(equalIndex + 1);
|
|
2383
|
+
} else {
|
|
2384
|
+
const key = arg.slice(2);
|
|
2385
|
+
const nextArg = argv[i + 1];
|
|
2386
|
+
if (nextArg !== void 0 && !nextArg.startsWith("-")) {
|
|
2387
|
+
options[key] = nextArg;
|
|
2388
|
+
i++;
|
|
2389
|
+
} else options[key] = true;
|
|
2390
|
+
}
|
|
2391
|
+
} else if (arg.startsWith("-") && arg.length > 1) if (arg.length === 2) {
|
|
2392
|
+
const key = arg[1];
|
|
2393
|
+
const nextArg = argv[i + 1];
|
|
2394
|
+
if (nextArg !== void 0 && !nextArg.startsWith("-")) {
|
|
2395
|
+
options[key] = nextArg;
|
|
2396
|
+
i++;
|
|
2397
|
+
} else options[key] = true;
|
|
2398
|
+
} else for (let j = 1; j < arg.length; j++) options[arg[j]] = true;
|
|
2399
|
+
else if (command.length < 2) command.push(arg);
|
|
2400
|
+
else positional.push(arg);
|
|
2401
|
+
}
|
|
2402
|
+
return {
|
|
2403
|
+
command,
|
|
2404
|
+
options,
|
|
2405
|
+
positional
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
var VERSION = "0.1.0";
|
|
2409
|
+
function showHelp() {
|
|
2410
|
+
console.log(`
|
|
2411
|
+
${colors.bold("forge-cli")} v${VERSION}
|
|
2412
|
+
|
|
2413
|
+
${colors.bold("USAGE:")}
|
|
2414
|
+
forge-cli <command> [subcommand] [options]
|
|
2415
|
+
|
|
2416
|
+
${colors.bold("COMMANDS:")}
|
|
2417
|
+
config Manage CLI configuration
|
|
2418
|
+
set <token> Save API token
|
|
2419
|
+
get Show current token (masked)
|
|
2420
|
+
delete Delete stored token
|
|
2421
|
+
|
|
2422
|
+
servers, s Manage servers
|
|
2423
|
+
list, ls List all servers
|
|
2424
|
+
get <id> Get server details
|
|
2425
|
+
reboot <id> Reboot a server
|
|
2426
|
+
|
|
2427
|
+
sites Manage sites
|
|
2428
|
+
list, ls List sites (requires --server)
|
|
2429
|
+
get <id> Get site details (requires --server)
|
|
2430
|
+
|
|
2431
|
+
deployments, d Manage deployments
|
|
2432
|
+
list, ls List deployments (requires --server --site)
|
|
2433
|
+
deploy Trigger a deployment (requires --server --site)
|
|
2434
|
+
|
|
2435
|
+
databases, db Manage databases
|
|
2436
|
+
list, ls List databases (requires --server)
|
|
2437
|
+
get <id> Get database details (requires --server)
|
|
2438
|
+
|
|
2439
|
+
database-users Manage database users
|
|
2440
|
+
list, ls List database users (requires --server)
|
|
2441
|
+
get <id> Get database user details (requires --server)
|
|
2442
|
+
create Create a database user (requires --server --name --password)
|
|
2443
|
+
delete <id> Delete a database user (requires --server)
|
|
2444
|
+
|
|
2445
|
+
daemons Manage daemons
|
|
2446
|
+
list, ls List daemons (requires --server)
|
|
2447
|
+
get <id> Get daemon details (requires --server)
|
|
2448
|
+
restart <id> Restart a daemon (requires --server)
|
|
2449
|
+
|
|
2450
|
+
env Manage environment variables
|
|
2451
|
+
get Get env variables (requires --server --site)
|
|
2452
|
+
update Update env variables (requires --server --site --content)
|
|
2453
|
+
|
|
2454
|
+
nginx Manage nginx configuration
|
|
2455
|
+
get Get nginx config (requires --server --site)
|
|
2456
|
+
update Update nginx config (requires --server --site --content)
|
|
2457
|
+
|
|
2458
|
+
certificates, certs Manage SSL certificates
|
|
2459
|
+
list, ls List certificates (requires --server --site)
|
|
2460
|
+
get <id> Get certificate details (requires --server --site)
|
|
2461
|
+
activate <id> Activate a certificate (requires --server --site)
|
|
2462
|
+
|
|
2463
|
+
firewall-rules, fw Manage firewall rules
|
|
2464
|
+
list, ls List firewall rules (requires --server)
|
|
2465
|
+
get <id> Get firewall rule details (requires --server)
|
|
2466
|
+
|
|
2467
|
+
ssh-keys Manage SSH keys
|
|
2468
|
+
list, ls List SSH keys (requires --server)
|
|
2469
|
+
get <id> Get SSH key details (requires --server)
|
|
2470
|
+
|
|
2471
|
+
backups Manage backup configurations
|
|
2472
|
+
list, ls List backup configurations (requires --server)
|
|
2473
|
+
get <id> Get backup configuration details (requires --server)
|
|
2474
|
+
create Create a backup configuration (requires --server --provider --frequency)
|
|
2475
|
+
delete <id> Delete a backup configuration (requires --server)
|
|
2476
|
+
|
|
2477
|
+
commands Manage site commands
|
|
2478
|
+
list, ls List commands (requires --server --site)
|
|
2479
|
+
get <id> Get command details (requires --server --site)
|
|
2480
|
+
create Execute a command (requires --server --site --command)
|
|
2481
|
+
|
|
2482
|
+
scheduled-jobs Manage scheduled jobs (cron)
|
|
2483
|
+
list, ls List scheduled jobs (requires --server)
|
|
2484
|
+
get <id> Get scheduled job details (requires --server)
|
|
2485
|
+
create Create a scheduled job (requires --server --command)
|
|
2486
|
+
delete <id> Delete a scheduled job (requires --server)
|
|
2487
|
+
|
|
2488
|
+
user Display authenticated user profile
|
|
2489
|
+
get Get the authenticated user profile
|
|
2490
|
+
|
|
2491
|
+
monitors Manage server monitors
|
|
2492
|
+
list, ls List monitors (requires --server)
|
|
2493
|
+
get <id> Get monitor details (requires --server)
|
|
2494
|
+
create Create a monitor (requires --server --type --operator --threshold --minutes)
|
|
2495
|
+
delete <id> Delete a monitor (requires --server)
|
|
2496
|
+
|
|
2497
|
+
nginx-templates Manage Nginx templates
|
|
2498
|
+
list, ls List Nginx templates (requires --server)
|
|
2499
|
+
get <id> Get Nginx template details (requires --server)
|
|
2500
|
+
create Create a Nginx template (requires --server --name --content)
|
|
2501
|
+
update <id> Update a Nginx template (requires --server)
|
|
2502
|
+
delete <id> Delete a Nginx template (requires --server)
|
|
2503
|
+
|
|
2504
|
+
security-rules Manage site security rules
|
|
2505
|
+
list, ls List security rules (requires --server --site)
|
|
2506
|
+
get <id> Get security rule details (requires --server --site)
|
|
2507
|
+
create Create a security rule (requires --server --site --name)
|
|
2508
|
+
delete <id> Delete a security rule (requires --server --site)
|
|
2509
|
+
|
|
2510
|
+
redirect-rules Manage site redirect rules
|
|
2511
|
+
list, ls List redirect rules (requires --server --site)
|
|
2512
|
+
get <id> Get redirect rule details (requires --server --site)
|
|
2513
|
+
create Create a redirect rule (requires --server --site --from --to)
|
|
2514
|
+
delete <id> Delete a redirect rule (requires --server --site)
|
|
2515
|
+
|
|
2516
|
+
recipes Manage recipes
|
|
2517
|
+
list, ls List all recipes
|
|
2518
|
+
get <id> Get recipe details
|
|
2519
|
+
run <id> Run a recipe (requires --servers)
|
|
2520
|
+
|
|
2521
|
+
${colors.bold("OPTIONS:")}
|
|
2522
|
+
--token <token> Forge API token (overrides config and env)
|
|
2523
|
+
--server <id> Server ID (required for server-scoped commands)
|
|
2524
|
+
--site <id> Site ID (required for site-scoped commands)
|
|
2525
|
+
-f, --format <fmt> Output format: json, human, table (default: human)
|
|
2526
|
+
--no-color Disable colored output
|
|
2527
|
+
-h, --help Show help
|
|
2528
|
+
-v, --version Show version
|
|
2529
|
+
|
|
2530
|
+
${colors.bold("EXAMPLES:")}
|
|
2531
|
+
# Configure API token
|
|
2532
|
+
forge-cli config set YOUR_TOKEN
|
|
2533
|
+
|
|
2534
|
+
# Or pass token directly
|
|
2535
|
+
forge-cli servers list --token YOUR_TOKEN
|
|
2536
|
+
|
|
2537
|
+
# List all servers
|
|
2538
|
+
forge-cli servers list
|
|
2539
|
+
|
|
2540
|
+
# List sites on a server
|
|
2541
|
+
forge-cli sites list --server 123
|
|
2542
|
+
|
|
2543
|
+
# Deploy a site
|
|
2544
|
+
forge-cli deployments deploy --server 123 --site 456
|
|
2545
|
+
|
|
2546
|
+
# Get JSON output (for AI agents)
|
|
2547
|
+
forge-cli servers list --format json
|
|
2548
|
+
|
|
2549
|
+
${colors.bold("CREDENTIAL PRIORITY:")}
|
|
2550
|
+
1. CLI argument (--token)
|
|
2551
|
+
2. Environment variable (FORGE_API_TOKEN)
|
|
2552
|
+
3. Config file (~/.config/forge-tools/config.json)
|
|
2553
|
+
|
|
2554
|
+
${colors.bold("ENVIRONMENT VARIABLES:")}
|
|
2555
|
+
FORGE_API_TOKEN API token
|
|
2556
|
+
NO_COLOR Disable colors
|
|
2557
|
+
XDG_CONFIG_HOME Config directory (respects XDG spec)
|
|
2558
|
+
`);
|
|
2559
|
+
}
|
|
2560
|
+
async function main() {
|
|
2561
|
+
const { command, options, positional } = parseArgs();
|
|
2562
|
+
const [mainCommand, subcommand] = command;
|
|
2563
|
+
const wantsHelp = options.help !== void 0 || options.h !== void 0;
|
|
2564
|
+
if (wantsHelp && !mainCommand) {
|
|
2565
|
+
showHelp();
|
|
2566
|
+
process.exit(0);
|
|
2567
|
+
}
|
|
2568
|
+
if (options.version || options.v) {
|
|
2569
|
+
console.log(VERSION);
|
|
2570
|
+
process.exit(0);
|
|
2571
|
+
}
|
|
2572
|
+
if (options["no-color"]) setColorEnabled(false);
|
|
2573
|
+
if (!mainCommand) {
|
|
2574
|
+
showHelp();
|
|
2575
|
+
process.exit(0);
|
|
2576
|
+
}
|
|
2577
|
+
try {
|
|
2578
|
+
switch (mainCommand) {
|
|
2579
|
+
case "config":
|
|
2580
|
+
if (wantsHelp) {
|
|
2581
|
+
showConfigHelp();
|
|
2582
|
+
process.exit(0);
|
|
2583
|
+
}
|
|
2584
|
+
handleConfigCommand(subcommand ?? "get", positional, options);
|
|
2585
|
+
break;
|
|
2586
|
+
case "servers":
|
|
2587
|
+
case "s":
|
|
2588
|
+
if (wantsHelp) {
|
|
2589
|
+
showServersHelp(subcommand);
|
|
2590
|
+
process.exit(0);
|
|
2591
|
+
}
|
|
2592
|
+
await handleServersCommand(subcommand ?? "list", positional, options);
|
|
2593
|
+
break;
|
|
2594
|
+
case "sites":
|
|
2595
|
+
if (wantsHelp) {
|
|
2596
|
+
showSitesHelp(subcommand);
|
|
2597
|
+
process.exit(0);
|
|
2598
|
+
}
|
|
2599
|
+
await handleSitesCommand(subcommand ?? "list", positional, options);
|
|
2600
|
+
break;
|
|
2601
|
+
case "deployments":
|
|
2602
|
+
case "d":
|
|
2603
|
+
if (wantsHelp) {
|
|
2604
|
+
showDeploymentsHelp(subcommand);
|
|
2605
|
+
process.exit(0);
|
|
2606
|
+
}
|
|
2607
|
+
await handleDeploymentsCommand(subcommand ?? "list", positional, options);
|
|
2608
|
+
break;
|
|
2609
|
+
case "databases":
|
|
2610
|
+
case "db":
|
|
2611
|
+
if (wantsHelp) {
|
|
2612
|
+
showDatabasesHelp(subcommand);
|
|
2613
|
+
process.exit(0);
|
|
2614
|
+
}
|
|
2615
|
+
await handleDatabasesCommand(subcommand ?? "list", positional, options);
|
|
2616
|
+
break;
|
|
2617
|
+
case "database-users":
|
|
2618
|
+
if (wantsHelp) {
|
|
2619
|
+
showDatabaseUsersHelp(subcommand);
|
|
2620
|
+
process.exit(0);
|
|
2621
|
+
}
|
|
2622
|
+
await handleDatabaseUsersCommand(subcommand ?? "list", positional, options);
|
|
2623
|
+
break;
|
|
2624
|
+
case "daemons":
|
|
2625
|
+
if (wantsHelp) {
|
|
2626
|
+
showDaemonsHelp(subcommand);
|
|
2627
|
+
process.exit(0);
|
|
2628
|
+
}
|
|
2629
|
+
await handleDaemonsCommand(subcommand ?? "list", positional, options);
|
|
2630
|
+
break;
|
|
2631
|
+
case "env":
|
|
2632
|
+
if (wantsHelp) {
|
|
2633
|
+
showEnvHelp(subcommand);
|
|
2634
|
+
process.exit(0);
|
|
2635
|
+
}
|
|
2636
|
+
await handleEnvCommand(subcommand ?? "get", positional, options);
|
|
2637
|
+
break;
|
|
2638
|
+
case "nginx":
|
|
2639
|
+
if (wantsHelp) {
|
|
2640
|
+
showNginxHelp(subcommand);
|
|
2641
|
+
process.exit(0);
|
|
2642
|
+
}
|
|
2643
|
+
await handleNginxCommand(subcommand ?? "get", positional, options);
|
|
2644
|
+
break;
|
|
2645
|
+
case "certificates":
|
|
2646
|
+
case "certs":
|
|
2647
|
+
if (wantsHelp) {
|
|
2648
|
+
showCertificatesHelp(subcommand);
|
|
2649
|
+
process.exit(0);
|
|
2650
|
+
}
|
|
2651
|
+
await handleCertificatesCommand(subcommand ?? "list", positional, options);
|
|
2652
|
+
break;
|
|
2653
|
+
case "firewall-rules":
|
|
2654
|
+
case "fw":
|
|
2655
|
+
if (wantsHelp) {
|
|
2656
|
+
showFirewallRulesHelp(subcommand);
|
|
2657
|
+
process.exit(0);
|
|
2658
|
+
}
|
|
2659
|
+
await handleFirewallRulesCommand(subcommand ?? "list", positional, options);
|
|
2660
|
+
break;
|
|
2661
|
+
case "ssh-keys":
|
|
2662
|
+
if (wantsHelp) {
|
|
2663
|
+
showSshKeysHelp(subcommand);
|
|
2664
|
+
process.exit(0);
|
|
2665
|
+
}
|
|
2666
|
+
await handleSshKeysCommand(subcommand ?? "list", positional, options);
|
|
2667
|
+
break;
|
|
2668
|
+
case "backups":
|
|
2669
|
+
if (wantsHelp) {
|
|
2670
|
+
showBackupsHelp(subcommand);
|
|
2671
|
+
process.exit(0);
|
|
2672
|
+
}
|
|
2673
|
+
await handleBackupsCommand(subcommand ?? "list", positional, options);
|
|
2674
|
+
break;
|
|
2675
|
+
case "commands":
|
|
2676
|
+
if (wantsHelp) {
|
|
2677
|
+
showCommandsHelp(subcommand);
|
|
2678
|
+
process.exit(0);
|
|
2679
|
+
}
|
|
2680
|
+
await handleCommandsCommand(subcommand ?? "list", positional, options);
|
|
2681
|
+
break;
|
|
2682
|
+
case "scheduled-jobs":
|
|
2683
|
+
if (wantsHelp) {
|
|
2684
|
+
showScheduledJobsHelp(subcommand);
|
|
2685
|
+
process.exit(0);
|
|
2686
|
+
}
|
|
2687
|
+
await handleScheduledJobsCommand(subcommand ?? "list", positional, options);
|
|
2688
|
+
break;
|
|
2689
|
+
case "user":
|
|
2690
|
+
if (wantsHelp) {
|
|
2691
|
+
showUserHelp(subcommand);
|
|
2692
|
+
process.exit(0);
|
|
2693
|
+
}
|
|
2694
|
+
await handleUserCommand(subcommand ?? "get", positional, options);
|
|
2695
|
+
break;
|
|
2696
|
+
case "monitors":
|
|
2697
|
+
if (wantsHelp) {
|
|
2698
|
+
showMonitorsHelp(subcommand);
|
|
2699
|
+
process.exit(0);
|
|
2700
|
+
}
|
|
2701
|
+
await handleMonitorsCommand(subcommand ?? "list", positional, options);
|
|
2702
|
+
break;
|
|
2703
|
+
case "nginx-templates":
|
|
2704
|
+
if (wantsHelp) {
|
|
2705
|
+
showNginxTemplatesHelp(subcommand);
|
|
2706
|
+
process.exit(0);
|
|
2707
|
+
}
|
|
2708
|
+
await handleNginxTemplatesCommand(subcommand ?? "list", positional, options);
|
|
2709
|
+
break;
|
|
2710
|
+
case "security-rules":
|
|
2711
|
+
if (wantsHelp) {
|
|
2712
|
+
showSecurityRulesHelp(subcommand);
|
|
2713
|
+
process.exit(0);
|
|
2714
|
+
}
|
|
2715
|
+
await handleSecurityRulesCommand(subcommand ?? "list", positional, options);
|
|
2716
|
+
break;
|
|
2717
|
+
case "redirect-rules":
|
|
2718
|
+
if (wantsHelp) {
|
|
2719
|
+
showRedirectRulesHelp(subcommand);
|
|
2720
|
+
process.exit(0);
|
|
2721
|
+
}
|
|
2722
|
+
await handleRedirectRulesCommand(subcommand ?? "list", positional, options);
|
|
2723
|
+
break;
|
|
2724
|
+
case "recipes":
|
|
2725
|
+
if (wantsHelp) {
|
|
2726
|
+
showRecipesHelp(subcommand);
|
|
2727
|
+
process.exit(0);
|
|
2728
|
+
}
|
|
2729
|
+
await handleRecipesCommand(subcommand ?? "list", positional, options);
|
|
2730
|
+
break;
|
|
2731
|
+
default:
|
|
2732
|
+
console.error(colors.red(`Unknown command: ${mainCommand}`));
|
|
2733
|
+
console.log(`Run ${colors.cyan("forge-cli --help")} for usage information`);
|
|
2734
|
+
process.exit(1);
|
|
2735
|
+
}
|
|
2736
|
+
} catch (error) {
|
|
2737
|
+
console.error(colors.red("Fatal error:"), error);
|
|
2738
|
+
process.exit(1);
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
main().catch((error) => {
|
|
2742
|
+
console.error(colors.red("Unhandled error:"), error);
|
|
2743
|
+
process.exit(1);
|
|
2744
|
+
});
|
|
2745
|
+
|
|
2746
|
+
//# sourceMappingURL=cli.js.map
|