@ebowwa/hetzner 0.1.0 → 0.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.
package/ssh-keys.js CHANGED
@@ -1,90 +1,180 @@
1
+ "use strict";
1
2
  /**
2
3
  * Hetzner SSH key operations
3
4
  */
4
- import { HetznerListSSHKeysResponseSchema, HetznerGetSSHKeyResponseSchema, HetznerCreateSSHKeyRequestSchema, HetznerCreateSSHKeyResponseSchema, } from "./schemas.js";
5
- export class SSHKeyOperations {
6
- client;
7
- constructor(client) {
5
+ var __assign = (this && this.__assign) || function () {
6
+ __assign = Object.assign || function(t) {
7
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
8
+ s = arguments[i];
9
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
10
+ t[p] = s[p];
11
+ }
12
+ return t;
13
+ };
14
+ return __assign.apply(this, arguments);
15
+ };
16
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
+ return new (P || (P = Promise))(function (resolve, reject) {
19
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
23
+ });
24
+ };
25
+ var __generator = (this && this.__generator) || function (thisArg, body) {
26
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
27
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
28
+ function verb(n) { return function (v) { return step([n, v]); }; }
29
+ function step(op) {
30
+ if (f) throw new TypeError("Generator is already executing.");
31
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
32
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
33
+ if (y = 0, t) op = [op[0] & 2, t.value];
34
+ switch (op[0]) {
35
+ case 0: case 1: t = op; break;
36
+ case 4: _.label++; return { value: op[1], done: false };
37
+ case 5: _.label++; y = op[1]; op = [0]; continue;
38
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
39
+ default:
40
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
41
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
42
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
43
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
44
+ if (t[2]) _.ops.pop();
45
+ _.trys.pop(); continue;
46
+ }
47
+ op = body.call(thisArg, _);
48
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
49
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
+ }
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.SSHKeyOperations = void 0;
54
+ var schemas_js_1 = require("./schemas.js");
55
+ var SSHKeyOperations = /** @class */ (function () {
56
+ function SSHKeyOperations(client) {
8
57
  this.client = client;
9
58
  }
10
59
  /**
11
60
  * List all SSH keys
12
61
  */
13
- async list() {
14
- const response = await this.client.request("/ssh_keys");
15
- // Validate response with Zod
16
- const validated = HetznerListSSHKeysResponseSchema.safeParse(response);
17
- if (!validated.success) {
18
- console.warn('Hetzner list SSH keys validation warning:', validated.error.issues);
19
- return response.ssh_keys; // Return unvalidated data for backward compatibility
20
- }
21
- return validated.data.ssh_keys;
22
- }
62
+ SSHKeyOperations.prototype.list = function () {
63
+ return __awaiter(this, void 0, void 0, function () {
64
+ var response, validated;
65
+ return __generator(this, function (_a) {
66
+ switch (_a.label) {
67
+ case 0: return [4 /*yield*/, this.client.request("/ssh_keys")];
68
+ case 1:
69
+ response = _a.sent();
70
+ validated = schemas_js_1.HetznerListSSHKeysResponseSchema.safeParse(response);
71
+ if (!validated.success) {
72
+ console.warn('Hetzner list SSH keys validation warning:', validated.error.issues);
73
+ return [2 /*return*/, response.ssh_keys]; // Return unvalidated data for backward compatibility
74
+ }
75
+ return [2 /*return*/, validated.data.ssh_keys];
76
+ }
77
+ });
78
+ });
79
+ };
23
80
  /**
24
81
  * Get a specific SSH key by ID or name
25
82
  */
26
- async get(idOrName) {
27
- const endpoint = typeof idOrName === 'number'
28
- ? `/ssh_keys/${idOrName}`
29
- : `/ssh_keys?name=${encodeURIComponent(idOrName)}`;
30
- const response = await this.client.request(endpoint);
31
- // Validate response with Zod
32
- const validated = HetznerGetSSHKeyResponseSchema.safeParse(response);
33
- if (!validated.success) {
34
- console.warn('Hetzner get SSH key validation warning:', validated.error.issues);
35
- return response.ssh_key; // Return unvalidated data for backward compatibility
36
- }
37
- return validated.data.ssh_key;
38
- }
83
+ SSHKeyOperations.prototype.get = function (idOrName) {
84
+ return __awaiter(this, void 0, void 0, function () {
85
+ var endpoint, response, validated;
86
+ return __generator(this, function (_a) {
87
+ switch (_a.label) {
88
+ case 0:
89
+ endpoint = typeof idOrName === 'number'
90
+ ? "/ssh_keys/".concat(idOrName)
91
+ : "/ssh_keys?name=".concat(encodeURIComponent(idOrName));
92
+ return [4 /*yield*/, this.client.request(endpoint)];
93
+ case 1:
94
+ response = _a.sent();
95
+ validated = schemas_js_1.HetznerGetSSHKeyResponseSchema.safeParse(response);
96
+ if (!validated.success) {
97
+ console.warn('Hetzner get SSH key validation warning:', validated.error.issues);
98
+ return [2 /*return*/, response.ssh_key]; // Return unvalidated data for backward compatibility
99
+ }
100
+ return [2 /*return*/, validated.data.ssh_key];
101
+ }
102
+ });
103
+ });
104
+ };
39
105
  /**
40
106
  * Create a new SSH key
41
107
  *
42
108
  * @param options - SSH key creation options
43
109
  * @returns Created SSH key
44
110
  */
45
- async create(options) {
46
- // Validate input with Zod
47
- const validatedOptions = HetznerCreateSSHKeyRequestSchema.safeParse(options);
48
- if (!validatedOptions.success) {
49
- throw new Error(`Invalid SSH key options: ${validatedOptions.error.issues.map(i => i.message).join(', ')}`);
50
- }
51
- const body = {
52
- name: validatedOptions.data.name,
53
- public_key: validatedOptions.data.public_key,
54
- ...(validatedOptions.data.labels && { labels: validatedOptions.data.labels }),
55
- };
56
- const response = await this.client.request("/ssh_keys", {
57
- method: "POST",
58
- body: JSON.stringify(body),
111
+ SSHKeyOperations.prototype.create = function (options) {
112
+ return __awaiter(this, void 0, void 0, function () {
113
+ var validatedOptions, body, response, validated;
114
+ return __generator(this, function (_a) {
115
+ switch (_a.label) {
116
+ case 0:
117
+ validatedOptions = schemas_js_1.HetznerCreateSSHKeyRequestSchema.safeParse(options);
118
+ if (!validatedOptions.success) {
119
+ throw new Error("Invalid SSH key options: ".concat(validatedOptions.error.issues.map(function (i) { return i.message; }).join(', ')));
120
+ }
121
+ body = __assign({ name: validatedOptions.data.name, public_key: validatedOptions.data.public_key }, (validatedOptions.data.labels && { labels: validatedOptions.data.labels }));
122
+ return [4 /*yield*/, this.client.request("/ssh_keys", {
123
+ method: "POST",
124
+ body: JSON.stringify(body),
125
+ })];
126
+ case 1:
127
+ response = _a.sent();
128
+ validated = schemas_js_1.HetznerCreateSSHKeyResponseSchema.safeParse(response);
129
+ if (!validated.success) {
130
+ console.warn('Hetzner create SSH key validation warning:', validated.error.issues);
131
+ return [2 /*return*/, response.ssh_key]; // Return unvalidated data for backward compatibility
132
+ }
133
+ return [2 /*return*/, validated.data.ssh_key];
134
+ }
135
+ });
59
136
  });
60
- // Validate response with Zod
61
- const validated = HetznerCreateSSHKeyResponseSchema.safeParse(response);
62
- if (!validated.success) {
63
- console.warn('Hetzner create SSH key validation warning:', validated.error.issues);
64
- return response.ssh_key; // Return unvalidated data for backward compatibility
65
- }
66
- return validated.data.ssh_key;
67
- }
137
+ };
68
138
  /**
69
139
  * Delete an SSH key
70
140
  *
71
141
  * @param id - SSH key ID
72
142
  */
73
- async delete(id) {
74
- await this.client.request(`/ssh_keys/${id}`, { method: "DELETE" });
75
- }
143
+ SSHKeyOperations.prototype.delete = function (id) {
144
+ return __awaiter(this, void 0, void 0, function () {
145
+ return __generator(this, function (_a) {
146
+ switch (_a.label) {
147
+ case 0: return [4 /*yield*/, this.client.request("/ssh_keys/".concat(id), { method: "DELETE" })];
148
+ case 1:
149
+ _a.sent();
150
+ return [2 /*return*/];
151
+ }
152
+ });
153
+ });
154
+ };
76
155
  /**
77
156
  * Find an SSH key by name
78
157
  * Returns undefined if not found
79
158
  */
80
- async findByName(name) {
81
- try {
82
- const keys = await this.list();
83
- return keys.find(key => key.name === name);
84
- }
85
- catch {
86
- return undefined;
87
- }
88
- }
89
- }
90
- //# sourceMappingURL=ssh-keys.js.map
159
+ SSHKeyOperations.prototype.findByName = function (name) {
160
+ return __awaiter(this, void 0, void 0, function () {
161
+ var keys, _a;
162
+ return __generator(this, function (_b) {
163
+ switch (_b.label) {
164
+ case 0:
165
+ _b.trys.push([0, 2, , 3]);
166
+ return [4 /*yield*/, this.list()];
167
+ case 1:
168
+ keys = _b.sent();
169
+ return [2 /*return*/, keys.find(function (key) { return key.name === name; })];
170
+ case 2:
171
+ _a = _b.sent();
172
+ return [2 /*return*/, undefined];
173
+ case 3: return [2 /*return*/];
174
+ }
175
+ });
176
+ });
177
+ };
178
+ return SSHKeyOperations;
179
+ }());
180
+ exports.SSHKeyOperations = SSHKeyOperations;
package/ssh-setup.js ADDED
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ /**
3
+ * SSH Key Management for Hetzner
4
+ *
5
+ * This module ensures SSH keys are properly configured between:
6
+ * 1. Local machine (~/.ssh/)
7
+ * 2. Hetzner Cloud API
8
+ *
9
+ * PROBLEM:
10
+ * - Creating random keys in Hetzner doesn't work because we need the matching private key locally
11
+ * - Password auth is unreliable and often disabled
12
+ * - IP reuse causes known_hosts conflicts
13
+ *
14
+ * SOLUTION:
15
+ * - Always use existing local keys or create new key pairs
16
+ * - Upload public key to Hetzner, keep private key local
17
+ */
18
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
19
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
20
+ return new (P || (P = Promise))(function (resolve, reject) {
21
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
23
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
24
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
25
+ });
26
+ };
27
+ var __generator = (this && this.__generator) || function (thisArg, body) {
28
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
29
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
30
+ function verb(n) { return function (v) { return step([n, v]); }; }
31
+ function step(op) {
32
+ if (f) throw new TypeError("Generator is already executing.");
33
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
34
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
35
+ if (y = 0, t) op = [op[0] & 2, t.value];
36
+ switch (op[0]) {
37
+ case 0: case 1: t = op; break;
38
+ case 4: _.label++; return { value: op[1], done: false };
39
+ case 5: _.label++; y = op[1]; op = [0]; continue;
40
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
41
+ default:
42
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
43
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
44
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
45
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
46
+ if (t[2]) _.ops.pop();
47
+ _.trys.pop(); continue;
48
+ }
49
+ op = body.call(thisArg, _);
50
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
51
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
52
+ }
53
+ };
54
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
56
+ if (ar || !(i in from)) {
57
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
58
+ ar[i] = from[i];
59
+ }
60
+ }
61
+ return to.concat(ar || Array.prototype.slice.call(from));
62
+ };
63
+ Object.defineProperty(exports, "__esModule", { value: true });
64
+ exports.getOrCreateHetznerSSHKey = getOrCreateHetznerSSHKey;
65
+ exports.ensureHetznerSSHKey = ensureHetznerSSHKey;
66
+ exports.clearKnownHosts = clearKnownHosts;
67
+ exports.testSSHConnection = testSSHConnection;
68
+ exports.prepareSSHKeys = prepareSSHKeys;
69
+ var fs_1 = require("fs");
70
+ var path_1 = require("path");
71
+ var ssh_1 = require("@ebowwa/ssh");
72
+ var HETZNER_SSH_DIR = (0, path_1.join)(process.env.HOME || "", ".ssh");
73
+ var HETZNER_KEY_PREFIX = "hetzner-codespaces";
74
+ /**
75
+ * Get or create a local SSH key pair for Hetzner
76
+ * Returns the key name to use with Hetzner API
77
+ */
78
+ function getOrCreateHetznerSSHKey() {
79
+ return __awaiter(this, void 0, void 0, function () {
80
+ var existingKey;
81
+ return __generator(this, function (_a) {
82
+ existingKey = findExistingHetznerKey();
83
+ if (existingKey) {
84
+ console.log("\u2713 Using existing SSH key: ".concat(existingKey.name));
85
+ return [2 /*return*/, existingKey];
86
+ }
87
+ // Create new key pair
88
+ console.log("Creating new SSH key pair for Hetzner...");
89
+ return [2 /*return*/, createNewKeyPair()];
90
+ });
91
+ });
92
+ }
93
+ /**
94
+ * Find existing Hetzner SSH key in local ~/.ssh/
95
+ */
96
+ function findExistingHetznerKey() {
97
+ var privateKeyPath = (0, path_1.join)(HETZNER_SSH_DIR, "".concat(HETZNER_KEY_PREFIX));
98
+ var publicKeyPath = "".concat(privateKeyPath, ".pub");
99
+ if (!(0, fs_1.existsSync)(privateKeyPath) || !(0, fs_1.existsSync)(publicKeyPath)) {
100
+ return null;
101
+ }
102
+ var publicKey = (0, fs_1.readFileSync)(publicKeyPath, "utf-8").trim();
103
+ return {
104
+ name: HETZNER_KEY_PREFIX,
105
+ publicKey: publicKey,
106
+ privateKeyPath: privateKeyPath,
107
+ };
108
+ }
109
+ /**
110
+ * Create a new SSH key pair for Hetzner
111
+ */
112
+ function createNewKeyPair() {
113
+ var keyName = "".concat(HETZNER_KEY_PREFIX, "-").concat(Date.now());
114
+ var privateKeyPath = (0, path_1.join)(HETZNER_SSH_DIR, keyName);
115
+ var publicKeyPath = "".concat(privateKeyPath, ".pub");
116
+ // Generate new ed25519 key pair
117
+ try {
118
+ // Bun.spawn automatically escapes arguments to prevent shell injection
119
+ Bun.spawnSync(["ssh-keygen", "-t", "ed25519", "-f", privateKeyPath, "-N", "", "-C", keyName], {
120
+ stdout: "ignore",
121
+ stderr: "ignore",
122
+ });
123
+ // Set proper permissions
124
+ Bun.spawnSync(["chmod", "600", privateKeyPath], { stdout: "ignore", stderr: "ignore" });
125
+ Bun.spawnSync(["chmod", "644", publicKeyPath], { stdout: "ignore", stderr: "ignore" });
126
+ var publicKey = (0, fs_1.readFileSync)(publicKeyPath, "utf-8").trim();
127
+ console.log("\u2713 Created new SSH key: ".concat(keyName));
128
+ console.log(" Private: ".concat(privateKeyPath));
129
+ console.log(" Public: ".concat(publicKeyPath));
130
+ return {
131
+ name: keyName,
132
+ publicKey: publicKey,
133
+ privateKeyPath: privateKeyPath,
134
+ };
135
+ }
136
+ catch (error) {
137
+ throw new Error("Failed to create SSH key: ".concat(error));
138
+ }
139
+ }
140
+ /**
141
+ * Ensure SSH key exists in Hetzner
142
+ * Returns the SSH key name to use when creating servers
143
+ */
144
+ function ensureHetznerSSHKey(hetznerAPI) {
145
+ return __awaiter(this, void 0, void 0, function () {
146
+ var localKey, existingKeys, matchingKey, createResponse, error, createdKey;
147
+ return __generator(this, function (_a) {
148
+ switch (_a.label) {
149
+ case 0: return [4 /*yield*/, getOrCreateHetznerSSHKey()];
150
+ case 1:
151
+ localKey = _a.sent();
152
+ return [4 /*yield*/, hetznerAPI("/ssh_keys", "GET", null)
153
+ .then(function (r) { return r.json(); })
154
+ .then(function (data) { return data.ssh_keys; })];
155
+ case 2:
156
+ existingKeys = _a.sent();
157
+ matchingKey = existingKeys.find(function (k) { return k.public_key.trim() === localKey.publicKey.trim(); });
158
+ if (matchingKey) {
159
+ console.log("\u2713 SSH key already exists in Hetzner: ".concat(matchingKey.name, " (").concat(matchingKey.id, ")"));
160
+ return [2 /*return*/, matchingKey.name]; // Use existing key name
161
+ }
162
+ // 4. Upload new key to Hetzner
163
+ console.log("Uploading SSH key to Hetzner: ".concat(localKey.name, "..."));
164
+ return [4 /*yield*/, hetznerAPI("/ssh_keys", "POST", {
165
+ name: localKey.name,
166
+ public_key: localKey.publicKey,
167
+ })];
168
+ case 3:
169
+ createResponse = _a.sent();
170
+ if (!!createResponse.ok) return [3 /*break*/, 5];
171
+ return [4 /*yield*/, createResponse.text()];
172
+ case 4:
173
+ error = _a.sent();
174
+ throw new Error("Failed to upload SSH key to Hetzner: ".concat(error));
175
+ case 5: return [4 /*yield*/, createResponse.json()];
176
+ case 6:
177
+ createdKey = (_a.sent());
178
+ console.log("\u2713 SSH key uploaded: ".concat(createdKey.name, " (").concat(createdKey.id, ")"));
179
+ return [2 /*return*/, createdKey.name];
180
+ }
181
+ });
182
+ });
183
+ }
184
+ /**
185
+ * Clear known_hosts entry for an IP (to fix IP reuse issues)
186
+ */
187
+ function clearKnownHosts(ip) {
188
+ try {
189
+ // Bun.spawn automatically escapes arguments to prevent shell injection
190
+ Bun.spawnSync(["ssh-keygen", "-R", ip], { stdout: "ignore", stderr: "ignore" });
191
+ console.log("\u2713 Cleared known_hosts entry for ".concat(ip));
192
+ }
193
+ catch (_a) {
194
+ // Ignore if entry doesn't exist
195
+ }
196
+ }
197
+ /**
198
+ * Test SSH connection to a server using typed flags
199
+ */
200
+ function testSSHConnection(ip_1, privateKeyPath_1) {
201
+ return __awaiter(this, arguments, void 0, function (ip, privateKeyPath, username) {
202
+ var flags, sshArgs, proc_1, timeout, _a;
203
+ if (username === void 0) { username = "root"; }
204
+ return __generator(this, function (_b) {
205
+ switch (_b.label) {
206
+ case 0:
207
+ _b.trys.push([0, 2, , 3]);
208
+ flags = __spreadArray(__spreadArray([], ssh_1.SSHPresets.default, true), [
209
+ ssh_1.SSHFlags.identity(privateKeyPath),
210
+ (0, ssh_1.sshConfig)("ConnectTimeout", "10"),
211
+ ], false);
212
+ sshArgs = (0, ssh_1.buildSSHArgs)(flags, ip, username);
213
+ sshArgs.push("echo", "connected");
214
+ proc_1 = Bun.spawn(sshArgs, {
215
+ stdout: "ignore",
216
+ stderr: "ignore",
217
+ });
218
+ timeout = setTimeout(function () { return proc_1.kill(); }, 15000);
219
+ return [4 /*yield*/, proc_1.exited];
220
+ case 1:
221
+ _b.sent();
222
+ clearTimeout(timeout);
223
+ return [2 /*return*/, proc_1.exitCode === 0];
224
+ case 2:
225
+ _a = _b.sent();
226
+ return [2 /*return*/, false];
227
+ case 3: return [2 /*return*/];
228
+ }
229
+ });
230
+ });
231
+ }
232
+ /**
233
+ * Full workflow: Prepare SSH keys before creating servers
234
+ */
235
+ function prepareSSHKeys(hetznerAPI) {
236
+ return __awaiter(this, void 0, void 0, function () {
237
+ var sshKeyName, localKey;
238
+ return __generator(this, function (_a) {
239
+ switch (_a.label) {
240
+ case 0: return [4 /*yield*/, ensureHetznerSSHKey(hetznerAPI)];
241
+ case 1:
242
+ sshKeyName = _a.sent();
243
+ return [4 /*yield*/, getOrCreateHetznerSSHKey()];
244
+ case 2:
245
+ localKey = _a.sent();
246
+ return [2 /*return*/, {
247
+ sshKeyName: sshKeyName,
248
+ privateKeyPath: localKey.privateKeyPath,
249
+ }];
250
+ }
251
+ });
252
+ });
253
+ }
package/ssh-setup.ts CHANGED
@@ -18,7 +18,7 @@
18
18
  import { existsSync, readFileSync, writeFileSync } from "fs";
