@ebowwa/hetzner 0.2.2 → 0.3.1

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 (61) hide show
  1. package/dist/bootstrap/index.js +1126 -0
  2. package/dist/bootstrap/index.js.map +15 -0
  3. package/dist/index.js +3540 -0
  4. package/dist/index.js.map +31 -0
  5. package/dist/onboarding/index.js +460 -0
  6. package/dist/onboarding/index.js.map +14 -0
  7. package/package.json +53 -16
  8. package/actions.js +0 -1084
  9. package/actions.ts +0 -1053
  10. package/auth.js +0 -39
  11. package/auth.ts +0 -37
  12. package/bootstrap/FIREWALL.md +0 -326
  13. package/bootstrap/KERNEL-HARDENING.md +0 -258
  14. package/bootstrap/SECURITY-INTEGRATION.md +0 -281
  15. package/bootstrap/TESTING.md +0 -301
  16. package/bootstrap/cloud-init.js +0 -323
  17. package/bootstrap/cloud-init.ts +0 -394
  18. package/bootstrap/firewall.js +0 -292
  19. package/bootstrap/firewall.ts +0 -342
  20. package/bootstrap/genesis.js +0 -424
  21. package/bootstrap/genesis.ts +0 -518
  22. package/bootstrap/index.js +0 -59
  23. package/bootstrap/index.ts +0 -71
  24. package/bootstrap/kernel-hardening.js +0 -270
  25. package/bootstrap/kernel-hardening.test.js +0 -182
  26. package/bootstrap/kernel-hardening.test.ts +0 -230
  27. package/bootstrap/kernel-hardening.ts +0 -272
  28. package/bootstrap/security-audit.js +0 -122
  29. package/bootstrap/security-audit.ts +0 -124
  30. package/bootstrap/ssh-hardening.js +0 -186
  31. package/bootstrap/ssh-hardening.ts +0 -192
  32. package/client.js +0 -234
  33. package/client.ts +0 -177
  34. package/config.js +0 -7
  35. package/config.ts +0 -5
  36. package/errors.js +0 -345
  37. package/errors.ts +0 -371
  38. package/index.js +0 -73
  39. package/index.ts +0 -59
  40. package/onboarding/doppler.ts +0 -116
  41. package/onboarding/git.ts +0 -133
  42. package/onboarding/index.ts +0 -18
  43. package/onboarding/onboarding.ts +0 -193
  44. package/onboarding/tailscale.ts +0 -159
  45. package/onboarding/types.ts +0 -115
  46. package/pricing.js +0 -387
  47. package/pricing.ts +0 -422
  48. package/schemas.js +0 -667
  49. package/schemas.ts +0 -765
  50. package/server-status.js +0 -122
  51. package/server-status.ts +0 -81
  52. package/servers.js +0 -667
  53. package/servers.ts +0 -568
  54. package/ssh-keys.js +0 -180
  55. package/ssh-keys.ts +0 -122
  56. package/ssh-setup.js +0 -253
  57. package/ssh-setup.ts +0 -218
  58. package/types.js +0 -99
  59. package/types.ts +0 -389
  60. package/volumes.js +0 -295
  61. package/volumes.ts +0 -229
