@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.
- package/dist/bootstrap/index.js +1126 -0
- package/dist/bootstrap/index.js.map +15 -0
- package/dist/index.js +3540 -0
- package/dist/index.js.map +31 -0
- package/dist/onboarding/index.js +460 -0
- package/dist/onboarding/index.js.map +14 -0
- package/package.json +53 -16
- package/actions.js +0 -1084
- package/actions.ts +0 -1053
- package/auth.js +0 -39
- package/auth.ts +0 -37
- package/bootstrap/FIREWALL.md +0 -326
- package/bootstrap/KERNEL-HARDENING.md +0 -258
- package/bootstrap/SECURITY-INTEGRATION.md +0 -281
- package/bootstrap/TESTING.md +0 -301
- package/bootstrap/cloud-init.js +0 -323
- package/bootstrap/cloud-init.ts +0 -394
- package/bootstrap/firewall.js +0 -292
- package/bootstrap/firewall.ts +0 -342
- package/bootstrap/genesis.js +0 -424
- package/bootstrap/genesis.ts +0 -518
- package/bootstrap/index.js +0 -59
- package/bootstrap/index.ts +0 -71
- package/bootstrap/kernel-hardening.js +0 -270
- package/bootstrap/kernel-hardening.test.js +0 -182
- package/bootstrap/kernel-hardening.test.ts +0 -230
- package/bootstrap/kernel-hardening.ts +0 -272
- package/bootstrap/security-audit.js +0 -122
- package/bootstrap/security-audit.ts +0 -124
- package/bootstrap/ssh-hardening.js +0 -186
- package/bootstrap/ssh-hardening.ts +0 -192
- package/client.js +0 -234
- package/client.ts +0 -177
- package/config.js +0 -7
- package/config.ts +0 -5
- package/errors.js +0 -345
- package/errors.ts +0 -371
- package/index.js +0 -73
- package/index.ts +0 -59
- package/onboarding/doppler.ts +0 -116
- package/onboarding/git.ts +0 -133
- package/onboarding/index.ts +0 -18
- package/onboarding/onboarding.ts +0 -193
- package/onboarding/tailscale.ts +0 -159
- package/onboarding/types.ts +0 -115
- package/pricing.js +0 -387
- package/pricing.ts +0 -422
- package/schemas.js +0 -667
- package/schemas.ts +0 -765
- package/server-status.js +0 -122
- package/server-status.ts +0 -81
- package/servers.js +0 -667
- package/servers.ts +0 -568
- package/ssh-keys.js +0 -180
- package/ssh-keys.ts +0 -122
- package/ssh-setup.js +0 -253
- package/ssh-setup.ts +0 -218
- package/types.js +0 -99
- package/types.ts +0 -389
- package/volumes.js +0 -295
- package/volumes.ts +0 -229
package/errors.js
DELETED
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Hetzner Cloud API error types and utilities
|
|
4
|
-
*/
|
|
5
|
-
var __extends = (this && this.__extends) || (function () {
|
|
6
|
-
var extendStatics = function (d, b) {
|
|
7
|
-
extendStatics = Object.setPrototypeOf ||
|
|
8
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
9
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
10
|
-
return extendStatics(d, b);
|
|
11
|
-
};
|
|
12
|
-
return function (d, b) {
|
|
13
|
-
if (typeof b !== "function" && b !== null)
|
|
14
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
15
|
-
extendStatics(d, b);
|
|
16
|
-
function __() { this.constructor = d; }
|
|
17
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
18
|
-
};
|
|
19
|
-
})();
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.HetznerTimeoutError = exports.HetznerActionError = exports.HetznerServiceError = exports.HetznerConflictError = exports.HetznerInvalidInputError = exports.HetznerResourceLimitError = exports.HetznerResourceLockedError = exports.HetznerRateLimitError = exports.HetznerNotFoundError = exports.HetznerForbiddenError = exports.HetznerUnauthorizedError = exports.HetznerAPIError = exports.HetznerErrorCode = void 0;
|
|
22
|
-
exports.createHetznerError = createHetznerError;
|
|
23
|
-
exports.isRetryableError = isRetryableError;
|
|
24
|
-
exports.isRateLimitError = isRateLimitError;
|
|
25
|
-
exports.isResourceLockedError = isResourceLockedError;
|
|
26
|
-
exports.calculateRetryDelay = calculateRetryDelay;
|
|
27
|
-
exports.defaultErrorHandler = defaultErrorHandler;
|
|
28
|
-
// ============================================================================
|
|
29
|
-
// Error Codes
|
|
30
|
-
// ============================================================================
|
|
31
|
-
/**
|
|
32
|
-
* Hetzner API error codes
|
|
33
|
-
* @see https://docs.hetzner.cloud/#errors
|
|
34
|
-
*/
|
|
35
|
-
var HetznerErrorCode;
|
|
36
|
-
(function (HetznerErrorCode) {
|
|
37
|
-
// Authentication errors
|
|
38
|
-
HetznerErrorCode["Unauthorized"] = "unauthorized";
|
|
39
|
-
HetznerErrorCode["InvalidInput"] = "invalid_input";
|
|
40
|
-
HetznerErrorCode["JSONError"] = "json_error";
|
|
41
|
-
HetznerErrorCode["Forbidden"] = "forbidden";
|
|
42
|
-
// Resource errors
|
|
43
|
-
HetznerErrorCode["NotFound"] = "not_found";
|
|
44
|
-
HetznerErrorCode["ResourceLocked"] = "locked";
|
|
45
|
-
HetznerErrorCode["ResourceLimitExceeded"] = "resource_limit_exceeded";
|
|
46
|
-
HetznerErrorCode["UniquenessError"] = "uniqueness_error";
|
|
47
|
-
// Rate limiting
|
|
48
|
-
HetznerErrorCode["RateLimitExceeded"] = "rate_limit_exceeded";
|
|
49
|
-
// Conflict errors
|
|
50
|
-
HetznerErrorCode["Conflict"] = "conflict";
|
|
51
|
-
HetznerErrorCode["ServiceError"] = "service_error";
|
|
52
|
-
// Server-specific errors
|
|
53
|
-
HetznerErrorCode["ServerNotStopped"] = "server_not_stopped";
|
|
54
|
-
HetznerErrorCode["ServerAlreadyStopped"] = "server_already_stopped";
|
|
55
|
-
HetznerErrorCode["InvalidServerType"] = "invalid_server_type";
|
|
56
|
-
// IP/network errors
|
|
57
|
-
HetznerErrorCode["IpNotOwned"] = "ip_not_owned";
|
|
58
|
-
HetznerErrorCode["IpAlreadyAssigned"] = "ip_already_assigned";
|
|
59
|
-
// Volume errors
|
|
60
|
-
HetznerErrorCode["VolumeAlreadyAttached"] = "volume_already_attached";
|
|
61
|
-
HetznerErrorCode["VolumeSizeNotMultiple"] = "volume_size_not_multiple";
|
|
62
|
-
// Firewall errors
|
|
63
|
-
HetznerErrorCode["FirewallInUse"] = "firewall_in_use";
|
|
64
|
-
// Certificate errors
|
|
65
|
-
HetznerErrorCode["CertificateValidationFailed"] = "certificate_validation_failed";
|
|
66
|
-
HetznerErrorCode["CertificatePending"] = "certificate_pending";
|
|
67
|
-
})(HetznerErrorCode || (exports.HetznerErrorCode = HetznerErrorCode = {}));
|
|
68
|
-
// ============================================================================
|
|
69
|
-
// Error Classes
|
|
70
|
-
// ============================================================================
|
|
71
|
-
/**
|
|
72
|
-
* Base Hetzner API error
|
|
73
|
-
*/
|
|
74
|
-
var HetznerAPIError = /** @class */ (function (_super) {
|
|
75
|
-
__extends(HetznerAPIError, _super);
|
|
76
|
-
function HetznerAPIError(message, code, details) {
|
|
77
|
-
var _this = _super.call(this, message) || this;
|
|
78
|
-
_this.code = code;
|
|
79
|
-
_this.details = details;
|
|
80
|
-
_this.name = "HetznerAPIError";
|
|
81
|
-
return _this;
|
|
82
|
-
}
|
|
83
|
-
return HetznerAPIError;
|
|
84
|
-
}(Error));
|
|
85
|
-
exports.HetznerAPIError = HetznerAPIError;
|
|
86
|
-
/**
|
|
87
|
-
* Authentication error (401)
|
|
88
|
-
*/
|
|
89
|
-
var HetznerUnauthorizedError = /** @class */ (function (_super) {
|
|
90
|
-
__extends(HetznerUnauthorizedError, _super);
|
|
91
|
-
function HetznerUnauthorizedError(message) {
|
|
92
|
-
if (message === void 0) { message = "Unauthorized: Invalid API token"; }
|
|
93
|
-
var _this = _super.call(this, message, HetznerErrorCode.Unauthorized) || this;
|
|
94
|
-
_this.name = "HetznerUnauthorizedError";
|
|
95
|
-
return _this;
|
|
96
|
-
}
|
|
97
|
-
return HetznerUnauthorizedError;
|
|
98
|
-
}(HetznerAPIError));
|
|
99
|
-
exports.HetznerUnauthorizedError = HetznerUnauthorizedError;
|
|
100
|
-
/**
|
|
101
|
-
* Forbidden error (403)
|
|
102
|
-
*/
|
|
103
|
-
var HetznerForbiddenError = /** @class */ (function (_super) {
|
|
104
|
-
__extends(HetznerForbiddenError, _super);
|
|
105
|
-
function HetznerForbiddenError(message) {
|
|
106
|
-
if (message === void 0) { message = "Forbidden: Insufficient permissions"; }
|
|
107
|
-
var _this = _super.call(this, message, HetznerErrorCode.Forbidden) || this;
|
|
108
|
-
_this.name = "HetznerForbiddenError";
|
|
109
|
-
return _this;
|
|
110
|
-
}
|
|
111
|
-
return HetznerForbiddenError;
|
|
112
|
-
}(HetznerAPIError));
|
|
113
|
-
exports.HetznerForbiddenError = HetznerForbiddenError;
|
|
114
|
-
/**
|
|
115
|
-
* Resource not found error (404)
|
|
116
|
-
*/
|
|
117
|
-
var HetznerNotFoundError = /** @class */ (function (_super) {
|
|
118
|
-
__extends(HetznerNotFoundError, _super);
|
|
119
|
-
function HetznerNotFoundError(resource, id) {
|
|
120
|
-
var _this = _super.call(this, "".concat(resource, " with ID ").concat(id, " not found"), HetznerErrorCode.NotFound, { resource: resource, id: id }) || this;
|
|
121
|
-
_this.name = "HetznerNotFoundError";
|
|
122
|
-
return _this;
|
|
123
|
-
}
|
|
124
|
-
return HetznerNotFoundError;
|
|
125
|
-
}(HetznerAPIError));
|
|
126
|
-
exports.HetznerNotFoundError = HetznerNotFoundError;
|
|
127
|
-
/**
|
|
128
|
-
* Rate limit exceeded error (429)
|
|
129
|
-
*/
|
|
130
|
-
var HetznerRateLimitError = /** @class */ (function (_super) {
|
|
131
|
-
__extends(HetznerRateLimitError, _super);
|
|
132
|
-
function HetznerRateLimitError(message, rateLimitInfo) {
|
|
133
|
-
if (message === void 0) { message = "Rate limit exceeded"; }
|
|
134
|
-
var _this = _super.call(this, message, HetznerErrorCode.RateLimitExceeded, rateLimitInfo) || this;
|
|
135
|
-
_this.rateLimitInfo = rateLimitInfo;
|
|
136
|
-
_this.name = "HetznerRateLimitError";
|
|
137
|
-
return _this;
|
|
138
|
-
}
|
|
139
|
-
Object.defineProperty(HetznerRateLimitError.prototype, "resetInMs", {
|
|
140
|
-
/**
|
|
141
|
-
* Get the number of milliseconds until the rate limit resets
|
|
142
|
-
*/
|
|
143
|
-
get: function () {
|
|
144
|
-
if (!this.rateLimitInfo)
|
|
145
|
-
return 60000; // Default to 1 minute
|
|
146
|
-
return Math.max(0, this.rateLimitInfo.reset * 1000 - Date.now());
|
|
147
|
-
},
|
|
148
|
-
enumerable: false,
|
|
149
|
-
configurable: true
|
|
150
|
-
});
|
|
151
|
-
Object.defineProperty(HetznerRateLimitError.prototype, "resetTime", {
|
|
152
|
-
/**
|
|
153
|
-
* Get a human-readable reset time
|
|
154
|
-
*/
|
|
155
|
-
get: function () {
|
|
156
|
-
if (!this.rateLimitInfo)
|
|
157
|
-
return "unknown";
|
|
158
|
-
return new Date(this.rateLimitInfo.reset * 1000).toISOString();
|
|
159
|
-
},
|
|
160
|
-
enumerable: false,
|
|
161
|
-
configurable: true
|
|
162
|
-
});
|
|
163
|
-
return HetznerRateLimitError;
|
|
164
|
-
}(HetznerAPIError));
|
|
165
|
-
exports.HetznerRateLimitError = HetznerRateLimitError;
|
|
166
|
-
/**
|
|
167
|
-
* Resource locked error
|
|
168
|
-
*/
|
|
169
|
-
var HetznerResourceLockedError = /** @class */ (function (_super) {
|
|
170
|
-
__extends(HetznerResourceLockedError, _super);
|
|
171
|
-
function HetznerResourceLockedError(resource, id, actionInProgress) {
|
|
172
|
-
var _this = _super.call(this, "".concat(resource, " ").concat(id, " is locked").concat(actionInProgress ? " by ".concat(actionInProgress) : ""), HetznerErrorCode.ResourceLocked, { resource: resource, id: id, actionInProgress: actionInProgress }) || this;
|
|
173
|
-
_this.actionInProgress = actionInProgress;
|
|
174
|
-
_this.name = "HetznerResourceLockedError";
|
|
175
|
-
return _this;
|
|
176
|
-
}
|
|
177
|
-
return HetznerResourceLockedError;
|
|
178
|
-
}(HetznerAPIError));
|
|
179
|
-
exports.HetznerResourceLockedError = HetznerResourceLockedError;
|
|
180
|
-
/**
|
|
181
|
-
* Resource limit exceeded error
|
|
182
|
-
*/
|
|
183
|
-
var HetznerResourceLimitError = /** @class */ (function (_super) {
|
|
184
|
-
__extends(HetznerResourceLimitError, _super);
|
|
185
|
-
function HetznerResourceLimitError(resource, limit) {
|
|
186
|
-
var _this = _super.call(this, "Resource limit exceeded: ".concat(resource, " (limit: ").concat(limit, ")"), HetznerErrorCode.ResourceLimitExceeded, { resource: resource, limit: limit }) || this;
|
|
187
|
-
_this.name = "HetznerResourceLimitError";
|
|
188
|
-
return _this;
|
|
189
|
-
}
|
|
190
|
-
return HetznerResourceLimitError;
|
|
191
|
-
}(HetznerAPIError));
|
|
192
|
-
exports.HetznerResourceLimitError = HetznerResourceLimitError;
|
|
193
|
-
/**
|
|
194
|
-
* Invalid input error
|
|
195
|
-
*/
|
|
196
|
-
var HetznerInvalidInputError = /** @class */ (function (_super) {
|
|
197
|
-
__extends(HetznerInvalidInputError, _super);
|
|
198
|
-
function HetznerInvalidInputError(message, fields) {
|
|
199
|
-
var _this = _super.call(this, message, HetznerErrorCode.InvalidInput, { fields: fields }) || this;
|
|
200
|
-
_this.fields = fields;
|
|
201
|
-
_this.name = "HetznerInvalidInputError";
|
|
202
|
-
return _this;
|
|
203
|
-
}
|
|
204
|
-
return HetznerInvalidInputError;
|
|
205
|
-
}(HetznerAPIError));
|
|
206
|
-
exports.HetznerInvalidInputError = HetznerInvalidInputError;
|
|
207
|
-
/**
|
|
208
|
-
* Conflict error
|
|
209
|
-
*/
|
|
210
|
-
var HetznerConflictError = /** @class */ (function (_super) {
|
|
211
|
-
__extends(HetznerConflictError, _super);
|
|
212
|
-
function HetznerConflictError(message, details) {
|
|
213
|
-
var _this = _super.call(this, message, HetznerErrorCode.Conflict, details) || this;
|
|
214
|
-
_this.name = "HetznerConflictError";
|
|
215
|
-
return _this;
|
|
216
|
-
}
|
|
217
|
-
return HetznerConflictError;
|
|
218
|
-
}(HetznerAPIError));
|
|
219
|
-
exports.HetznerConflictError = HetznerConflictError;
|
|
220
|
-
/**
|
|
221
|
-
* Service error (5xx)
|
|
222
|
-
*/
|
|
223
|
-
var HetznerServiceError = /** @class */ (function (_super) {
|
|
224
|
-
__extends(HetznerServiceError, _super);
|
|
225
|
-
function HetznerServiceError(message, statusCode) {
|
|
226
|
-
var _this = _super.call(this, message, HetznerErrorCode.ServiceError, { statusCode: statusCode }) || this;
|
|
227
|
-
_this.statusCode = statusCode;
|
|
228
|
-
_this.name = "HetznerServiceError";
|
|
229
|
-
return _this;
|
|
230
|
-
}
|
|
231
|
-
return HetznerServiceError;
|
|
232
|
-
}(HetznerAPIError));
|
|
233
|
-
exports.HetznerServiceError = HetznerServiceError;
|
|
234
|
-
/**
|
|
235
|
-
* Action failed error
|
|
236
|
-
*/
|
|
237
|
-
var HetznerActionError = /** @class */ (function (_super) {
|
|
238
|
-
__extends(HetznerActionError, _super);
|
|
239
|
-
function HetznerActionError(actionError, actionId) {
|
|
240
|
-
var _this = _super.call(this, "Action ".concat(actionId, " failed: ").concat(actionError.code, " - ").concat(actionError.message), actionError.code, { actionError: actionError, actionId: actionId }) || this;
|
|
241
|
-
_this.actionError = actionError;
|
|
242
|
-
_this.actionId = actionId;
|
|
243
|
-
_this.name = "HetznerActionError";
|
|
244
|
-
return _this;
|
|
245
|
-
}
|
|
246
|
-
return HetznerActionError;
|
|
247
|
-
}(HetznerAPIError));
|
|
248
|
-
exports.HetznerActionError = HetznerActionError;
|
|
249
|
-
/**
|
|
250
|
-
* Timeout error for action polling
|
|
251
|
-
*/
|
|
252
|
-
var HetznerTimeoutError = /** @class */ (function (_super) {
|
|
253
|
-
__extends(HetznerTimeoutError, _super);
|
|
254
|
-
function HetznerTimeoutError(actionId, timeout, lastProgress) {
|
|
255
|
-
var _this = _super.call(this, "Action ".concat(actionId, " timed out after ").concat(timeout, "ms (last progress: ").concat(lastProgress, "%)"), "timeout", { actionId: actionId, timeout: timeout, lastProgress: lastProgress }) || this;
|
|
256
|
-
_this.lastProgress = lastProgress;
|
|
257
|
-
_this.name = "HetznerTimeoutError";
|
|
258
|
-
return _this;
|
|
259
|
-
}
|
|
260
|
-
return HetznerTimeoutError;
|
|
261
|
-
}(HetznerAPIError));
|
|
262
|
-
exports.HetznerTimeoutError = HetznerTimeoutError;
|
|
263
|
-
// ============================================================================
|
|
264
|
-
// Error Factory
|
|
265
|
-
// ============================================================================
|
|
266
|
-
/**
|
|
267
|
-
* Parse Hetzner API error response and create appropriate error
|
|
268
|
-
*/
|
|
269
|
-
function createHetznerError(statusCode, body) {
|
|
270
|
-
var error = body.error;
|
|
271
|
-
if (!error) {
|
|
272
|
-
return new HetznerServiceError("HTTP ".concat(statusCode, ": ").concat(JSON.stringify(body)), statusCode);
|
|
273
|
-
}
|
|
274
|
-
switch (statusCode) {
|
|
275
|
-
case 401:
|
|
276
|
-
return new HetznerUnauthorizedError(error.message);
|
|
277
|
-
case 403:
|
|
278
|
-
return new HetznerForbiddenError(error.message);
|
|
279
|
-
case 404:
|
|
280
|
-
return new HetznerNotFoundError("resource", "unknown");
|
|
281
|
-
case 429:
|
|
282
|
-
return new HetznerRateLimitError(error.message);
|
|
283
|
-
case 400:
|
|
284
|
-
if (error.code === HetznerErrorCode.ResourceLocked) {
|
|
285
|
-
return new HetznerResourceLockedError("resource", "unknown", error.message);
|
|
286
|
-
}
|
|
287
|
-
if (error.code === HetznerErrorCode.InvalidInput) {
|
|
288
|
-
return new HetznerInvalidInputError(error.message);
|
|
289
|
-
}
|
|
290
|
-
return new HetznerInvalidInputError(error.message);
|
|
291
|
-
case 409:
|
|
292
|
-
return new HetznerConflictError(error.message, error.details);
|
|
293
|
-
default:
|
|
294
|
-
if (statusCode >= 500) {
|
|
295
|
-
return new HetznerServiceError(error.message, statusCode);
|
|
296
|
-
}
|
|
297
|
-
return new HetznerAPIError(error.message, error.code, error.details);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Check if an error is retryable
|
|
302
|
-
*/
|
|
303
|
-
function isRetryableError(error) {
|
|
304
|
-
if (error instanceof HetznerRateLimitError)
|
|
305
|
-
return true;
|
|
306
|
-
if (error instanceof HetznerResourceLockedError)
|
|
307
|
-
return true;
|
|
308
|
-
if (error instanceof HetznerServiceError)
|
|
309
|
-
return true;
|
|
310
|
-
if (error instanceof HetznerConflictError)
|
|
311
|
-
return true;
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Check if an error is a rate limit error
|
|
316
|
-
*/
|
|
317
|
-
function isRateLimitError(error) {
|
|
318
|
-
return error instanceof HetznerRateLimitError;
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Check if an error is a resource locked error
|
|
322
|
-
*/
|
|
323
|
-
function isResourceLockedError(error) {
|
|
324
|
-
return error instanceof HetznerResourceLockedError;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Calculate retry delay with exponential backoff
|
|
328
|
-
*/
|
|
329
|
-
function calculateRetryDelay(attempt, baseDelay, maxDelay) {
|
|
330
|
-
if (baseDelay === void 0) { baseDelay = 1000; }
|
|
331
|
-
if (maxDelay === void 0) { maxDelay = 60000; }
|
|
332
|
-
var delay = baseDelay * Math.pow(2, attempt);
|
|
333
|
-
// Add jitter (±25%)
|
|
334
|
-
var jitter = delay * 0.25 * (Math.random() * 2 - 1);
|
|
335
|
-
return Math.min(maxDelay, delay + jitter);
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Default error handler that logs to console
|
|
339
|
-
*/
|
|
340
|
-
function defaultErrorHandler(error) {
|
|
341
|
-
console.error("[Hetzner API Error] ".concat(error.name, ": ").concat(error.message));
|
|
342
|
-
if (error.details) {
|
|
343
|
-
console.error("Details:", error.details);
|
|
344
|
-
}
|
|
345
|
-
}
|