19
19
  import { join } from "path";
20
20
  import crypto from "crypto";
21
- import { SSHPresets, SSHFlags, buildSSHArgs, sshConfig } from "@codespaces/ssh";
21
+ import { SSHPresets, SSHFlags, buildSSHArgs, sshConfig } from "@ebowwa/ssh";
22
22
 
23
23
  interface SSHKey {
24
24
  id: number;
package/types.js CHANGED
@@ -1,19 +1,23 @@
1
+ "use strict";
1
2
  /**
2
3
  * Hetzner Cloud API types
3
4
  */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ResourceType = exports.ActionCommand = exports.VolumeStatus = exports.ActionStatus = exports.EnvironmentStatus = void 0;
4
7
  // ============================================================================
5
8
  // Import shared status enums
6
9
  // ============================================================================
7
- import { EnvironmentStatus, ActionStatus, VolumeStatus, } from "@ebowwa/codespaces-types/compile";
8
- // Re-export for convenience
9
- export { EnvironmentStatus, ActionStatus, VolumeStatus };
10
+ var compile_1 = require("@ebowwa/codespaces-types/compile");
11
+ Object.defineProperty(exports, "EnvironmentStatus", { enumerable: true, get: function () { return compile_1.EnvironmentStatus; } });
12
+ Object.defineProperty(exports, "ActionStatus", { enumerable: true, get: function () { return compile_1.ActionStatus; } });
13
+ Object.defineProperty(exports, "VolumeStatus", { enumerable: true, get: function () { return compile_1.VolumeStatus; } });
10
14
  // ============================================================================
11
15
  // Action Types
12
16
  // ============================================================================
13
17
  /**
14
18
  * Action command types from Hetzner Cloud API
15
19
  */
16
- export var ActionCommand;
20
+ var ActionCommand;
17
21
  (function (ActionCommand) {
18
22
  // Server actions
19
23
  ActionCommand["CreateServer"] = "create_server";
@@ -78,11 +82,11 @@ export var ActionCommand;
78
82
  ActionCommand["FirewallChangeProtection"] = "firewall_change_protection";
79
83
  // Image actions
80
84
  ActionCommand["ImageChangeProtection"] = "image_change_protection";
81
- })(ActionCommand || (ActionCommand = {}));
85
+ })(ActionCommand || (exports.ActionCommand = ActionCommand = {}));
82
86
  /**
83
87
  * Resource types that can be affected by actions
84
88
  */
85
- export var ResourceType;
89
+ var ResourceType;
86
90
  (function (ResourceType) {
87
91
  ResourceType["Server"] = "server";
88
92
  ResourceType["Volume"] = "volume";
@@ -92,5 +96,4 @@ export var ResourceType;
92
96
  ResourceType["Certificate"] = "certificate";
93
97
  ResourceType["Firewall"] = "firewall";
94
98
  ResourceType["Image"] = "image";
95
- })(ResourceType || (ResourceType = {}));
96
- //# sourceMappingURL=types.js.map
99
+ })(ResourceType || (exports.ResourceType = ResourceType = {}));