quicklify 1.0.5 → 1.2.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.
Files changed (214) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +86 -25
  3. package/README.tr.md +86 -25
  4. package/SECURITY.md +79 -17
  5. package/bin/quicklify-mcp +5 -0
  6. package/dist/commands/add.d.ts +1 -0
  7. package/dist/commands/add.d.ts.map +1 -1
  8. package/dist/commands/add.js +41 -65
  9. package/dist/commands/add.js.map +1 -1
  10. package/dist/commands/backup.d.ts +2 -11
  11. package/dist/commands/backup.d.ts.map +1 -1
  12. package/dist/commands/backup.js +113 -57
  13. package/dist/commands/backup.js.map +1 -1
  14. package/dist/commands/destroy.d.ts.map +1 -1
  15. package/dist/commands/destroy.js +58 -37
  16. package/dist/commands/destroy.js.map +1 -1
  17. package/dist/commands/domain.d.ts +2 -9
  18. package/dist/commands/domain.d.ts.map +1 -1
  19. package/dist/commands/domain.js +47 -56
  20. package/dist/commands/domain.js.map +1 -1
  21. package/dist/commands/firewall.d.ts +3 -10
  22. package/dist/commands/firewall.d.ts.map +1 -1
  23. package/dist/commands/firewall.js +28 -51
  24. package/dist/commands/firewall.js.map +1 -1
  25. package/dist/commands/health.d.ts +2 -2
  26. package/dist/commands/health.d.ts.map +1 -1
  27. package/dist/commands/health.js +77 -19
  28. package/dist/commands/health.js.map +1 -1
  29. package/dist/commands/init.d.ts.map +1 -1
  30. package/dist/commands/init.js +142 -24
  31. package/dist/commands/init.js.map +1 -1
  32. package/dist/commands/interactive.d.ts +2 -0
  33. package/dist/commands/interactive.d.ts.map +1 -0
  34. package/dist/commands/interactive.js +357 -0
  35. package/dist/commands/interactive.js.map +1 -0
  36. package/dist/commands/list.d.ts.map +1 -1
  37. package/dist/commands/list.js +4 -2
  38. package/dist/commands/list.js.map +1 -1
  39. package/dist/commands/logs.d.ts +3 -2
  40. package/dist/commands/logs.d.ts.map +1 -1
  41. package/dist/commands/logs.js +15 -12
  42. package/dist/commands/logs.js.map +1 -1
  43. package/dist/commands/maintain.d.ts.map +1 -1
  44. package/dist/commands/maintain.js +28 -47
  45. package/dist/commands/maintain.js.map +1 -1
  46. package/dist/commands/monitor.d.ts +3 -9
  47. package/dist/commands/monitor.d.ts.map +1 -1
  48. package/dist/commands/monitor.js +3 -48
  49. package/dist/commands/monitor.js.map +1 -1
  50. package/dist/commands/remove.d.ts.map +1 -1
  51. package/dist/commands/remove.js +25 -0
  52. package/dist/commands/remove.js.map +1 -1
  53. package/dist/commands/restart.d.ts.map +1 -1
  54. package/dist/commands/restart.js +39 -39
  55. package/dist/commands/restart.js.map +1 -1
  56. package/dist/commands/restore.d.ts +2 -13
  57. package/dist/commands/restore.d.ts.map +1 -1
  58. package/dist/commands/restore.js +42 -54
  59. package/dist/commands/restore.js.map +1 -1
  60. package/dist/commands/secure.d.ts +2 -9
  61. package/dist/commands/secure.d.ts.map +1 -1
  62. package/dist/commands/secure.js +2 -97
  63. package/dist/commands/secure.js.map +1 -1
  64. package/dist/commands/snapshot.d.ts.map +1 -1
  65. package/dist/commands/snapshot.js +55 -67
  66. package/dist/commands/snapshot.js.map +1 -1
  67. package/dist/commands/ssh.d.ts.map +1 -1
  68. package/dist/commands/ssh.js +4 -1
  69. package/dist/commands/ssh.js.map +1 -1
  70. package/dist/commands/status.d.ts.map +1 -1
  71. package/dist/commands/status.js +53 -85
  72. package/dist/commands/status.js.map +1 -1
  73. package/dist/commands/update.d.ts.map +1 -1
  74. package/dist/commands/update.js +23 -16
  75. package/dist/commands/update.js.map +1 -1
  76. package/dist/constants.d.ts +14 -0
  77. package/dist/constants.d.ts.map +1 -0
  78. package/dist/constants.js +23 -0
  79. package/dist/constants.js.map +1 -0
  80. package/dist/core/backup.d.ts +59 -0
  81. package/dist/core/backup.d.ts.map +1 -0
  82. package/dist/core/backup.js +417 -0
  83. package/dist/core/backup.js.map +1 -0
  84. package/dist/core/domain.d.ts +30 -0
  85. package/dist/core/domain.d.ts.map +1 -0
  86. package/dist/core/domain.js +170 -0
  87. package/dist/core/domain.js.map +1 -0
  88. package/dist/core/firewall.d.ts +27 -0
  89. package/dist/core/firewall.d.ts.map +1 -0
  90. package/dist/core/firewall.js +158 -0
  91. package/dist/core/firewall.js.map +1 -0
  92. package/dist/core/logs.d.ts +28 -0
  93. package/dist/core/logs.d.ts.map +1 -0
  94. package/dist/core/logs.js +129 -0
  95. package/dist/core/logs.js.map +1 -0
  96. package/dist/core/maintain.d.ts +41 -0
  97. package/dist/core/maintain.d.ts.map +1 -0
  98. package/dist/core/maintain.js +179 -0
  99. package/dist/core/maintain.js.map +1 -0
  100. package/dist/core/manage.d.ts +43 -0
  101. package/dist/core/manage.d.ts.map +1 -0
  102. package/dist/core/manage.js +241 -0
  103. package/dist/core/manage.js.map +1 -0
  104. package/dist/core/provision.d.ts +19 -0
  105. package/dist/core/provision.d.ts.map +1 -0
  106. package/dist/core/provision.js +192 -0
  107. package/dist/core/provision.js.map +1 -0
  108. package/dist/core/secure.d.ts +29 -0
  109. package/dist/core/secure.d.ts.map +1 -0
  110. package/dist/core/secure.js +204 -0
  111. package/dist/core/secure.js.map +1 -0
  112. package/dist/core/snapshot.d.ts +22 -0
  113. package/dist/core/snapshot.d.ts.map +1 -0
  114. package/dist/core/snapshot.js +58 -0
  115. package/dist/core/snapshot.js.map +1 -0
  116. package/dist/core/status.d.ts +12 -0
  117. package/dist/core/status.d.ts.map +1 -0
  118. package/dist/core/status.js +44 -0
  119. package/dist/core/status.js.map +1 -0
  120. package/dist/core/tokens.d.ts +4 -0
  121. package/dist/core/tokens.d.ts.map +1 -0
  122. package/dist/core/tokens.js +23 -0
  123. package/dist/core/tokens.js.map +1 -0
  124. package/dist/index.js +17 -4
  125. package/dist/index.js.map +1 -1
  126. package/dist/mcp/index.d.ts +3 -0
  127. package/dist/mcp/index.d.ts.map +1 -0
  128. package/dist/mcp/index.js +16 -0
  129. package/dist/mcp/index.js.map +1 -0
  130. package/dist/mcp/server.d.ts +3 -0
  131. package/dist/mcp/server.d.ts.map +1 -0
  132. package/dist/mcp/server.js +111 -0
  133. package/dist/mcp/server.js.map +1 -0
  134. package/dist/mcp/tools/serverBackup.d.ts +24 -0
  135. package/dist/mcp/tools/serverBackup.d.ts.map +1 -0
  136. package/dist/mcp/tools/serverBackup.js +262 -0
  137. package/dist/mcp/tools/serverBackup.js.map +1 -0
  138. package/dist/mcp/tools/serverInfo.d.ts +36 -0
  139. package/dist/mcp/tools/serverInfo.d.ts.map +1 -0
  140. package/dist/mcp/tools/serverInfo.js +283 -0
  141. package/dist/mcp/tools/serverInfo.js.map +1 -0
  142. package/dist/mcp/tools/serverLogs.d.ts +25 -0
  143. package/dist/mcp/tools/serverLogs.d.ts.map +1 -0
  144. package/dist/mcp/tools/serverLogs.js +124 -0
  145. package/dist/mcp/tools/serverLogs.js.map +1 -0
  146. package/dist/mcp/tools/serverMaintain.d.ts +17 -0
  147. package/dist/mcp/tools/serverMaintain.d.ts.map +1 -0
  148. package/dist/mcp/tools/serverMaintain.js +156 -0
  149. package/dist/mcp/tools/serverMaintain.js.map +1 -0
  150. package/dist/mcp/tools/serverManage.d.ts +38 -0
  151. package/dist/mcp/tools/serverManage.d.ts.map +1 -0
  152. package/dist/mcp/tools/serverManage.js +190 -0
  153. package/dist/mcp/tools/serverManage.js.map +1 -0
  154. package/dist/mcp/tools/serverProvision.d.ts +36 -0
  155. package/dist/mcp/tools/serverProvision.d.ts.map +1 -0
  156. package/dist/mcp/tools/serverProvision.js +116 -0
  157. package/dist/mcp/tools/serverProvision.js.map +1 -0
  158. package/dist/mcp/tools/serverSecure.d.ts +35 -0
  159. package/dist/mcp/tools/serverSecure.d.ts.map +1 -0
  160. package/dist/mcp/tools/serverSecure.js +335 -0
  161. package/dist/mcp/tools/serverSecure.js.map +1 -0
  162. package/dist/mcp/utils.d.ts +42 -0
  163. package/dist/mcp/utils.d.ts.map +1 -0
  164. package/dist/mcp/utils.js +61 -0
  165. package/dist/mcp/utils.js.map +1 -0
  166. package/dist/providers/base.d.ts +2 -2
  167. package/dist/providers/base.d.ts.map +1 -1
  168. package/dist/providers/digitalocean.d.ts +2 -2
  169. package/dist/providers/digitalocean.d.ts.map +1 -1
  170. package/dist/providers/digitalocean.js +3 -3
  171. package/dist/providers/digitalocean.js.map +1 -1
  172. package/dist/providers/hetzner.d.ts +2 -2
  173. package/dist/providers/hetzner.d.ts.map +1 -1
  174. package/dist/providers/hetzner.js +7 -4
  175. package/dist/providers/hetzner.js.map +1 -1
  176. package/dist/providers/linode.d.ts +2 -2
  177. package/dist/providers/linode.d.ts.map +1 -1
  178. package/dist/providers/linode.js +2 -2
  179. package/dist/providers/linode.js.map +1 -1
  180. package/dist/providers/vultr.d.ts +2 -2
  181. package/dist/providers/vultr.d.ts.map +1 -1
  182. package/dist/providers/vultr.js +9 -3
  183. package/dist/providers/vultr.js.map +1 -1
  184. package/dist/types/index.d.ts +11 -1
  185. package/dist/types/index.d.ts.map +1 -1
  186. package/dist/utils/cloudInit.d.ts +1 -0
  187. package/dist/utils/cloudInit.d.ts.map +1 -1
  188. package/dist/utils/cloudInit.js +62 -0
  189. package/dist/utils/cloudInit.js.map +1 -1
  190. package/dist/utils/config.js +1 -1
  191. package/dist/utils/config.js.map +1 -1
  192. package/dist/utils/errorMapper.d.ts +1 -0
  193. package/dist/utils/errorMapper.d.ts.map +1 -1
  194. package/dist/utils/errorMapper.js +25 -1
  195. package/dist/utils/errorMapper.js.map +1 -1
  196. package/dist/utils/modeGuard.d.ts +5 -0
  197. package/dist/utils/modeGuard.d.ts.map +1 -0
  198. package/dist/utils/modeGuard.js +13 -0
  199. package/dist/utils/modeGuard.js.map +1 -0
  200. package/dist/utils/openBrowser.d.ts.map +1 -1
  201. package/dist/utils/openBrowser.js +9 -2
  202. package/dist/utils/openBrowser.js.map +1 -1
  203. package/dist/utils/prompts.d.ts +2 -2
  204. package/dist/utils/prompts.d.ts.map +1 -1
  205. package/dist/utils/prompts.js +3 -3
  206. package/dist/utils/prompts.js.map +1 -1
  207. package/dist/utils/ssh.d.ts +10 -0
  208. package/dist/utils/ssh.d.ts.map +1 -1
  209. package/dist/utils/ssh.js +181 -17
  210. package/dist/utils/ssh.js.map +1 -1
  211. package/dist/utils/sshKey.d.ts.map +1 -1
  212. package/dist/utils/sshKey.js +3 -0
  213. package/dist/utils/sshKey.js.map +1 -1
  214. package/package.json +7 -4