package/volumes.js DELETED
@@ -1,295 +0,0 @@
1
- "use strict";
2
- /**
3
- * Hetzner Volume Operations
4
- *
5
- * Provides methods for managing Hetzner Cloud volumes.
6
- * See: https://docs.hetzner.cloud/#volumes
7
- */
8
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
9
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10
- return new (P || (P = Promise))(function (resolve, reject) {
11
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14
- step((generator = generator.apply(thisArg, _arguments || [])).next());
15
- });
16
- };
17
- var __generator = (this && this.__generator) || function (thisArg, body) {
18
- 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);
19
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
20
- function verb(n) { return function (v) { return step([n, v]); }; }
21
- function step(op) {
22
- if (f) throw new TypeError("Generator is already executing.");
23
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
24
- 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;
25
- if (y = 0, t) op = [op[0] & 2, t.value];
26
- switch (op[0]) {
27
- case 0: case 1: t = op; break;
28
- case 4: _.label++; return { value: op[1], done: false };
29
- case 5: _.label++; y = op[1]; op = [0]; continue;
30
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
31
- default:
32
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
33
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
34
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
35
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
36
- if (t[2]) _.ops.pop();
37
- _.trys.pop(); continue;
38
- }
39
- op = body.call(thisArg, _);
40
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
41
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
42
- }
43
- };
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.VolumeOperations = void 0;
46
- /**
47
- * Volume operations for Hetzner Cloud API
48
- */
49
- var VolumeOperations = /** @class */ (function () {
50
- function VolumeOperations(client) {
51
- this.client = client;
52
- }
53
- /**
54
- * List all volumes
55
- *
56
- * @param options - List options (name, status, sort, etc.)
57
- * @returns Array of volumes
58
- */
59
- VolumeOperations.prototype.list = function (options) {
60
- return __awaiter(this, void 0, void 0, function () {
61
- var params, endpoint, response;
62
- return __generator(this, function (_a) {
63
- switch (_a.label) {
64
- case 0:
65
- params = new URLSearchParams();
66
- if (options === null || options === void 0 ? void 0 : options.name)
67
- params.set("name", options.name);
68
- if (options === null || options === void 0 ? void 0 : options.status)
69
- params.set("status", options.status);
70
- if (options === null || options === void 0 ? void 0 : options.sort)
71
- params.set("sort", options.sort);
72
- if (options === null || options === void 0 ? void 0 : options.label_selector)
73
- params.set("label_selector", options.label_selector);
74
- endpoint = "/volumes".concat(params.toString() ? "?".concat(params) : "");
75
- return [4 /*yield*/, this.client.request(endpoint)];
76
- case 1:
77
- response = _a.sent();
78
- return [2 /*return*/, response.volumes || []];
79
- }
80
- });
81
- });
82
- };
83
- /**
84
- * Get a specific volume by ID
85
- *
86
- * @param id - Volume ID
87
- * @returns Volume details
88
- */
89
- VolumeOperations.prototype.get = function (id) {
90
- return __awaiter(this, void 0, void 0, function () {
91
- var response;
92
- return __generator(this, function (_a) {
93
- switch (_a.label) {
94
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(id))];
95
- case 1:
96
- response = _a.sent();
97
- return [2 /*return*/, response.volume];
98
- }
99
- });
100
- });
101
- };
102
- /**
103
- * Create a new volume
104
- *
105
- * @param options - Volume creation options
106
- * @returns Created volume with action info
107
- */
108
- VolumeOperations.prototype.create = function (options) {
109
- return __awaiter(this, void 0, void 0, function () {
110
- var response;
111
- var _a;
112
- return __generator(this, function (_b) {
113
- switch (_b.label) {
114
- case 0: return [4 /*yield*/, this.client.request("/volumes", {
115
- method: "POST",
116
- body: JSON.stringify({
117
- name: options.name,
118
- size: options.size,
119
- server: options.server,
120
- location: options.location,
121
- automount: (_a = options.automount) !== null && _a !== void 0 ? _a : true,
122
- format: options.format,
123
- labels: options.labels,
124
- }),
125
- })];
126
- case 1:
127
- response = _b.sent();
128
- return [2 /*return*/, response];
129
- }
130
- });
131
- });
132
- };
133
- /**
134
- * Delete a volume
135
- *
136
- * @param id - Volume ID
137
- * @returns Action response
138
- */
139
- VolumeOperations.prototype.delete = function (id) {
140
- return __awaiter(this, void 0, void 0, function () {
141
- var response;
142
- return __generator(this, function (_a) {
143
- switch (_a.label) {
144
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(id), {
145
- method: "DELETE",
146
- })];
147
- case 1:
148
- response = _a.sent();
149
- return [2 /*return*/, response.action];
150
- }
151
- });
152
- });
153
- };
154
- /**
155
- * Attach a volume to a server
156
- *
157
- * @param volumeId - Volume ID
158
- * @param serverId - Server ID
159
- * @param automount - Automatically mount the volume
160
- * @returns Action response
161
- */
162
- VolumeOperations.prototype.attach = function (volumeId_1, serverId_1) {
163
- return __awaiter(this, arguments, void 0, function (volumeId, serverId, automount) {
164
- var response;
165
- if (automount === void 0) { automount = true; }
166
- return __generator(this, function (_a) {
167
- switch (_a.label) {
168
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/attach"), {
169
- method: "POST",
170
- body: JSON.stringify({
171
- server: serverId,
172
- automount: automount,
173
- }),
174
- })];
175
- case 1:
176
- response = _a.sent();
177
- return [2 /*return*/, response.action];
178
- }
179
- });
180
- });
181
- };
182
- /**
183
- * Detach a volume from a server
184
- *
185
- * @param volumeId - Volume ID
186
- * @returns Action response
187
- */
188
- VolumeOperations.prototype.detach = function (volumeId) {
189
- return __awaiter(this, void 0, void 0, function () {
190
- var response;
191
- return __generator(this, function (_a) {
192
- switch (_a.label) {
193
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/detach"), {
194
- method: "POST",
195
- })];
196
- case 1:
197
- response = _a.sent();
198
- return [2 /*return*/, response.action];
199
- }
200
- });
201
- });
202
- };
203
- /**
204
- * Resize a volume
205
- *
206
- * @param volumeId - Volume ID
207
- * @param size - New size in GB (must be larger than current)
208
- * @returns Action response
209
- */
210
- VolumeOperations.prototype.resize = function (volumeId, size) {
211
- return __awaiter(this, void 0, void 0, function () {
212
- var response;
213
- return __generator(this, function (_a) {
214
- switch (_a.label) {
215
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/resize"), {
216
- method: "POST",
217
- body: JSON.stringify({ size: size }),
218
- })];
219
- case 1:
220
- response = _a.sent();
221
- return [2 /*return*/, response.action];
222
- }
223
- });
224
- });
225
- };
226
- /**
227
- * Change volume protection
228
- *
229
- * @param volumeId - Volume ID
230
- * @param deleteProtection - Enable delete protection
231
- * @returns Action response
232
- */
233
- VolumeOperations.prototype.changeProtection = function (volumeId, deleteProtection) {
234
- return __awaiter(this, void 0, void 0, function () {
235
- var response;
236
- return __generator(this, function (_a) {
237
- switch (_a.label) {
238
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/change_protection"), {
239
- method: "POST",
240
- body: JSON.stringify({
241
- delete: deleteProtection,
242
- }),
243
- })];
244
- case 1:
245
- response = _a.sent();
246
- return [2 /*return*/, response.action];
247
- }
248
- });
249
- });
250
- };
251
- /**
252
- * Update volume labels
253
- *
254
- * @param volumeId - Volume ID
255
- * @param labels - New labels
256
- * @returns Updated volume
257
- */
258
- VolumeOperations.prototype.updateLabels = function (volumeId, labels) {
259
- return __awaiter(this, void 0, void 0, function () {
260
- var response;
261
- return __generator(this, function (_a) {
262
- switch (_a.label) {
263
- case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId), {
264
- method: "PUT",
265
- body: JSON.stringify({ labels: labels }),
266
- })];
267
- case 1:
268
- response = _a.sent();
269
- return [2 /*return*/, response.volume];
270
- }
271
- });
272
- });
273
- };
274
- /**
275
- * Get volume pricing information
276
- * Calculates monthly cost based on size (€0.008/GB per month)
277
- *
278
- * @param sizeInGB - Volume size in GB
279
- * @returns Monthly and hourly pricing
280
- */
281
- VolumeOperations.calculatePrice = function (sizeInGB) {
282
- var PRICE_PER_GB_MONTHLY = 0.008; // €0.008 per GB per month
283
- var HOURS_PER_MONTH = 730; // Average
284
- var monthly = sizeInGB * PRICE_PER_GB_MONTHLY;
285
- var hourly = monthly / HOURS_PER_MONTH;
286
- return {
287
- size: sizeInGB,
288
- monthly: Math.round(monthly * 100) / 100,
289
- hourly: Math.round(hourly * 10000) / 10000,
290
- currency: "EUR",
291
- };
292
- };
293
- return VolumeOperations;
294
- }());
295
- exports.VolumeOperations = VolumeOperations;
package/volumes.ts DELETED
@@ -1,229 +0,0 @@
1
- /**
2
- * Hetzner Volume Operations
3
- *
4
- * Provides methods for managing Hetzner Cloud volumes.
5
- * See: https://docs.hetzner.cloud/#volumes
6
- */
7
-
8
- import type { HetznerClient } from "./client.js";
9
- import type {
10
- HetznerVolume,
11
- CreateVolumeOptions,
12
- } from "./types.js";
13
- import {
14
- HetznerListVolumesResponseSchema,
15
- HetznerGetVolumeResponseSchema,
16
- HetznerCreateVolumeResponseSchema,
17
- HetznerActionResponseSchema,
18
- } from "./schemas.js";
19
-
20
- /**
21
- * Volume operations for Hetzner Cloud API
22
- */
23
- export class VolumeOperations {
24
- constructor(private client: HetznerClient) {}
25
-
26
- /**
27
- * List all volumes
28
- *
29
- * @param options - List options (name, status, sort, etc.)
30
- * @returns Array of volumes
31
- */
32
- async list(options?: {
33
- name?: string;
34
- status?: string;
35
- sort?: string;
36
- label_selector?: string;
37
- }): Promise<HetznerVolume[]> {
38
- const params = new URLSearchParams();
39
- if (options?.name) params.set("name", options.name);
40
- if (options?.status) params.set("status", options.status);
41
- if (options?.sort) params.set("sort", options.sort);
42
- if (options?.label_selector) params.set("label_selector", options.label_selector);
43
-
44
- const endpoint = `/volumes${params.toString() ? `?${params}` : ""}`;
45
- const response = await this.client.request<typeof HetznerListVolumesResponseSchema._output>(
46
- endpoint,
47
- );
48
-
49
- return response.volumes || [];
50
- }
51
-
52
- /**
53
- * Get a specific volume by ID
54
- *
55
- * @param id - Volume ID
56
- * @returns Volume details
57
- */
58
- async get(id: number): Promise<HetznerVolume> {
59
- const response = await this.client.request<typeof HetznerGetVolumeResponseSchema._output>(
60
- `/volumes/${id}`,
61
- );
62
- return response.volume;
63
- }
64
-
65
- /**
66
- * Create a new volume
67
- *
68
- * @param options - Volume creation options
69
- * @returns Created volume with action info
70
- */
71
- async create(options: CreateVolumeOptions): Promise<{
72
- volume: HetznerVolume;
73
- action: any;
74
- next_actions: any[];
75
- }> {
76
- const response = await this.client.request<typeof HetznerCreateVolumeResponseSchema._output>(
77
- "/volumes",
78
- {
79
- method: "POST",
80
- body: JSON.stringify({
81
- name: options.name,
82
- size: options.size,
83
- server: options.server,
84
- location: options.location,
85
- automount: options.automount ?? true,
86
- format: options.format,
87
- labels: options.labels,
88
- }),
89
- },
90
- );
91
- return response;
92
- }
93
-
94
- /**
95
- * Delete a volume
96
- *
97
- * @param id - Volume ID
98
- * @returns Action response
99
- */
100
- async delete(id: number): Promise<any> {
101
- const response = await this.client.request<typeof HetznerActionResponseSchema._output>(
102
- `/volumes/${id}`,
103
- {
104
- method: "DELETE",
105
- },
106
- );
107
- return response.action;
108
- }
109
-
110
- /**
111
- * Attach a volume to a server
112
- *
113
- * @param volumeId - Volume ID
114
- * @param serverId - Server ID
115
- * @param automount - Automatically mount the volume
116
- * @returns Action response
117
- */
118
- async attach(
119
- volumeId: number,
120
- serverId: number,
121
- automount: boolean = true,
122
- ): Promise<any> {
123
- const response = await this.client.request<typeof HetznerActionResponseSchema._output>(
124
- `/volumes/${volumeId}/actions/attach`,
125
- {
126
- method: "POST",
127
- body: JSON.stringify({
128
- server: serverId,
129
- automount,
130
- }),
131
- },
132
- );
133
- return response.action;
134
- }
135
-
136
- /**
137
- * Detach a volume from a server
138
- *
139
- * @param volumeId - Volume ID
140
- * @returns Action response
141
- */
142
- async detach(volumeId: number): Promise<any> {
143
- const response = await this.client.request<typeof HetznerActionResponseSchema._output>(
144
- `/volumes/${volumeId}/actions/detach`,
145
- {
146
- method: "POST",
147
- },
148
- );
149
- return response.action;
150
- }
151
-
152
- /**
153
- * Resize a volume
154
- *
155
- * @param volumeId - Volume ID
156
- * @param size - New size in GB (must be larger than current)
157
- * @returns Action response
158
- */
159
- async resize(volumeId: number, size: number): Promise<any> {
160
- const response = await this.client.request<typeof HetznerActionResponseSchema._output>(
161
- `/volumes/${volumeId}/actions/resize`,
162
- {
163
- method: "POST",
164
- body: JSON.stringify({ size }),
165
- },
166
- );
167
- return response.action;
168
- }
169
-
170
- /**
171
- * Change volume protection
172
- *
173
- * @param volumeId - Volume ID
174
- * @param deleteProtection - Enable delete protection
175
- * @returns Action response
176
- */
177
- async changeProtection(volumeId: number, deleteProtection: boolean): Promise<any> {
178
- const response = await this.client.request<typeof HetznerActionResponseSchema._output>(
179
- `/volumes/${volumeId}/actions/change_protection`,
180
- {
181
- method: "POST",
182
- body: JSON.stringify({
183
- delete: deleteProtection,
184
- }),
185
- },
186
- );
187
- return response.action;
188
- }
189
-
190
- /**
191
- * Update volume labels
192
- *
193
- * @param volumeId - Volume ID
194
- * @param labels - New labels
195
- * @returns Updated volume
196
- */
197
- async updateLabels(volumeId: number, labels: Record<string, string>): Promise<HetznerVolume> {
198
- const response = await this.client.request<typeof HetznerGetVolumeResponseSchema._output>(
199
- `/volumes/${volumeId}`,
200
- {
201
- method: "PUT",
202
- body: JSON.stringify({ labels }),
203
- },
204
- );
205
- return response.volume;
206
- }
207
-
208
- /**
209
- * Get volume pricing information
210
- * Calculates monthly cost based on size (€0.008/GB per month)
211
- *
212
- * @param sizeInGB - Volume size in GB
213
- * @returns Monthly and hourly pricing
214
- */
215
- static calculatePrice(sizeInGB: number) {
216
- const PRICE_PER_GB_MONTHLY = 0.008; // €0.008 per GB per month
217
- const HOURS_PER_MONTH = 730; // Average
218
-
219
- const monthly = sizeInGB * PRICE_PER_GB_MONTHLY;
220
- const hourly = monthly / HOURS_PER_MONTH;
221
-
222
- return {
223
- size: sizeInGB,
224
- monthly: Math.round(monthly * 100) / 100,
225
- hourly: Math.round(hourly * 10000) / 10000,
226
- currency: "EUR",
227
- };
228
- }
229
- }