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,43 @@
1
+ import type { ServerRecord, ServerMode } from "../types/index.js";
2
+ export declare function isSafeMode(): boolean;
3
+ export declare function isValidProvider(provider: string): boolean;
4
+ export declare function validateIpAddress(ip: string): string | null;
5
+ export declare function validateServerName(name: string): string | null;
6
+ export interface AddServerParams {
7
+ provider: string;
8
+ ip: string;
9
+ name: string;
10
+ skipVerify?: boolean;
11
+ apiToken?: string;
12
+ mode?: ServerMode;
13
+ }
14
+ export interface AddServerResult {
15
+ success: boolean;
16
+ server?: ServerRecord;
17
+ coolifyStatus?: string;
18
+ error?: string;
19
+ }
20
+ export declare function addServerRecord(params: AddServerParams): Promise<AddServerResult>;
21
+ export interface RemoveServerResult {
22
+ success: boolean;
23
+ server?: ServerRecord;
24
+ error?: string;
25
+ }
26
+ export declare function removeServerRecord(query: string): RemoveServerResult;
27
+ export interface DestroyServerResult {
28
+ success: boolean;
29
+ server?: ServerRecord;
30
+ cloudDeleted: boolean;
31
+ localRemoved: boolean;
32
+ error?: string;
33
+ hint?: string;
34
+ }
35
+ export declare function destroyCloudServer(query: string): Promise<DestroyServerResult>;
36
+ export interface RebootServerResult {
37
+ success: boolean;
38
+ server?: ServerRecord;
39
+ error?: string;
40
+ hint?: string;
41
+ }
42
+ export declare function rebootServer(query: string): Promise<RebootServerResult>;
43
+ //# sourceMappingURL=manage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../src/core/manage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIlE,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAMD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa3D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS9D;AAID,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAuGvF;AAID,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAYpE;AAID,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiEpF;AAID,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoC7E"}
@@ -0,0 +1,241 @@
1
+ import { getServers, saveServer, removeServer, findServer } from "../utils/config.js";
2
+ import { createProviderWithToken } from "../utils/providerFactory.js";
3
+ import { sshExec, checkSshAvailable } from "../utils/ssh.js";
4
+ import { getErrorMessage, mapProviderError } from "../utils/errorMapper.js";
5
+ import { getProviderToken } from "./tokens.js";
6
+ // ─── SAFE_MODE ────────────────────────────────────────────────────────────────
7
+ export function isSafeMode() {
8
+ return process.env.QUICKLIFY_SAFE_MODE === "true";
9
+ }
10
+ // ─── Validation ───────────────────────────────────────────────────────────────
11
+ const VALID_PROVIDERS = ["hetzner", "digitalocean", "vultr", "linode"];
12
+ export function isValidProvider(provider) {
13
+ return VALID_PROVIDERS.includes(provider);
14
+ }
15
+ export function validateIpAddress(ip) {
16
+ if (!ip)
17
+ return "IP address is required";
18
+ if (!/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(ip)) {
19
+ return "Invalid IP address format";
20
+ }
21
+ const octets = ip.split(".").map(Number);
22
+ if (octets.some((o) => o < 0 || o > 255)) {
23
+ return "Invalid IP address (octets must be 0-255)";
24
+ }
25
+ if (ip === "0.0.0.0" || ip.startsWith("127.")) {
26
+ return "Reserved IP address not allowed";
27
+ }
28
+ return null;
29
+ }
30
+ export function validateServerName(name) {
31
+ if (!name)
32
+ return "Server name is required";
33
+ if (name.length < 3 || name.length > 63) {
34
+ return "Server name must be 3-63 characters";
35
+ }
36
+ if (!/^[a-z][a-z0-9-]*[a-z0-9]$/.test(name)) {
37
+ return "Must start with a letter, end with letter/number, only lowercase letters, numbers, hyphens";
38
+ }
39
+ return null;
40
+ }
41
+ export async function addServerRecord(params) {
42
+ // Validate provider
43
+ if (!isValidProvider(params.provider)) {
44
+ return {
45
+ success: false,
46
+ error: `Invalid provider: ${params.provider}. Valid: ${VALID_PROVIDERS.join(", ")}`,
47
+ };
48
+ }
49
+ // Get token from explicit param or env
50
+ const token = params.apiToken ?? getProviderToken(params.provider);
51
+ if (!token) {
52
+ return {
53
+ success: false,
54
+ error: `No API token found for provider: ${params.provider}. Set ${params.provider.toUpperCase()}_TOKEN environment variable`,
55
+ };
56
+ }
57
+ // Validate IP
58
+ const ipError = validateIpAddress(params.ip);
59
+ if (ipError) {
60
+ return { success: false, error: ipError };
61
+ }
62
+ // Check duplicate
63
+ const existing = getServers();
64
+ const duplicate = existing.find((s) => s.ip === params.ip);
65
+ if (duplicate) {
66
+ return {
67
+ success: false,
68
+ error: `Server with IP ${params.ip} already exists: ${duplicate.name}`,
69
+ };
70
+ }
71
+ // Validate name
72
+ const nameError = validateServerName(params.name);
73
+ if (nameError) {
74
+ return { success: false, error: nameError };
75
+ }
76
+ // Validate API token
77
+ try {
78
+ const provider = createProviderWithToken(params.provider, token);
79
+ const valid = await provider.validateToken(token);
80
+ if (!valid) {
81
+ return { success: false, error: `Invalid API token for ${params.provider}` };
82
+ }
83
+ }
84
+ catch (error) {
85
+ return {
86
+ success: false,
87
+ error: `Token validation failed: ${getErrorMessage(error)}`,
88
+ };
89
+ }
90
+ // Resolve mode
91
+ const mode = params.mode || "coolify";
92
+ // Optional Coolify verification via SSH (skip entirely for bare mode)
93
+ let coolifyStatus = "skipped";
94
+ if (!params.skipVerify && mode !== "bare") {
95
+ if (!checkSshAvailable()) {
96
+ coolifyStatus = "ssh_unavailable";
97
+ }
98
+ else {
99
+ try {
100
+ const result = await sshExec(params.ip, "curl -s -o /dev/null -w '%{http_code}' http://localhost:8000/api/health");
101
+ if (result.code === 0 && result.stdout.trim().includes("200")) {
102
+ coolifyStatus = "running";
103
+ }
104
+ else {
105
+ const dockerResult = await sshExec(params.ip, "docker ps --format '{{.Names}}' 2>/dev/null | grep -q coolify && echo OK");
106
+ if (dockerResult.code === 0 && dockerResult.stdout.trim().includes("OK")) {
107
+ coolifyStatus = "containers_detected";
108
+ }
109
+ else {
110
+ coolifyStatus = "not_detected";
111
+ }
112
+ }
113
+ }
114
+ catch (error) {
115
+ process.stderr.write(`[warn] Coolify verification failed: ${getErrorMessage(error)}\n`);
116
+ coolifyStatus = "verification_failed";
117
+ }
118
+ }
119
+ }
120
+ // Save to config
121
+ const record = {
122
+ id: `manual-${Date.now()}`,
123
+ name: params.name,
124
+ provider: params.provider,
125
+ ip: params.ip,
126
+ region: "unknown",
127
+ size: "unknown",
128
+ createdAt: new Date().toISOString(),
129
+ mode,
130
+ };
131
+ saveServer(record);
132
+ return { success: true, server: record, coolifyStatus };
133
+ }
134
+ export function removeServerRecord(query) {
135
+ const server = findServer(query);
136
+ if (!server) {
137
+ return { success: false, error: `Server not found: ${query}` };
138
+ }
139
+ const removed = removeServer(server.id);
140
+ if (!removed) {
141
+ return { success: false, error: `Failed to remove server: ${server.name}` };
142
+ }
143
+ return { success: true, server };
144
+ }
145
+ export async function destroyCloudServer(query) {
146
+ const server = findServer(query);
147
+ if (!server) {
148
+ return {
149
+ success: false,
150
+ cloudDeleted: false,
151
+ localRemoved: false,
152
+ error: `Server not found: ${query}`,
153
+ };
154
+ }
155
+ // Manual servers can only be removed, not destroyed
156
+ if (server.id.startsWith("manual-")) {
157
+ return {
158
+ success: false,
159
+ server,
160
+ cloudDeleted: false,
161
+ localRemoved: false,
162
+ error: `Server "${server.name}" was manually added (no cloud provider ID). Use 'remove' action instead.`,
163
+ };
164
+ }
165
+ // Get token from env
166
+ const token = getProviderToken(server.provider);
167
+ if (!token) {
168
+ return {
169
+ success: false,
170
+ server,
171
+ cloudDeleted: false,
172
+ localRemoved: false,
173
+ error: `No API token for ${server.provider}. Set ${server.provider.toUpperCase()}_TOKEN environment variable`,
174
+ };
175
+ }
176
+ try {
177
+ const provider = createProviderWithToken(server.provider, token);
178
+ await provider.destroyServer(server.id);
179
+ removeServer(server.id);
180
+ return { success: true, server, cloudDeleted: true, localRemoved: true };
181
+ }
182
+ catch (error) {
183
+ const message = getErrorMessage(error);
184
+ const isNotFound = message.toLowerCase().includes("not found") || message.toLowerCase().includes("not_found");
185
+ if (isNotFound) {
186
+ removeServer(server.id);
187
+ return {
188
+ success: true,
189
+ server,
190
+ cloudDeleted: false,
191
+ localRemoved: true,
192
+ hint: `Server not found on ${server.provider} (may have been deleted manually). Removed from local config.`,
193
+ };
194
+ }
195
+ const hint = mapProviderError(error, server.provider);
196
+ return {
197
+ success: false,
198
+ server,
199
+ cloudDeleted: false,
200
+ localRemoved: false,
201
+ error: message,
202
+ ...(hint ? { hint } : {}),
203
+ };
204
+ }
205
+ }
206
+ export async function rebootServer(query) {
207
+ const server = findServer(query);
208
+ if (!server) {
209
+ return { success: false, error: `Server not found: ${query}` };
210
+ }
211
+ if (server.id.startsWith("manual-")) {
212
+ return {
213
+ success: false,
214
+ server,
215
+ error: `Server "${server.name}" was manually added. Reboot is only available for cloud-provisioned servers.`,
216
+ };
217
+ }
218
+ const token = getProviderToken(server.provider);
219
+ if (!token) {
220
+ return {
221
+ success: false,
222
+ server,
223
+ error: `No API token for ${server.provider}. Set ${server.provider.toUpperCase()}_TOKEN environment variable`,
224
+ };
225
+ }
226
+ try {
227
+ const provider = createProviderWithToken(server.provider, token);
228
+ await provider.rebootServer(server.id);
229
+ return { success: true, server };
230
+ }
231
+ catch (error) {
232
+ const hint = mapProviderError(error, server.provider);
233
+ return {
234
+ success: false,
235
+ server,
236
+ error: getErrorMessage(error),
237
+ ...(hint ? { hint } : {}),
238
+ };
239
+ }
240
+ }
241
+ //# sourceMappingURL=manage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.js","sourceRoot":"","sources":["../../src/core/manage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { CloudProvider } from "../providers/base.js";
2
+ import type { ServerRecord, ServerMode } from "../types/index.js";
3
+ export interface ProvisionConfig {
4
+ provider: string;
5
+ region?: string;
6
+ size?: string;
7
+ name: string;
8
+ template?: string;
9
+ mode?: ServerMode;
10
+ }
11
+ export interface ProvisionResult {
12
+ success: boolean;
13
+ server?: ServerRecord;
14
+ error?: string;
15
+ hint?: string;
16
+ }
17
+ export declare function uploadSshKeyBestEffort(provider: CloudProvider): Promise<string[]>;
18
+ export declare function provisionServer(config: ProvisionConfig): Promise<ProvisionResult>;
19
+ //# sourceMappingURL=provision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../../src/core/provision.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAKlE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAYD,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBvF;AAID,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA8JvF"}
@@ -0,0 +1,192 @@
1
+ import { isValidProvider, validateServerName } from "./manage.js";
2
+ import { getProviderToken } from "./tokens.js";
3
+ import { createProviderWithToken } from "../utils/providerFactory.js";
4
+ import { getCoolifyCloudInit, getBareCloudInit } from "../utils/cloudInit.js";
5
+ import { findLocalSshKey, generateSshKey, getSshKeyName } from "../utils/sshKey.js";
6
+ import { saveServer } from "../utils/config.js";
7
+ import { getTemplateDefaults } from "../utils/templates.js";
8
+ import { getErrorMessage, mapProviderError } from "../utils/errorMapper.js";
9
+ import { assertValidIp } from "../utils/ssh.js";
10
+ import { IP_WAIT, BOOT_MAX_ATTEMPTS, BOOT_INTERVAL } from "../constants.js";
11
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
12
+ function sleep(ms) {
13
+ return new Promise((resolve) => setTimeout(resolve, ms));
14
+ }
15
+ function isPendingIp(ip) {
16
+ return !ip || ip === "pending" || ip === "0.0.0.0";
17
+ }
18
+ export async function uploadSshKeyBestEffort(provider) {
19
+ let publicKey = findLocalSshKey();
20
+ if (!publicKey) {
21
+ process.stderr.write("[provision] No local SSH key found. Generating one...\n");
22
+ publicKey = generateSshKey();
23
+ if (!publicKey) {
24
+ process.stderr.write("[provision] SSH key generation failed. Continuing without SSH key.\n");
25
+ return [];
26
+ }
27
+ process.stderr.write("[provision] SSH key generated (~/.ssh/id_ed25519)\n");
28
+ }
29
+ try {
30
+ const keyId = await provider.uploadSshKey(getSshKeyName(), publicKey);
31
+ return [keyId];
32
+ }
33
+ catch (error) {
34
+ process.stderr.write(`[provision] SSH key upload failed: ${getErrorMessage(error)}. Continuing without SSH key.\n`);
35
+ return [];
36
+ }
37
+ }
38
+ // ─── Main ────────────────────────────────────────────────────────────────────
39
+ export async function provisionServer(config) {
40
+ // 1. Validate provider
41
+ if (!isValidProvider(config.provider)) {
42
+ return {
43
+ success: false,
44
+ error: `Invalid provider: ${config.provider}. Valid: hetzner, digitalocean, vultr, linode`,
45
+ };
46
+ }
47
+ // 2. Validate name
48
+ const nameError = validateServerName(config.name);
49
+ if (nameError) {
50
+ return { success: false, error: nameError };
51
+ }
52
+ // 3. Resolve region/size — explicit params override template defaults
53
+ const template = config.template || "starter";
54
+ const defaults = getTemplateDefaults(template, config.provider);
55
+ const region = config.region || defaults?.region;
56
+ const size = config.size || defaults?.size;
57
+ if (!region || !size) {
58
+ return {
59
+ success: false,
60
+ error: `Could not resolve region/size for provider "${config.provider}" with template "${template}"`,
61
+ hint: "Provide explicit region and size parameters, or use a valid template",
62
+ };
63
+ }
64
+ // 4. Resolve token
65
+ const token = getProviderToken(config.provider);
66
+ if (!token) {
67
+ return {
68
+ success: false,
69
+ error: `No API token found for ${config.provider}`,
70
+ hint: `Set ${config.provider.toUpperCase()}_TOKEN environment variable`,
71
+ };
72
+ }
73
+ // 5. Create provider instance
74
+ const provider = createProviderWithToken(config.provider, token);
75
+ // 6. Validate token
76
+ try {
77
+ const valid = await provider.validateToken(token);
78
+ if (!valid) {
79
+ return { success: false, error: `Invalid API token for ${config.provider}` };
80
+ }
81
+ }
82
+ catch (error) {
83
+ return {
84
+ success: false,
85
+ error: `Token validation failed: ${getErrorMessage(error)}`,
86
+ };
87
+ }
88
+ // 7. Upload SSH key (best-effort)
89
+ const sshKeyIds = await uploadSshKeyBestEffort(provider);
90
+ // 8. Generate cloud-init
91
+ const mode = config.mode || "coolify";
92
+ const cloudInit = mode === "bare"
93
+ ? getBareCloudInit(config.name)
94
+ : getCoolifyCloudInit(config.name);
95
+ // 9. Create server
96
+ let serverId;
97
+ let serverIp;
98
+ try {
99
+ const result = await provider.createServer({
100
+ name: config.name,
101
+ region,
102
+ size,
103
+ cloudInit,
104
+ sshKeyIds,
105
+ });
106
+ serverId = result.id;
107
+ serverIp = result.ip;
108
+ }
109
+ catch (error) {
110
+ const message = getErrorMessage(error);
111
+ const hint = mapProviderError(error, config.provider);
112
+ return {
113
+ success: false,
114
+ error: `Server creation failed: ${message}`,
115
+ ...(hint ? { hint } : {}),
116
+ };
117
+ }
118
+ // 10. Wait for running status
119
+ for (let i = 0; i < BOOT_MAX_ATTEMPTS; i++) {
120
+ try {
121
+ const status = await provider.getServerStatus(serverId);
122
+ if (status === "running")
123
+ break;
124
+ }
125
+ catch {
126
+ // Ignore polling errors, retry
127
+ }
128
+ if (i === BOOT_MAX_ATTEMPTS - 1) {
129
+ return {
130
+ success: false,
131
+ error: `Server did not reach running state within ${BOOT_MAX_ATTEMPTS}s`,
132
+ hint: "The server may still be booting. Check status manually.",
133
+ };
134
+ }
135
+ await sleep(BOOT_INTERVAL);
136
+ }
137
+ // 11. Wait for IP assignment (provider-specific timing)
138
+ if (isPendingIp(serverIp)) {
139
+ const ipConfig = IP_WAIT[config.provider] || { attempts: 20, interval: 3000 };
140
+ for (let i = 0; i < ipConfig.attempts; i++) {
141
+ await sleep(ipConfig.interval);
142
+ try {
143
+ const details = await provider.getServerDetails(serverId);
144
+ if (!isPendingIp(details.ip)) {
145
+ try {
146
+ assertValidIp(details.ip);
147
+ serverIp = details.ip;
148
+ break;
149
+ }
150
+ catch {
151
+ // Invalid IP format, keep polling
152
+ }
153
+ }
154
+ }
155
+ catch {
156
+ // Ignore polling errors, retry
157
+ }
158
+ }
159
+ }
160
+ else {
161
+ // Validate the IP we already have
162
+ try {
163
+ assertValidIp(serverIp);
164
+ }
165
+ catch {
166
+ process.stderr.write(`[provision] IP validation failed for ${serverIp}, marking as pending\n`);
167
+ serverIp = "pending";
168
+ }
169
+ }
170
+ // 12. Save to config
171
+ const record = {
172
+ id: serverId,
173
+ name: config.name,
174
+ provider: config.provider,
175
+ ip: serverIp,
176
+ region,
177
+ size,
178
+ createdAt: new Date().toISOString(),
179
+ mode,
180
+ };
181
+ saveServer(record);
182
+ // 13. Return result
183
+ if (isPendingIp(serverIp)) {
184
+ return {
185
+ success: true,
186
+ server: record,
187
+ hint: `IP address not yet assigned. Check status with: server_info { action: 'status', server: '${config.name}' }`,
188
+ };
189
+ }
190
+ return { success: true, server: record };
191
+ }
192
+ //# sourceMappingURL=provision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/core/provision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAoB5E,gFAAgF;AAEhF,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,WAAW,CAAC,EAAU;IAC7B,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAuB;IAClE,IAAI,SAAS,GAAG,eAAe,EAAE,CAAC;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAChF,SAAS,GAAG,cAAc,EAAE,CAAC;QAC7B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;YAC7F,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,aAAa,EAAE,EAAE,SAAS,CAAC,CAAC;QACtE,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sCAAsC,eAAe,CAAC,KAAK,CAAC,iCAAiC,CAC9F,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAuB;IAC3D,uBAAuB;IACvB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,qBAAqB,MAAM,CAAC,QAAQ,+CAA+C;SAC3F,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9C,CAAC;IAED,sEAAsE;IACtE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC9C,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,QAAQ,EAAE,MAAM,CAAC;IACjD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,QAAQ,EAAE,IAAI,CAAC;IAE3C,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,+CAA+C,MAAM,CAAC,QAAQ,oBAAoB,QAAQ,GAAG;YACpG,IAAI,EAAE,sEAAsE;SAC7E,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,0BAA0B,MAAM,CAAC,QAAQ,EAAE;YAClD,IAAI,EAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,6BAA6B;SACxE,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,uBAAuB,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEjE,oBAAoB;IACpB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,4BAA4B,eAAe,CAAC,KAAK,CAAC,EAAE;SAC5D,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAEzD,yBAAyB;IACzB,MAAM,IAAI,GAAe,MAAM,CAAC,IAAI,IAAI,SAAS,CAAC;IAClD,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM;QAC/B,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAErC,mBAAmB;IACnB,IAAI,QAAgB,CAAC;IACrB,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC;YACzC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM;YACN,IAAI;YACJ,SAAS;YACT,SAAS;SACV,CAAC,CAAC;QACH,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;QACrB,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,2BAA2B,OAAO,EAAE;YAC3C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1B,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACxD,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;QACD,IAAI,CAAC,KAAK,iBAAiB,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,6CAA6C,iBAAiB,GAAG;gBACxE,IAAI,EAAE,yDAAyD;aAChE,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC;IAED,wDAAwD;IACxD,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC9E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC1D,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7B,IAAI,CAAC;wBACH,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;wBAC1B,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC;wBACtB,MAAM;oBACR,CAAC;oBAAC,MAAM,CAAC;wBACP,kCAAkC;oBACpC,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,kCAAkC;QAClC,IAAI,CAAC;YACH,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,QAAQ,wBAAwB,CAAC,CAAC;YAC/F,QAAQ,GAAG,SAAS,CAAC;QACvB,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,MAAM,GAAiB;QAC3B,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,EAAE,EAAE,QAAQ;QACZ,MAAM;QACN,IAAI;QACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI;KACL,CAAC;IACF,UAAU,CAAC,MAAM,CAAC,CAAC;IAEnB,oBAAoB;IACpB,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,4FAA4F,MAAM,CAAC,IAAI,KAAK;SACnH,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { SshdSetting, SecureAuditResult } from "../types/index.js";
2
+ export declare function parseSshdConfig(content: string): SshdSetting[];
3
+ export declare function parseAuditResult(stdout: string): SecureAuditResult;
4
+ export declare function buildHardeningCommand(options?: {
5
+ port?: number;
6
+ }): string;
7
+ export declare function buildFail2banCommand(): string;
8
+ export declare function buildAuditCommand(): string;
9
+ export declare function buildKeyCheckCommand(): string;
10
+ export interface SecureSetupResult {
11
+ success: boolean;
12
+ sshHardening: boolean;
13
+ fail2ban: boolean;
14
+ sshKeyCount: number;
15
+ error?: string;
16
+ hint?: string;
17
+ }
18
+ export interface SecureAuditFullResult {
19
+ audit: SecureAuditResult;
20
+ score: number;
21
+ error?: string;
22
+ hint?: string;
23
+ }
24
+ export declare function applySecureSetup(ip: string, options?: {
25
+ port?: number;
26
+ }): Promise<SecureSetupResult>;
27
+ export declare function calculateSecurityScore(audit: SecureAuditResult): number;
28
+ export declare function runSecureAudit(ip: string): Promise<SecureAuditFullResult>;
29
+ //# sourceMappingURL=secure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure.d.ts","sourceRoot":"","sources":["../../src/core/secure.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAIxE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CA8B9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CA8BlE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAqBzE;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAkB7C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAID,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAwD5B;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAOvE;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAmC/E"}