@@ -0,0 +1,27 @@
1
+ import type { FirewallStatus, FirewallProtocol } from "../types/index.js";
2
+ export declare const PROTECTED_PORTS: number[];
3
+ export declare const COOLIFY_PORTS: number[];
4
+ export declare const BARE_PORTS: number[];
5
+ export declare function isValidPort(port: number): boolean;
6
+ export declare function isProtectedPort(port: number): boolean;
7
+ export declare function buildFirewallSetupCommand(): string;
8
+ export declare function buildBareFirewallSetupCommand(): string;
9
+ export declare function buildUfwRuleCommand(action: "allow" | "delete allow", port: number, protocol?: FirewallProtocol): string;
10
+ export declare function buildUfwStatusCommand(): string;
11
+ export declare function parseUfwStatus(stdout: string): FirewallStatus;
12
+ export interface FirewallResult {
13
+ success: boolean;
14
+ error?: string;
15
+ hint?: string;
16
+ warning?: string;
17
+ }
18
+ export interface FirewallStatusResult {
19
+ status: FirewallStatus;
20
+ error?: string;
21
+ hint?: string;
22
+ }
23
+ export declare function setupFirewall(ip: string): Promise<FirewallResult>;
24
+ export declare function addFirewallRule(ip: string, port: number, protocol?: FirewallProtocol): Promise<FirewallResult>;
25
+ export declare function removeFirewallRule(ip: string, port: number, protocol?: FirewallProtocol): Promise<FirewallResult>;
26
+ export declare function getFirewallStatus(ip: string): Promise<FirewallStatusResult>;
27
+ //# sourceMappingURL=firewall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firewall.d.ts","sourceRoot":"","sources":["../../src/core/firewall.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAgB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAIxF,eAAO,MAAM,eAAe,UAAO,CAAC;AACpC,eAAO,MAAM,aAAa,UAA8B,CAAC;AACzD,eAAO,MAAM,UAAU,UAAY,CAAC;AAIpC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAUlD;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAUtD;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,OAAO,GAAG,cAAc,EAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAAwB,GACjC,MAAM,CAER;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAkB7D;AAID,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAoBvE;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAAwB,GACjC,OAAO,CAAC,cAAc,CAAC,CAwBzB;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAAwB,GACjC,OAAO,CAAC,cAAc,CAAC,CAkCzB;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAoBjF"}
@@ -0,0 +1,158 @@
1
+ import { sshExec, assertValidIp } from "../utils/ssh.js";
2
+ import { getErrorMessage, mapSshError } from "../utils/errorMapper.js";
3
+ // ─── Constants ──────────────────────────────────────────────────────────────
4
+ export const PROTECTED_PORTS = [22];
5
+ export const COOLIFY_PORTS = [80, 443, 8000, 6001, 6002];
6
+ export const BARE_PORTS = [80, 443];
7
+ // ─── Pure Functions ─────────────────────────────────────────────────────────
8
+ export function isValidPort(port) {
9
+ return Number.isInteger(port) && port >= 1 && port <= 65535;
10
+ }
11
+ export function isProtectedPort(port) {
12
+ return PROTECTED_PORTS.includes(port);
13
+ }
14
+ export function buildFirewallSetupCommand() {
15
+ const commands = [
16
+ "apt-get install -y ufw",
17
+ "ufw default deny incoming",
18
+ "ufw default allow outgoing",
19
+ ...COOLIFY_PORTS.map((p) => `ufw allow ${p}/tcp`),
20
+ "ufw allow 22/tcp",
21
+ 'echo "y" | ufw enable',
22
+ ];
23
+ return commands.join(" && ");
24
+ }
25
+ export function buildBareFirewallSetupCommand() {
26
+ const commands = [
27
+ "apt-get install -y ufw",
28
+ "ufw default deny incoming",
29
+ "ufw default allow outgoing",
30
+ ...BARE_PORTS.map((p) => `ufw allow ${p}/tcp`),
31
+ "ufw allow 22/tcp",
32
+ 'echo "y" | ufw enable',
33
+ ];
34
+ return commands.join(" && ");
35
+ }
36
+ export function buildUfwRuleCommand(action, port, protocol = "tcp") {
37
+ return `ufw ${action} ${port}/${protocol}`;
38
+ }
39
+ export function buildUfwStatusCommand() {
40
+ return "ufw status numbered";
41
+ }
42
+ export function parseUfwStatus(stdout) {
43
+ const lines = stdout.split("\n");
44
+ const active = stdout.toLowerCase().includes("status: active");
45
+ const rules = [];
46
+ for (const line of lines) {
47
+ const match = line.match(/\[\s*\d+\]\s+(\d+)\/(tcp|udp)\s+(ALLOW|DENY)\s+IN\s+(.*)/i);
48
+ if (match) {
49
+ rules.push({
50
+ port: parseInt(match[1], 10),
51
+ protocol: match[2].toLowerCase(),
52
+ action: match[3].toUpperCase(),
53
+ from: match[4].trim() || "Anywhere",
54
+ });
55
+ }
56
+ }
57
+ return { active, rules };
58
+ }
59
+ // ─── Async Wrappers ─────────────────────────────────────────────────────────
60
+ export async function setupFirewall(ip) {
61
+ assertValidIp(ip);
62
+ try {
63
+ const result = await sshExec(ip, buildFirewallSetupCommand());
64
+ if (result.code !== 0) {
65
+ return {
66
+ success: false,
67
+ error: `Firewall setup failed (exit code ${result.code})`,
68
+ };
69
+ }
70
+ return { success: true };
71
+ }
72
+ catch (error) {
73
+ const hint = mapSshError(error, ip);
74
+ return {
75
+ success: false,
76
+ error: getErrorMessage(error),
77
+ ...(hint ? { hint } : {}),
78
+ };
79
+ }
80
+ }
81
+ export async function addFirewallRule(ip, port, protocol = "tcp") {
82
+ assertValidIp(ip);
83
+ if (!isValidPort(port)) {
84
+ return { success: false, error: `Invalid port: ${port}. Must be 1-65535.` };
85
+ }
86
+ try {
87
+ const result = await sshExec(ip, buildUfwRuleCommand("allow", port, protocol));
88
+ if (result.code !== 0) {
89
+ return {
90
+ success: false,
91
+ error: `Failed to add rule for port ${port}/${protocol}`,
92
+ };
93
+ }
94
+ return { success: true };
95
+ }
96
+ catch (error) {
97
+ const hint = mapSshError(error, ip);
98
+ return {
99
+ success: false,
100
+ error: getErrorMessage(error),
101
+ ...(hint ? { hint } : {}),
102
+ };
103
+ }
104
+ }
105
+ export async function removeFirewallRule(ip, port, protocol = "tcp") {
106
+ assertValidIp(ip);
107
+ if (!isValidPort(port)) {
108
+ return { success: false, error: `Invalid port: ${port}. Must be 1-65535.` };
109
+ }
110
+ if (isProtectedPort(port)) {
111
+ return { success: false, error: `Port ${port} is protected (SSH access). Cannot remove.` };
112
+ }
113
+ const warning = COOLIFY_PORTS.includes(port)
114
+ ? `Port ${port} is used by Coolify. Removing it may break Coolify access.`
115
+ : undefined;
116
+ try {
117
+ const result = await sshExec(ip, buildUfwRuleCommand("delete allow", port, protocol));
118
+ if (result.code !== 0) {
119
+ return {
120
+ success: false,
121
+ error: `Failed to remove rule for port ${port}/${protocol}`,
122
+ ...(warning ? { warning } : {}),
123
+ };
124
+ }
125
+ return { success: true, ...(warning ? { warning } : {}) };
126
+ }
127
+ catch (error) {
128
+ const hint = mapSshError(error, ip);
129
+ return {
130
+ success: false,
131
+ error: getErrorMessage(error),
132
+ ...(hint ? { hint } : {}),
133
+ ...(warning ? { warning } : {}),
134
+ };
135
+ }
136
+ }
137
+ export async function getFirewallStatus(ip) {
138
+ assertValidIp(ip);
139
+ try {
140
+ const result = await sshExec(ip, buildUfwStatusCommand());
141
+ if (result.code !== 0) {
142
+ return {
143
+ status: { active: false, rules: [] },
144
+ error: `Failed to get firewall status (exit code ${result.code})`,
145
+ };
146
+ }
147
+ return { status: parseUfwStatus(result.stdout) };
148
+ }
149
+ catch (error) {
150
+ const hint = mapSshError(error, ip);
151
+ return {
152
+ status: { active: false, rules: [] },
153
+ error: getErrorMessage(error),
154
+ ...(hint ? { hint } : {}),
155
+ };
156
+ }
157
+ }
158
+ //# sourceMappingURL=firewall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firewall.js","sourceRoot":"","sources":["../../src/core/firewall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGvE,+EAA+E;AAE/E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAEpC,+EAA+E;AAE/E,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,MAAM,QAAQ,GAAG;QACf,wBAAwB;QACxB,2BAA2B;QAC3B,4BAA4B;QAC5B,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC;QACjD,kBAAkB;QAClB,uBAAuB;KACxB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,MAAM,QAAQ,GAAG;QACf,wBAAwB;QACxB,2BAA2B;QAC3B,4BAA4B;QAC5B,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC;QAC9C,kBAAkB;QAClB,uBAAuB;KACxB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAgC,EAChC,IAAY,EACZ,WAA6B,KAAK;IAElC,OAAO,OAAO,MAAM,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAmB,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QACtF,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC5B,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAsB;gBACpD,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAsB;gBAClD,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,UAAU;aACpC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAiBD,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAU;IAC5C,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,EAAE,yBAAyB,EAAE,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,oCAAoC,MAAM,CAAC,IAAI,GAAG;aAC1D,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;YAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1B,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAU,EACV,IAAY,EACZ,WAA6B,KAAK;IAElC,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,IAAI,oBAAoB,EAAE,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC/E,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,+BAA+B,IAAI,IAAI,QAAQ,EAAE;aACzD,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;YAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1B,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,EAAU,EACV,IAAY,EACZ,WAA6B,KAAK;IAElC,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,IAAI,oBAAoB,EAAE,CAAC;IAC9E,CAAC;IAED,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,IAAI,4CAA4C,EAAE,CAAC;IAC7F,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC1C,CAAC,CAAC,QAAQ,IAAI,4DAA4D;QAC1E,CAAC,CAAC,SAAS,CAAC;IAEd,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,kCAAkC,IAAI,IAAI,QAAQ,EAAE;gBAC3D,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;YAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAU;IAChD,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;gBACL,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;gBACpC,KAAK,EAAE,4CAA4C,MAAM,CAAC,IAAI,GAAG;aAClE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACnD,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;YACL,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;YACpC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;YAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1B,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ export type LogService = "coolify" | "docker" | "system";
2
+ export interface SystemMetrics {
3
+ cpu: string;
4
+ ramUsed: string;
5
+ ramTotal: string;
6
+ diskUsed: string;
7
+ diskTotal: string;
8
+ diskPercent: string;
9
+ }
10
+ export interface LogResult {
11
+ logs: string;
12
+ service: LogService;
13
+ lines: number;
14
+ error?: string;
15
+ hint?: string;
16
+ }
17
+ export interface MetricsResult {
18
+ metrics: SystemMetrics;
19
+ containers?: string;
20
+ error?: string;
21
+ hint?: string;
22
+ }
23
+ export declare function buildLogCommand(service: LogService, lines: number, follow?: boolean): string;
24
+ export declare function buildMonitorCommand(includeContainers: boolean): string;
25
+ export declare function parseMetrics(stdout: string): SystemMetrics;
26
+ export declare function fetchServerLogs(ip: string, service: LogService, lines: number): Promise<LogResult>;
27
+ export declare function fetchServerMetrics(ip: string, includeContainers: boolean): Promise<MetricsResult>;
28
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/core/logs.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAWD,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,MAAM,CASnG;AAED,wBAAgB,mBAAmB,CAAC,iBAAiB,EAAE,OAAO,GAAG,MAAM,CAQtE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CA4C1D;AAED,wBAAsB,eAAe,CACnC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,SAAS,CAAC,CA2BpB;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,EACV,iBAAiB,EAAE,OAAO,GACzB,OAAO,CAAC,aAAa,CAAC,CAiCxB"}
@@ -0,0 +1,129 @@
1
+ import { sshExec } from "../utils/ssh.js";
2
+ import { getErrorMessage, mapSshError, sanitizeStderr } from "../utils/errorMapper.js";
3
+ const EMPTY_METRICS = {
4
+ cpu: "N/A",
5
+ ramUsed: "N/A",
6
+ ramTotal: "N/A",
7
+ diskUsed: "N/A",
8
+ diskTotal: "N/A",
9
+ diskPercent: "N/A",
10
+ };
11
+ export function buildLogCommand(service, lines, follow = false) {
12
+ switch (service) {
13
+ case "coolify":
14
+ return `docker logs coolify --tail ${lines}${follow ? " --follow" : ""}`;
15
+ case "docker":
16
+ return `journalctl -u docker --no-pager -n ${lines}${follow ? " -f" : ""}`;
17
+ case "system":
18
+ return `journalctl --no-pager -n ${lines}${follow ? " -f" : ""}`;
19
+ }
20
+ }
21
+ export function buildMonitorCommand(includeContainers) {
22
+ let command = "top -bn1 | head -5 && echo '---SEPARATOR---' && free -h && echo '---SEPARATOR---' && df -h --total | grep -E '(Filesystem|total)'";
23
+ if (includeContainers) {
24
+ command +=
25
+ " && echo '---SEPARATOR---' && (docker ps --format 'table {{.Names}}\\t{{.Status}}\\t{{.Ports}}' 2>/dev/null || echo 'Docker not installed')";
26
+ }
27
+ return command;
28
+ }
29
+ export function parseMetrics(stdout) {
30
+ const lines = stdout.split("\n");
31
+ let cpu = "N/A";
32
+ for (const line of lines) {
33
+ if (line.includes("Cpu") || line.includes("cpu")) {
34
+ const idleMatch = line.match(/([\d.]+)\s*(?:%?\s*)?id/);
35
+ if (idleMatch) {
36
+ const idle = parseFloat(idleMatch[1]);
37
+ cpu = `${(100 - idle).toFixed(1)}%`;
38
+ }
39
+ break;
40
+ }
41
+ }
42
+ let ramUsed = "N/A";
43
+ let ramTotal = "N/A";
44
+ for (const line of lines) {
45
+ if (line.startsWith("Mem:")) {
46
+ const parts = line.split(/\s+/);
47
+ if (parts.length >= 3) {
48
+ ramTotal = parts[1];
49
+ ramUsed = parts[2];
50
+ }
51
+ break;
52
+ }
53
+ }
54
+ let diskUsed = "N/A";
55
+ let diskTotal = "N/A";
56
+ let diskPercent = "N/A";
57
+ for (const line of lines) {
58
+ if (line.startsWith("total") || line.includes("/dev/")) {
59
+ const parts = line.split(/\s+/);
60
+ if (parts.length >= 5) {
61
+ diskTotal = parts[1];
62
+ diskUsed = parts[2];
63
+ diskPercent = parts[4];
64
+ }
65
+ if (line.startsWith("total"))
66
+ break;
67
+ }
68
+ }
69
+ return { cpu, ramUsed, ramTotal, diskUsed, diskTotal, diskPercent };
70
+ }
71
+ export async function fetchServerLogs(ip, service, lines) {
72
+ try {
73
+ const command = buildLogCommand(service, lines, false);
74
+ const result = await sshExec(ip, command);
75
+ if (result.code !== 0) {
76
+ const hint = mapSshError(new Error(result.stderr || "SSH command failed"), ip);
77
+ return {
78
+ logs: result.stdout || "",
79
+ service,
80
+ lines,
81
+ error: sanitizeStderr(result.stderr) || `Exit code ${result.code}`,
82
+ ...(hint ? { hint } : {}),
83
+ };
84
+ }
85
+ return { logs: result.stdout, service, lines };
86
+ }
87
+ catch (error) {
88
+ const hint = mapSshError(error, ip);
89
+ return {
90
+ logs: "",
91
+ service,
92
+ lines,
93
+ error: getErrorMessage(error),
94
+ ...(hint ? { hint } : {}),
95
+ };
96
+ }
97
+ }
98
+ export async function fetchServerMetrics(ip, includeContainers) {
99
+ try {
100
+ const command = buildMonitorCommand(includeContainers);
101
+ const result = await sshExec(ip, command);
102
+ if (result.code !== 0) {
103
+ const hint = mapSshError(new Error(result.stderr || "SSH command failed"), ip);
104
+ return {
105
+ metrics: { ...EMPTY_METRICS },
106
+ error: sanitizeStderr(result.stderr) || `Exit code ${result.code}`,
107
+ ...(hint ? { hint } : {}),
108
+ };
109
+ }
110
+ const metrics = parseMetrics(result.stdout);
111
+ let containers;
112
+ if (includeContainers) {
113
+ const sections = result.stdout.split("---SEPARATOR---");
114
+ if (sections.length >= 4) {
115
+ containers = sections[3].trim();
116
+ }
117
+ }
118
+ return { metrics, ...(containers ? { containers } : {}) };
119
+ }
120
+ catch (error) {
121
+ const hint = mapSshError(error, ip);
122
+ return {
123
+ metrics: { ...EMPTY_METRICS },
124
+ error: getErrorMessage(error),
125
+ ...(hint ? { hint } : {}),
126
+ };
127
+ }
128
+ }
129
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/core/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { ServerRecord } from "../types/index.js";
2
+ export interface StepResult {
3
+ step: number;
4
+ name: string;
5
+ status: "success" | "failure" | "skipped";
6
+ detail?: string;
7
+ error?: string;
8
+ hint?: string;
9
+ }
10
+ export interface MaintainResult {
11
+ server: string;
12
+ ip: string;
13
+ provider: string;
14
+ steps: StepResult[];
15
+ success: boolean;
16
+ }
17
+ export interface UpdateResult {
18
+ success: boolean;
19
+ output?: string;
20
+ error?: string;
21
+ hint?: string;
22
+ }
23
+ export interface RestartResult {
24
+ success: boolean;
25
+ finalStatus?: string;
26
+ error?: string;
27
+ hint?: string;
28
+ }
29
+ export declare function executeCoolifyUpdate(ip: string): Promise<UpdateResult>;
30
+ export declare function pollCoolifyHealth(ip: string, maxAttempts: number, intervalMs: number): Promise<boolean>;
31
+ export declare function rebootAndWait(server: ServerRecord, apiToken: string, maxAttempts?: number, intervalMs?: number, initialWaitMs?: number): Promise<RestartResult>;
32
+ export interface MaintainOptions {
33
+ skipReboot?: boolean;
34
+ healthPollAttempts?: number;
35
+ healthPollIntervalMs?: number;
36
+ rebootMaxAttempts?: number;
37
+ rebootIntervalMs?: number;
38
+ rebootInitialWaitMs?: number;
39
+ }
40
+ export declare function maintainServer(server: ServerRecord, apiToken: string, options?: MaintainOptions): Promise<MaintainResult>;
41
+ //# sourceMappingURL=maintain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintain.d.ts","sourceRoot":"","sources":["../../src/core/maintain.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKtD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoB5E;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CASlB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,MAAW,EACxB,UAAU,GAAE,MAAa,EACzB,aAAa,GAAE,MAAc,GAC5B,OAAO,CAAC,aAAa,CAAC,CA0CxB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAqGzB"}
@@ -0,0 +1,179 @@
1
+ import { sshExec, assertValidIp } from "../utils/ssh.js";
2
+ import { createProviderWithToken } from "../utils/providerFactory.js";
3
+ import { checkCoolifyHealth, getCloudServerStatus } from "./status.js";
4
+ import { getErrorMessage, mapSshError, mapProviderError } from "../utils/errorMapper.js";
5
+ import { COOLIFY_UPDATE_CMD } from "../constants.js";
6
+ // ─── Core Functions ──────────────────────────────────────────────────────────
7
+ export async function executeCoolifyUpdate(ip) {
8
+ assertValidIp(ip);
9
+ try {
10
+ const result = await sshExec(ip, COOLIFY_UPDATE_CMD);
11
+ if (result.code === 0) {
12
+ return { success: true, output: result.stdout || undefined };
13
+ }
14
+ return {
15
+ success: false,
16
+ error: `Update failed (exit code ${result.code})`,
17
+ output: result.stderr || result.stdout || undefined,
18
+ };
19
+ }
20
+ catch (error) {
21
+ const hint = mapSshError(error, ip);
22
+ return {
23
+ success: false,
24
+ error: getErrorMessage(error),
25
+ ...(hint ? { hint } : {}),
26
+ };
27
+ }
28
+ }
29
+ export async function pollCoolifyHealth(ip, maxAttempts, intervalMs) {
30
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
31
+ const status = await checkCoolifyHealth(ip);
32
+ if (status === "running")
33
+ return true;
34
+ if (attempt < maxAttempts - 1) {
35
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
36
+ }
37
+ }
38
+ return false;
39
+ }
40
+ export async function rebootAndWait(server, apiToken, maxAttempts = 30, intervalMs = 2000, initialWaitMs = 10000) {
41
+ if (server.id.startsWith("manual-")) {
42
+ return {
43
+ success: false,
44
+ error: `Cannot reboot manually added server via API. Use SSH: ssh root@${server.ip} reboot`,
45
+ };
46
+ }
47
+ try {
48
+ const provider = createProviderWithToken(server.provider, apiToken);
49
+ await provider.rebootServer(server.id);
50
+ // Wait for reboot to initiate
51
+ await new Promise((resolve) => setTimeout(resolve, initialWaitMs));
52
+ // Poll until running
53
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
54
+ try {
55
+ const status = await provider.getServerStatus(server.id);
56
+ if (status === "running") {
57
+ return { success: true, finalStatus: "running" };
58
+ }
59
+ }
60
+ catch {
61
+ // Server may be temporarily unreachable during reboot
62
+ }
63
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
64
+ }
65
+ return {
66
+ success: false,
67
+ finalStatus: "timeout",
68
+ error: "Server did not come back online in time",
69
+ hint: "The server may still be rebooting. Check status later.",
70
+ };
71
+ }
72
+ catch (error) {
73
+ const hint = mapProviderError(error, server.provider);
74
+ return {
75
+ success: false,
76
+ error: getErrorMessage(error),
77
+ ...(hint ? { hint } : {}),
78
+ };
79
+ }
80
+ }
81
+ export async function maintainServer(server, apiToken, options = {}) {
82
+ const isManual = server.id.startsWith("manual-");
83
+ const healthAttempts = options.healthPollAttempts ?? 12;
84
+ const healthInterval = options.healthPollIntervalMs ?? 5000;
85
+ const rebootAttempts = options.rebootMaxAttempts ?? 30;
86
+ const rebootInterval = options.rebootIntervalMs ?? 2000;
87
+ const rebootInitialWait = options.rebootInitialWaitMs ?? 10000;
88
+ const steps = [];
89
+ const result = {
90
+ server: server.name,
91
+ ip: server.ip,
92
+ provider: server.provider,
93
+ steps,
94
+ success: false,
95
+ };
96
+ // Step 1: Status check
97
+ if (isManual) {
98
+ steps.push({ step: 1, name: "Status Check", status: "skipped", detail: "Manual server — assuming running" });
99
+ }
100
+ else {
101
+ try {
102
+ const serverStatus = await getCloudServerStatus(server, apiToken);
103
+ if (serverStatus !== "running") {
104
+ steps.push({ step: 1, name: "Status Check", status: "failure", detail: `Server is ${serverStatus}` });
105
+ steps.push({ step: 2, name: "Coolify Update", status: "skipped" });
106
+ steps.push({ step: 3, name: "Health Check", status: "skipped" });
107
+ steps.push({ step: 4, name: "Reboot", status: "skipped" });
108
+ steps.push({ step: 5, name: "Final Check", status: "skipped" });
109
+ return result;
110
+ }
111
+ steps.push({ step: 1, name: "Status Check", status: "success", detail: "Server is running" });
112
+ }
113
+ catch (error) {
114
+ const hint = mapProviderError(error, server.provider);
115
+ steps.push({
116
+ step: 1, name: "Status Check", status: "failure",
117
+ error: getErrorMessage(error), ...(hint ? { hint } : {}),
118
+ });
119
+ steps.push({ step: 2, name: "Coolify Update", status: "skipped" });
120
+ steps.push({ step: 3, name: "Health Check", status: "skipped" });
121
+ steps.push({ step: 4, name: "Reboot", status: "skipped" });
122
+ steps.push({ step: 5, name: "Final Check", status: "skipped" });
123
+ return result;
124
+ }
125
+ }
126
+ // Step 2: Coolify update
127
+ const updateResult = await executeCoolifyUpdate(server.ip);
128
+ if (!updateResult.success) {
129
+ steps.push({
130
+ step: 2, name: "Coolify Update", status: "failure",
131
+ error: updateResult.error, ...(updateResult.hint ? { hint: updateResult.hint } : {}),
132
+ });
133
+ steps.push({ step: 3, name: "Health Check", status: "skipped" });
134
+ steps.push({ step: 4, name: "Reboot", status: "skipped" });
135
+ steps.push({ step: 5, name: "Final Check", status: "skipped" });
136
+ return result;
137
+ }
138
+ steps.push({ step: 2, name: "Coolify Update", status: "success" });
139
+ // Step 3: Health check after update
140
+ const healthOk = await pollCoolifyHealth(server.ip, healthAttempts, healthInterval);
141
+ if (!healthOk) {
142
+ steps.push({ step: 3, name: "Health Check", status: "failure", detail: "Coolify did not respond after update" });
143
+ // Continue — partial success
144
+ }
145
+ else {
146
+ steps.push({ step: 3, name: "Health Check", status: "success", detail: "Coolify is healthy" });
147
+ }
148
+ // Steps 4 & 5: Reboot + Final check (skip both if skipReboot or manual)
149
+ if (options.skipReboot || isManual) {
150
+ const reason = isManual ? "Manual server — no API reboot" : "Skipped by user";
151
+ steps.push({ step: 4, name: "Reboot", status: "skipped", detail: reason });
152
+ steps.push({ step: 5, name: "Final Check", status: "skipped", detail: reason });
153
+ result.success = steps.every((s) => s.status !== "failure");
154
+ return result;
155
+ }
156
+ // Step 4: Reboot
157
+ const rebootResult = await rebootAndWait(server, apiToken, rebootAttempts, rebootInterval, rebootInitialWait);
158
+ if (!rebootResult.success) {
159
+ steps.push({
160
+ step: 4, name: "Reboot", status: "failure",
161
+ error: rebootResult.error, ...(rebootResult.hint ? { hint: rebootResult.hint } : {}),
162
+ });
163
+ steps.push({ step: 5, name: "Final Check", status: "skipped" });
164
+ result.success = false;
165
+ return result;
166
+ }
167
+ steps.push({ step: 4, name: "Reboot", status: "success", detail: "Server rebooted" });
168
+ // Step 5: Final health check after reboot
169
+ const finalHealthOk = await pollCoolifyHealth(server.ip, healthAttempts, healthInterval);
170
+ if (finalHealthOk) {
171
+ steps.push({ step: 5, name: "Final Check", status: "success", detail: "Server and Coolify are running" });
172
+ }
173
+ else {
174
+ steps.push({ step: 5, name: "Final Check", status: "failure", detail: "Server running but Coolify did not respond" });
175
+ }
176
+ result.success = steps.every((s) => s.status !== "failure");
177
+ return result;
178
+ }
179
+ //# sourceMappingURL=maintain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintain.js","sourceRoot":"","sources":["../../src/core/maintain.ts"],"names":[],"mappings":"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"}