@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/client.js
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Hetzner Cloud API client
|
|
4
|
-
* For server-side use only (requires API token)
|
|
5
|
-
*
|
|
6
|
-
* TODO: RE-REVIEW https://docs.hetzner.cloud/reference/cloud#authentication
|
|
7
|
-
* - https://tailscale.com/kb/1150/cloud-hetzner
|
|
8
|
-
*/
|
|
9
|
-
var __assign = (this && this.__assign) || function () {
|
|
10
|
-
__assign = Object.assign || function(t) {
|
|
11
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
12
|
-
s = arguments[i];
|
|
13
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
14
|
-
t[p] = s[p];
|
|
15
|
-
}
|
|
16
|
-
return t;
|
|
17
|
-
};
|
|
18
|
-
return __assign.apply(this, arguments);
|
|
19
|
-
};
|
|
20
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
21
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
22
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
23
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
24
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
25
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
26
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
30
|
-
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);
|
|
31
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
32
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
33
|
-
function step(op) {
|
|
34
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
35
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
36
|
-
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;
|
|
37
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
38
|
-
switch (op[0]) {
|
|
39
|
-
case 0: case 1: t = op; break;
|
|
40
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
41
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
42
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
43
|
-
default:
|
|
44
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
45
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
46
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
47
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
48
|
-
if (t[2]) _.ops.pop();
|
|
49
|
-
_.trys.pop(); continue;
|
|
50
|
-
}
|
|
51
|
-
op = body.call(thisArg, _);
|
|
52
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
53
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
-
exports.HetznerClient = void 0;
|
|
58
|
-
// Explicitly import fetch for Bun compatibility
|
|
59
|
-
var bun_1 = require("bun");
|
|
60
|
-
var config_js_1 = require("./config.js");
|
|
61
|
-
// Use Bun's fetch if available, otherwise try global fetch
|
|
62
|
-
var fetch = bun_1.fetch || globalThis.fetch;
|
|
63
|
-
var auth_js_1 = require("./auth.js");
|
|
64
|
-
var servers_js_1 = require("./servers.js");
|
|
65
|
-
var actions_js_1 = require("./actions.js");
|
|
66
|
-
var pricing_js_1 = require("./pricing.js");
|
|
67
|
-
var ssh_keys_js_1 = require("./ssh-keys.js");
|
|
68
|
-
var volumes_js_1 = require("./volumes.js");
|
|
69
|
-
var errors_js_1 = require("./errors.js");
|
|
70
|
-
var actions_js_2 = require("./actions.js");
|
|
71
|
-
var HetznerClient = /** @class */ (function () {
|
|
72
|
-
function HetznerClient(apiToken) {
|
|
73
|
-
this.servers = new servers_js_1.ServerOperations(this);
|
|
74
|
-
this.actions = new actions_js_1.ActionOperations(this);
|
|
75
|
-
this.pricing = new pricing_js_1.PricingOperations(this);
|
|
76
|
-
this.ssh_keys = new ssh_keys_js_1.SSHKeyOperations(this);
|
|
77
|
-
this.volumes = new volumes_js_1.VolumeOperations(this);
|
|
78
|
-
this.apiToken = (0, auth_js_1.resolveApiToken)(apiToken);
|
|
79
|
-
// If no token from env or explicit, try CLI config
|
|
80
|
-
if (!this.apiToken) {
|
|
81
|
-
this.apiToken = (0, auth_js_1.getTokenFromCLI)();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
Object.defineProperty(HetznerClient.prototype, "isAuthenticated", {
|
|
85
|
-
get: function () {
|
|
86
|
-
return (0, auth_js_1.isAuthenticated)(this.apiToken);
|
|
87
|
-
},
|
|
88
|
-
enumerable: false,
|
|
89
|
-
configurable: true
|
|
90
|
-
});
|
|
91
|
-
/**
|
|
92
|
-
* Make a request to the Hetzner Cloud API
|
|
93
|
-
*
|
|
94
|
-
* @param endpoint - API endpoint (e.g., "/servers")
|
|
95
|
-
* @param options - RequestInit options
|
|
96
|
-
* @returns Parsed JSON response
|
|
97
|
-
* @throws {HetznerAPIError} On API errors
|
|
98
|
-
*/
|
|
99
|
-
HetznerClient.prototype.request = function (endpoint_1) {
|
|
100
|
-
return __awaiter(this, arguments, void 0, function (endpoint, options) {
|
|
101
|
-
var response, rateLimit, body, data;
|
|
102
|
-
if (options === void 0) { options = {}; }
|
|
103
|
-
return __generator(this, function (_a) {
|
|
104
|
-
switch (_a.label) {
|
|
105
|
-
case 0: return [4 /*yield*/, fetch("".concat(config_js_1.HETZNER_API_BASE).concat(endpoint), __assign(__assign({}, options), { headers: __assign({ Authorization: "Bearer ".concat(this.apiToken), "Content-Type": "application/json" }, options.headers) }))];
|
|
106
|
-
case 1:
|
|
107
|
-
response = _a.sent();
|
|
108
|
-
rateLimit = (0, actions_js_2.parseRateLimitHeaders)(response.headers);
|
|
109
|
-
this.handleRateLimit(rateLimit);
|
|
110
|
-
if (!!response.ok) return [3 /*break*/, 3];
|
|
111
|
-
return [4 /*yield*/, response.json().catch(function () { return ({}); })];
|
|
112
|
-
case 2:
|
|
113
|
-
body = _a.sent();
|
|
114
|
-
throw (0, errors_js_1.createHetznerError)(response.status, body);
|
|
115
|
-
case 3: return [4 /*yield*/, response.json()];
|
|
116
|
-
case 4:
|
|
117
|
-
data = _a.sent();
|
|
118
|
-
return [2 /*return*/, data];
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
};
|
|
123
|
-
/**
|
|
124
|
-
* Validate Hetzner API response with Zod schema
|
|
125
|
-
*
|
|
126
|
-
* @param schema - Zod schema to validate against
|
|
127
|
-
* @param data - Data to validate
|
|
128
|
-
* @returns Validated data
|
|
129
|
-
*/
|
|
130
|
-
HetznerClient.prototype.validateResponse = function (schema, data) {
|
|
131
|
-
var result = schema.safeParse(data);
|
|
132
|
-
if (result.success) {
|
|
133
|
-
return result.data;
|
|
134
|
-
}
|
|
135
|
-
// Log validation errors but don't throw to maintain backward compatibility
|
|
136
|
-
console.warn("Hetzner API response validation warning:", result.error.issues);
|
|
137
|
-
return data;
|
|
138
|
-
};
|
|
139
|
-
/**
|
|
140
|
-
* Handle rate limit information from response headers
|
|
141
|
-
*
|
|
142
|
-
* @param rateLimit - Rate limit info from response
|
|
143
|
-
*/
|
|
144
|
-
HetznerClient.prototype.handleRateLimit = function (rateLimit) {
|
|
145
|
-
if (!rateLimit)
|
|
146
|
-
return;
|
|
147
|
-
// Warn if rate limit is low
|
|
148
|
-
if (rateLimit.remaining < 100) {
|
|
149
|
-
console.warn("[Hetzner API] Rate limit low: ".concat(rateLimit.remaining, "/").concat(rateLimit.limit, " remaining. Resets at ").concat(new Date(rateLimit.reset * 1000).toISOString()));
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* Get current rate limit information
|
|
154
|
-
*
|
|
155
|
-
* Makes a lightweight request to check rate limit status
|
|
156
|
-
*
|
|
157
|
-
* @returns Rate limit info or null if not available
|
|
158
|
-
*/
|
|
159
|
-
HetznerClient.prototype.getRateLimit = function () {
|
|
160
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
161
|
-
var response, _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*/, fetch("".concat(config_js_1.HETZNER_API_BASE, "/servers"), {
|
|
167
|
-
headers: {
|
|
168
|
-
Authorization: "Bearer ".concat(this.apiToken),
|
|
169
|
-
},
|
|
170
|
-
})];
|
|
171
|
-
case 1:
|
|
172
|
-
response = _b.sent();
|
|
173
|
-
return [2 /*return*/, (0, actions_js_2.parseRateLimitHeaders)(response.headers)];
|
|
174
|
-
case 2:
|
|
175
|
-
_a = _b.sent();
|
|
176
|
-
return [2 /*return*/, null];
|
|
177
|
-
case 3: return [2 /*return*/];
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
};
|
|
182
|
-
// Backward-compatible convenience methods (delegates to servers operations)
|
|
183
|
-
HetznerClient.prototype.listServers = function () {
|
|
184
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
185
|
-
return __generator(this, function (_a) {
|
|
186
|
-
return [2 /*return*/, this.servers.list()];
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
};
|
|
190
|
-
HetznerClient.prototype.getServer = function (id) {
|
|
191
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
192
|
-
return __generator(this, function (_a) {
|
|
193
|
-
return [2 /*return*/, this.servers.get(id)];
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
};
|
|
197
|
-
HetznerClient.prototype.createServer = function (options) {
|
|
198
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
199
|
-
return __generator(this, function (_a) {
|
|
200
|
-
return [2 /*return*/, this.servers.create(options)];
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
};
|
|
204
|
-
HetznerClient.prototype.deleteServer = function (id) {
|
|
205
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
206
|
-
return __generator(this, function (_a) {
|
|
207
|
-
return [2 /*return*/, this.servers.delete(id)];
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
};
|
|
211
|
-
HetznerClient.prototype.powerOn = function (id) {
|
|
212
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
213
|
-
return __generator(this, function (_a) {
|
|
214
|
-
return [2 /*return*/, this.servers.powerOn(id)];
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
};
|
|
218
|
-
HetznerClient.prototype.powerOff = function (id) {
|
|
219
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
220
|
-
return __generator(this, function (_a) {
|
|
221
|
-
return [2 /*return*/, this.servers.powerOff(id)];
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
};
|
|
225
|
-
HetznerClient.prototype.reboot = function (id) {
|
|
226
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
227
|
-
return __generator(this, function (_a) {
|
|
228
|
-
return [2 /*return*/, this.servers.reboot(id)];
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
};
|
|
232
|
-
return HetznerClient;
|
|
233
|
-
}());
|
|
234
|
-
exports.HetznerClient = HetznerClient;
|
package/client.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hetzner Cloud API client
|
|
3
|
-
* For server-side use only (requires API token)
|
|
4
|
-
*
|
|
5
|
-
* TODO: RE-REVIEW https://docs.hetzner.cloud/reference/cloud#authentication
|
|
6
|
-
* - https://tailscale.com/kb/1150/cloud-hetzner
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// Explicitly import fetch for Bun compatibility
|
|
10
|
-
import { fetch as bunFetch } from "bun";
|
|
11
|
-
import { z } from "zod";
|
|
12
|
-
import { HETZNER_API_BASE } from "./config.js";
|
|
13
|
-
|
|
14
|
-
// Use Bun's fetch if available, otherwise try global fetch
|
|
15
|
-
const fetch = bunFetch || (globalThis as any).fetch;
|
|
16
|
-
import { resolveApiToken, getTokenFromCLI, isAuthenticated } from "./auth.js";
|
|
17
|
-
import { ServerOperations } from "./servers.js";
|
|
18
|
-
import { ActionOperations } from "./actions.js";
|
|
19
|
-
import { PricingOperations } from "./pricing.js";
|
|
20
|
-
import { SSHKeyOperations } from "./ssh-keys.js";
|
|
21
|
-
import { VolumeOperations } from "./volumes.js";
|
|
22
|
-
import {
|
|
23
|
-
HetznerListServersResponseSchema,
|
|
24
|
-
HetznerGetServerResponseSchema,
|
|
25
|
-
HetznerCreateServerResponseSchema,
|
|
26
|
-
} from "./schemas.js";
|
|
27
|
-
import {
|
|
28
|
-
createHetznerError,
|
|
29
|
-
isRateLimitError,
|
|
30
|
-
} from "./errors.js";
|
|
31
|
-
import {
|
|
32
|
-
parseRateLimitHeaders,
|
|
33
|
-
waitForRateLimitReset,
|
|
34
|
-
} from "./actions.js";
|
|
35
|
-
import type { RateLimitInfo } from "./types.js";
|
|
36
|
-
|
|
37
|
-
export class HetznerClient {
|
|
38
|
-
private apiToken: string;
|
|
39
|
-
|
|
40
|
-
constructor(apiToken?: string) {
|
|
41
|
-
this.apiToken = resolveApiToken(apiToken);
|
|
42
|
-
|
|
43
|
-
// If no token from env or explicit, try CLI config
|
|
44
|
-
if (!this.apiToken) {
|
|
45
|
-
this.apiToken = getTokenFromCLI();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get isAuthenticated(): boolean {
|
|
50
|
-
return isAuthenticated(this.apiToken);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Make a request to the Hetzner Cloud API
|
|
55
|
-
*
|
|
56
|
-
* @param endpoint - API endpoint (e.g., "/servers")
|
|
57
|
-
* @param options - RequestInit options
|
|
58
|
-
* @returns Parsed JSON response
|
|
59
|
-
* @throws {HetznerAPIError} On API errors
|
|
60
|
-
*/
|
|
61
|
-
async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
|
62
|
-
const response = await fetch(`${HETZNER_API_BASE}${endpoint}`, {
|
|
63
|
-
...options,
|
|
64
|
-
headers: {
|
|
65
|
-
Authorization: `Bearer ${this.apiToken}`,
|
|
66
|
-
"Content-Type": "application/json",
|
|
67
|
-
...options.headers,
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Parse rate limit headers
|
|
72
|
-
const rateLimit = parseRateLimitHeaders(response.headers);
|
|
73
|
-
this.handleRateLimit(rateLimit);
|
|
74
|
-
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
const body = await response.json().catch(() => ({}));
|
|
77
|
-
throw createHetznerError(response.status, body);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const data = await response.json();
|
|
81
|
-
return data as T;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Validate Hetzner API response with Zod schema
|
|
86
|
-
*
|
|
87
|
-
* @param schema - Zod schema to validate against
|
|
88
|
-
* @param data - Data to validate
|
|
89
|
-
* @returns Validated data
|
|
90
|
-
*/
|
|
91
|
-
private validateResponse<T>(schema: z.ZodType<T>, data: unknown): T {
|
|
92
|
-
const result = schema.safeParse(data);
|
|
93
|
-
if (result.success) {
|
|
94
|
-
return result.data;
|
|
95
|
-
}
|
|
96
|
-
// Log validation errors but don't throw to maintain backward compatibility
|
|
97
|
-
console.warn(
|
|
98
|
-
"Hetzner API response validation warning:",
|
|
99
|
-
result.error.issues
|
|
100
|
-
);
|
|
101
|
-
return data as T;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Handle rate limit information from response headers
|
|
106
|
-
*
|
|
107
|
-
* @param rateLimit - Rate limit info from response
|
|
108
|
-
*/
|
|
109
|
-
private handleRateLimit(rateLimit: RateLimitInfo | null): void {
|
|
110
|
-
if (!rateLimit) return;
|
|
111
|
-
|
|
112
|
-
// Warn if rate limit is low
|
|
113
|
-
if (rateLimit.remaining < 100) {
|
|
114
|
-
console.warn(
|
|
115
|
-
`[Hetzner API] Rate limit low: ${rateLimit.remaining}/${rateLimit.limit} remaining. Resets at ${new Date(rateLimit.reset * 1000).toISOString()}`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Get current rate limit information
|
|
122
|
-
*
|
|
123
|
-
* Makes a lightweight request to check rate limit status
|
|
124
|
-
*
|
|
125
|
-
* @returns Rate limit info or null if not available
|
|
126
|
-
*/
|
|
127
|
-
async getRateLimit(): Promise<RateLimitInfo | null> {
|
|
128
|
-
try {
|
|
129
|
-
const response = await fetch(`${HETZNER_API_BASE}/servers`, {
|
|
130
|
-
headers: {
|
|
131
|
-
Authorization: `Bearer ${this.apiToken}`,
|
|
132
|
-
},
|
|
133
|
-
});
|
|
134
|
-
return parseRateLimitHeaders(response.headers);
|
|
135
|
-
} catch {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
readonly servers = new ServerOperations(this);
|
|
141
|
-
readonly actions = new ActionOperations(this);
|
|
142
|
-
readonly pricing = new PricingOperations(this);
|
|
143
|
-
readonly ssh_keys = new SSHKeyOperations(this);
|
|
144
|
-
readonly volumes = new VolumeOperations(this);
|
|
145
|
-
|
|
146
|
-
// Backward-compatible convenience methods (delegates to servers operations)
|
|
147
|
-
async listServers() {
|
|
148
|
-
return this.servers.list();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async getServer(id: number) {
|
|
152
|
-
return this.servers.get(id);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async createServer(options: import("./types.js").CreateServerOptions) {
|
|
156
|
-
return this.servers.create(options);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async deleteServer(id: number) {
|
|
160
|
-
return this.servers.delete(id);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async powerOn(id: number) {
|
|
164
|
-
return this.servers.powerOn(id);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async powerOff(id: number) {
|
|
168
|
-
return this.servers.powerOff(id);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async reboot(id: number) {
|
|
172
|
-
return this.servers.reboot(id);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Re-export types for convenience
|
|
177
|
-
export type * from "./types.js";
|
package/config.js
DELETED