virtualizorjs 2.1.3 → 2.2.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/README.md CHANGED
@@ -6,9 +6,6 @@
6
6
 
7
7
  A **TypeScript-first** SDK for the [Virtualizor](https://www.virtualizor.com/) server management API. Manage VPS instances, users, and plans with a clean, namespaced interface and zero production dependencies.
8
8
 
9
- > [!IMPORTANT]
10
- > Since the Virtualizor API documentation is a mess (at least for me), I need help from YOU to report bugs, missing features or just to tell me that something is not clear. You can do that by opening an issue or a pull request.
11
-
12
9
  ## Installation
13
10
 
14
11
  **npm:**
@@ -29,12 +26,12 @@ bun add virtualizorjs
29
26
  import { createVirtualizorClient } from 'virtualizorjs';
30
27
 
31
28
  const client = createVirtualizorClient({
32
- host: 'virtualizor.example.com',
33
- apiKey: 'your-api-key',
34
- apiPass: 'your-api-pass',
35
- // Optional: port (default 4085), https (default true),
36
- // rejectUnauthorized (default false), timeout (default 30000ms)
37
- // 4085 for Https, 4084 for Http
29
+ host: process.env.VIRTUALIZOR_HOST!,
30
+ apiKey: process.env.VIRTUALIZOR_API_KEY!,
31
+ apiPass: process.env.VIRTUALIZOR_API_PASS!,
32
+ // Optional: port (default 4085), https (default true),
33
+ // rejectUnauthorized (default false), timeout (default 30000ms)
34
+ // Ports: 4085 (HTTPS), 4084 (HTTP)
38
35
  });
39
36
  ```
40
37
 
@@ -83,8 +80,8 @@ try {
83
80
 
84
81
  | Method | Parameters | Returns | Notes |
85
82
  |--------|-----------|---------|-------|
86
- | `list()` | | `Record<string, VPS>` | List all VPS |
87
- | `get(vpsId)` | `vpsId: string` | `VPS` | Get a single VPS |
83
+ | `list(filters?)` | `filters: ListVPSParams` | `Record<string, VPS>` | List all VPS with optional filters |
84
+ | `get(filters)` | `filters: ListVPSParams` | `VPS` | Get a single VPS with filters |
88
85
  | `create(params)` | `CreateVPSParams` | `AsyncTaskResult` | Async |
89
86
  | `delete(vpsId)` | `vpsId: string` | `AsyncTaskResult` | Async |
90
87
  | `start(vpsId)` | `vpsId: string` | `AsyncTaskResult` | Async |
@@ -173,16 +170,20 @@ All resources are fully typed. Import types as needed:
173
170
  ```typescript
174
171
  import type {
175
172
  VPS,
173
+ ListVPSParams,
176
174
  CreateVPSParams,
177
175
  RebuildVPSParams,
178
176
  CloneVPSParams,
179
177
  MigrateVPSParams,
178
+ VirtType,
180
179
  User,
181
180
  CreateUserParams,
182
181
  Plan,
183
182
  CreatePlanParams,
184
183
  Task,
185
184
  AsyncTaskResult,
185
+ VirtualizorConfig,
186
+ IpsInput,
186
187
  } from 'virtualizorjs';
187
188
  ```
188
189
 
package/dist/index.d.mts CHANGED
@@ -1,3 +1,73 @@
1
+ declare class VirtualizorApiError extends Error {
2
+ readonly code: number;
3
+ readonly details: Record<string, unknown> | undefined;
4
+ constructor(message: string, code: number, details?: Record<string, unknown>);
5
+ format(): string;
6
+ }
7
+
8
+ interface Logger {
9
+ debug(message: string, ...args: unknown[]): void;
10
+ info(message: string, ...args: unknown[]): void;
11
+ warn(message: string, ...args: unknown[]): void;
12
+ error(message: string, error?: Error): void;
13
+ success?(message: string, ...args: unknown[]): void;
14
+ }
15
+
16
+ declare class ConsoleLogger implements Logger {
17
+ private readonly prefix;
18
+ constructor(prefix?: string);
19
+ private timestamp;
20
+ private tag;
21
+ debug(message: string, ...args: unknown[]): void;
22
+ info(message: string, ...args: unknown[]): void;
23
+ warn(message: string, ...args: unknown[]): void;
24
+ error(message: string, error?: Error): void;
25
+ success(message: string, ...args: unknown[]): void;
26
+ }
27
+ declare const defaultLogger: ConsoleLogger;
28
+
29
+ declare const colors: {
30
+ red: (str: string) => string;
31
+ green: (str: string) => string;
32
+ yellow: (str: string) => string;
33
+ blue: (str: string) => string;
34
+ magenta: (str: string) => string;
35
+ cyan: (str: string) => string;
36
+ white: (str: string) => string;
37
+ gray: (str: string) => string;
38
+ dim: (str: string) => string;
39
+ bold: (str: string) => string;
40
+ underline: (str: string) => string;
41
+ bgRed: (str: string) => string;
42
+ bgGreen: (str: string) => string;
43
+ bgYellow: (str: string) => string;
44
+ bgBlue: (str: string) => string;
45
+ bgCyan: (str: string) => string;
46
+ };
47
+ declare const symbols: {
48
+ success: string;
49
+ error: string;
50
+ warning: string;
51
+ info: string;
52
+ bullet: string;
53
+ arrow: string;
54
+ chevron: string;
55
+ pointer: string;
56
+ star: string;
57
+ };
58
+
59
+ interface BoxOptions {
60
+ title?: string;
61
+ borderColor?: 'cyan' | 'yellow' | 'red' | 'green' | 'blue' | 'magenta';
62
+ padding?: number;
63
+ margin?: number;
64
+ }
65
+ declare function createBox(content: string, options?: BoxOptions): string;
66
+ declare function createUpdateBox(current: string, latest: string): string;
67
+ declare function createErrorBox(title: string, message: string, hint?: string): string;
68
+
69
+ declare function formatError(error: Error, verbose?: boolean): string;
70
+
1
71
  interface VirtualizorError {
2
72
  code: number;
3
73
  msg: string;
@@ -24,6 +94,8 @@ interface VirtualizorConfig {
24
94
  rejectUnauthorized?: boolean;
25
95
  timeout?: number;
26
96
  debug?: boolean;
97
+ logger?: Logger;
98
+ disableUpdateCheck?: boolean;
27
99
  }
28
100
  interface ResolvedConfig {
29
101
  host: string;
@@ -34,17 +106,19 @@ interface ResolvedConfig {
34
106
  rejectUnauthorized: boolean;
35
107
  timeout: number;
36
108
  debug: boolean;
109
+ logger: Logger;
110
+ disableUpdateCheck: boolean;
37
111
  }
38
112
 
39
- declare class VirtualizorApiError extends Error {
40
- readonly code: number;
41
- constructor(message: string, code: number);
42
- }
43
113
  declare class HttpClient {
44
114
  private readonly config;
115
+ private readonly agent;
116
+ private readonly logger;
45
117
  constructor(config: ResolvedConfig);
46
118
  parseResponse<T extends VirtualizorResponse>(data: T): T;
47
119
  request<T extends VirtualizorResponse>(act: string, queryParams?: ApiParams, bodyParams?: ApiParams): Promise<T>;
120
+ private validateJsonDepth;
121
+ destroy(): void;
48
122
  private rawRequest;
49
123
  }
50
124
 
@@ -352,7 +426,7 @@ declare class VpsResource {
352
426
  private readonly http;
353
427
  constructor(http: HttpClient);
354
428
  list(filters?: ListVPSParams): Promise<Record<string, VPS>>;
355
- get(vpsId: string): Promise<VPS>;
429
+ get(filters: ListVPSParams): Promise<VPS>;
356
430
  create(params: CreateVPSParams): Promise<AsyncTaskResult>;
357
431
  delete(vpsId: string): Promise<AsyncTaskResult>;
358
432
  start(vpsId: string): Promise<AsyncTaskResult>;
@@ -374,6 +448,7 @@ declare class VirtualizorClient {
374
448
  readonly users: UsersResource;
375
449
  readonly plans: PlansResource;
376
450
  readonly tasks: TasksResource;
451
+ readonly logger: Logger;
377
452
  constructor(config: VirtualizorConfig);
378
453
  }
379
454
  declare function createVirtualizorClient(config: VirtualizorConfig): VirtualizorClient;
@@ -399,4 +474,4 @@ declare function formatIps(ips: IpsInput, options: FormatIpsOptions & {
399
474
  as: 'string';
400
475
  }): string;
401
476
 
402
- export { type AsyncTaskResult, type CloneVPSParams, type CreatePlanParams, type CreateUserParams, type CreateVPSParams, type IpsInput, type ListVPSParams, type MigrateVPSParams, type Plan, type RebuildVPSParams, type Task, type User, type VPS, type VirtType, VirtualizorApiError, VirtualizorClient, type VirtualizorConfig, createVirtualizorClient, formatIps };
477
+ export { type AsyncTaskResult, type CloneVPSParams, ConsoleLogger, type CreatePlanParams, type CreateUserParams, type CreateVPSParams, type IpsInput, type ListVPSParams, type Logger, type MigrateVPSParams, type Plan, type RebuildVPSParams, type Task, type User, type VPS, type VirtType, VirtualizorApiError, VirtualizorClient, type VirtualizorConfig, colors, createBox, createErrorBox, createUpdateBox, createVirtualizorClient, defaultLogger, formatError, formatIps, symbols };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,73 @@
1
+ declare class VirtualizorApiError extends Error {
2
+ readonly code: number;
3
+ readonly details: Record<string, unknown> | undefined;
4
+ constructor(message: string, code: number, details?: Record<string, unknown>);
5
+ format(): string;
6
+ }
7
+
8
+ interface Logger {
9
+ debug(message: string, ...args: unknown[]): void;
10
+ info(message: string, ...args: unknown[]): void;
11
+ warn(message: string, ...args: unknown[]): void;
12
+ error(message: string, error?: Error): void;
13
+ success?(message: string, ...args: unknown[]): void;
14
+ }
15
+
16
+ declare class ConsoleLogger implements Logger {
17
+ private readonly prefix;
18
+ constructor(prefix?: string);
19
+ private timestamp;
20
+ private tag;
21
+ debug(message: string, ...args: unknown[]): void;
22
+ info(message: string, ...args: unknown[]): void;
23
+ warn(message: string, ...args: unknown[]): void;
24
+ error(message: string, error?: Error): void;
25
+ success(message: string, ...args: unknown[]): void;
26
+ }
27
+ declare const defaultLogger: ConsoleLogger;
28
+
29
+ declare const colors: {
30
+ red: (str: string) => string;
31
+ green: (str: string) => string;
32
+ yellow: (str: string) => string;
33
+ blue: (str: string) => string;
34
+ magenta: (str: string) => string;
35
+ cyan: (str: string) => string;
36
+ white: (str: string) => string;
37
+ gray: (str: string) => string;
38
+ dim: (str: string) => string;
39
+ bold: (str: string) => string;
40
+ underline: (str: string) => string;
41
+ bgRed: (str: string) => string;
42
+ bgGreen: (str: string) => string;
43
+ bgYellow: (str: string) => string;
44
+ bgBlue: (str: string) => string;
45
+ bgCyan: (str: string) => string;
46
+ };
47
+ declare const symbols: {
48
+ success: string;
49
+ error: string;
50
+ warning: string;
51
+ info: string;
52
+ bullet: string;
53
+ arrow: string;
54
+ chevron: string;
55
+ pointer: string;
56
+ star: string;
57
+ };
58
+
59
+ interface BoxOptions {
60
+ title?: string;
61
+ borderColor?: 'cyan' | 'yellow' | 'red' | 'green' | 'blue' | 'magenta';
62
+ padding?: number;
63
+ margin?: number;
64
+ }
65
+ declare function createBox(content: string, options?: BoxOptions): string;
66
+ declare function createUpdateBox(current: string, latest: string): string;
67
+ declare function createErrorBox(title: string, message: string, hint?: string): string;
68
+
69
+ declare function formatError(error: Error, verbose?: boolean): string;
70
+
1
71
  interface VirtualizorError {
2
72
  code: number;
3
73
  msg: string;
@@ -24,6 +94,8 @@ interface VirtualizorConfig {
24
94
  rejectUnauthorized?: boolean;
25
95
  timeout?: number;
26
96
  debug?: boolean;
97
+ logger?: Logger;
98
+ disableUpdateCheck?: boolean;
27
99
  }
28
100
  interface ResolvedConfig {
29
101
  host: string;
@@ -34,17 +106,19 @@ interface ResolvedConfig {
34
106
  rejectUnauthorized: boolean;
35
107
  timeout: number;
36
108
  debug: boolean;
109
+ logger: Logger;
110
+ disableUpdateCheck: boolean;
37
111
  }
38
112
 
39
- declare class VirtualizorApiError extends Error {
40
- readonly code: number;
41
- constructor(message: string, code: number);
42
- }
43
113
  declare class HttpClient {
44
114
  private readonly config;
115
+ private readonly agent;
116
+ private readonly logger;
45
117
  constructor(config: ResolvedConfig);
46
118
  parseResponse<T extends VirtualizorResponse>(data: T): T;
47
119
  request<T extends VirtualizorResponse>(act: string, queryParams?: ApiParams, bodyParams?: ApiParams): Promise<T>;
120
+ private validateJsonDepth;
121
+ destroy(): void;
48
122
  private rawRequest;
49
123
  }
50
124
 
@@ -352,7 +426,7 @@ declare class VpsResource {
352
426
  private readonly http;
353
427
  constructor(http: HttpClient);
354
428
  list(filters?: ListVPSParams): Promise<Record<string, VPS>>;
355
- get(vpsId: string): Promise<VPS>;
429
+ get(filters: ListVPSParams): Promise<VPS>;
356
430
  create(params: CreateVPSParams): Promise<AsyncTaskResult>;
357
431
  delete(vpsId: string): Promise<AsyncTaskResult>;
358
432
  start(vpsId: string): Promise<AsyncTaskResult>;
@@ -374,6 +448,7 @@ declare class VirtualizorClient {
374
448
  readonly users: UsersResource;
375
449
  readonly plans: PlansResource;
376
450
  readonly tasks: TasksResource;
451
+ readonly logger: Logger;
377
452
  constructor(config: VirtualizorConfig);
378
453
  }
379
454
  declare function createVirtualizorClient(config: VirtualizorConfig): VirtualizorClient;
@@ -399,4 +474,4 @@ declare function formatIps(ips: IpsInput, options: FormatIpsOptions & {
399
474
  as: 'string';
400
475
  }): string;
401
476
 
402
- export { type AsyncTaskResult, type CloneVPSParams, type CreatePlanParams, type CreateUserParams, type CreateVPSParams, type IpsInput, type ListVPSParams, type MigrateVPSParams, type Plan, type RebuildVPSParams, type Task, type User, type VPS, type VirtType, VirtualizorApiError, VirtualizorClient, type VirtualizorConfig, createVirtualizorClient, formatIps };
477
+ export { type AsyncTaskResult, type CloneVPSParams, ConsoleLogger, type CreatePlanParams, type CreateUserParams, type CreateVPSParams, type IpsInput, type ListVPSParams, type Logger, type MigrateVPSParams, type Plan, type RebuildVPSParams, type Task, type User, type VPS, type VirtType, VirtualizorApiError, VirtualizorClient, type VirtualizorConfig, colors, createBox, createErrorBox, createUpdateBox, createVirtualizorClient, defaultLogger, formatError, formatIps, symbols };
package/dist/index.js CHANGED
@@ -1,346 +1,11 @@
1
- 'use strict';
2
-
3
- var http = require('http');
4
- var https = require('https');
5
-
6
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
-
8
- var http__default = /*#__PURE__*/_interopDefault(http);
9
- var https__default = /*#__PURE__*/_interopDefault(https);
10
-
11
- // src/config/defaults.ts
12
- var DEFAULT_CONFIG = {
13
- port: 4085,
14
- https: true,
15
- rejectUnauthorized: false,
16
- timeout: 3e4,
17
- debug: false
18
- };
19
- var DEFAULT_TASK_POLLING = {
20
- pollIntervalMs: 2e3,
21
- timeoutMs: 12e4
22
- };
23
-
24
- // src/auth.ts
25
- function buildQueryString(params, apiKey, apiPass) {
26
- const clean = {};
27
- for (const [key, value] of Object.entries(params)) {
28
- if (value !== void 0) {
29
- clean[key] = value;
30
- }
31
- }
32
- const urlParams = new URLSearchParams();
33
- urlParams.set("api", "json");
34
- urlParams.set("adminapikey", apiKey);
35
- urlParams.set("adminapipass", apiPass);
36
- for (const [key, value] of Object.entries(clean)) {
37
- urlParams.set(key, String(value));
38
- }
39
- return `?${urlParams.toString()}`;
40
- }
41
-
42
- // src/http.ts
43
- var VirtualizorApiError = class extends Error {
44
- code;
45
- constructor(message, code) {
46
- super(message);
47
- this.name = "VirtualizorApiError";
48
- this.code = code;
49
- }
50
- };
51
- var HttpClient = class {
52
- constructor(config) {
53
- this.config = config;
54
- }
55
- parseResponse(data) {
56
- if (data.error && data.error.length > 0) {
57
- const first = data.error[0];
58
- if (first) {
59
- throw new VirtualizorApiError(first.msg, first.code);
60
- }
61
- }
62
- return data;
63
- }
64
- async request(act, queryParams = {}, bodyParams = {}) {
65
- const allQueryParams = { act, ...queryParams };
66
- const qs = buildQueryString(allQueryParams, this.config.apiKey, this.config.apiPass);
67
- const path = `/index.php${qs}`;
68
- const bodyString = Object.entries(bodyParams).filter(([, v]) => v !== void 0).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
69
- const data = await this.rawRequest(path, bodyString || void 0);
70
- return this.parseResponse(data);
71
- }
72
- rawRequest(path, body) {
73
- const transport = this.config.https ? https__default.default : http__default.default;
74
- const options = {
75
- host: this.config.host,
76
- port: this.config.port,
77
- path,
78
- method: body ? "POST" : "GET",
79
- headers: {
80
- "Content-Type": "application/x-www-form-urlencoded",
81
- ...body ? { "Content-Length": Buffer.byteLength(body) } : {}
82
- },
83
- ...this.config.https ? { agent: new https__default.default.Agent({ rejectUnauthorized: this.config.rejectUnauthorized }) } : {}
84
- };
85
- return new Promise((resolve, reject) => {
86
- const req = transport.request(options, (res) => {
87
- let raw = "";
88
- res.on("data", (chunk) => {
89
- raw += chunk.toString();
90
- });
91
- res.on("end", () => {
92
- if (res.statusCode === 302 || res.statusCode === 301) {
93
- reject(
94
- new Error(
95
- `Redirect detected (status ${res.statusCode}). Authentication failed. Check your API credentials. Location: ${res.headers.location}`
96
- )
97
- );
98
- return;
99
- }
100
- try {
101
- resolve(JSON.parse(raw));
102
- } catch (err) {
103
- if (this.config.debug)
104
- console.debug("[Virtualizor] Raw response (first 500 chars):", raw.slice(0, 500));
105
- reject(
106
- new Error(
107
- `Failed to parse response: ${raw.slice(0, 200)}. Parse error: ${err instanceof Error ? err.message : String(err)}`
108
- )
109
- );
110
- }
111
- });
112
- });
113
- req.setTimeout(this.config.timeout, () => {
114
- req.destroy(new Error(`Request timed out after ${this.config.timeout}ms`));
115
- });
116
- req.on("error", reject);
117
- if (body) {
118
- req.write(body);
119
- }
120
- req.end();
121
- });
122
- }
123
- };
124
-
125
- // src/resources/plans.ts
126
- var PlansResource = class {
127
- constructor(http2) {
128
- this.http = http2;
129
- }
130
- async list() {
131
- const res = await this.http.request("plans", {}, {});
132
- return res.plans;
133
- }
134
- async create(params) {
135
- return this.http.request("addplan", {}, params);
136
- }
137
- async delete(planId) {
138
- return this.http.request("plans", {}, { delete: planId });
139
- }
140
- };
141
-
142
- // src/resources/tasks.ts
143
- var TasksResource = class {
144
- constructor(http2) {
145
- this.http = http2;
146
- }
147
- async get(taskId) {
148
- const res = await this.http.request("tasks", { taskid: taskId }, {});
149
- return res.tasks[taskId];
150
- }
151
- async wait(taskId, options = {}) {
152
- const {
153
- pollIntervalMs = DEFAULT_TASK_POLLING.pollIntervalMs,
154
- timeoutMs = DEFAULT_TASK_POLLING.timeoutMs
155
- } = options;
156
- const deadline = Date.now() + timeoutMs;
157
- while (Date.now() < deadline) {
158
- const task = await this.get(taskId);
159
- if (!task) throw new Error(`Task ${taskId} not found`);
160
- if (task.status === "1" || task.status === "done") return task;
161
- if (task.status === "error" || task.status === "-1") {
162
- throw new Error(`Task ${taskId} failed`);
163
- }
164
- await new Promise((r) => setTimeout(r, pollIntervalMs));
165
- }
166
- throw new Error(`Task ${taskId} timed out after ${timeoutMs}ms`);
167
- }
168
- };
169
-
170
- // src/resources/users.ts
171
- var UsersResource = class {
172
- constructor(http2) {
173
- this.http = http2;
174
- }
175
- async list() {
176
- const res = await this.http.request("users", {}, {});
177
- return res.users;
178
- }
179
- async create(params) {
180
- return this.http.request("adduser", {}, params);
181
- }
182
- async delete(uid) {
183
- return this.http.request("users", {}, { delete: uid });
184
- }
185
- async suspend(uid) {
186
- return this.http.request("users", {}, { suspend: uid });
187
- }
188
- async unsuspend(uid) {
189
- return this.http.request("users", {}, { unsuspend: uid });
190
- }
191
- };
192
-
193
- // src/constants/vps.ts
194
- var VPS_CONSTANTS = {
195
- // Rebuild operation requires reos=1 flag
196
- REBUILD_REOS_FLAG: 1,
197
- // Migrate operation requires migrate=1 flag
198
- MIGRATE_FLAG: 1,
199
- // Migrate operation requires migrate_but=1 flag
200
- MIGRATE_BUT_FLAG: 1
201
- };
202
-
203
- // src/resources/vps.ts
204
- var VpsResource = class {
205
- constructor(http2) {
206
- this.http = http2;
207
- }
208
- async list(filters = {}) {
209
- const res = await this.http.request("vs", {}, filters);
210
- return res.vs ?? {};
211
- }
212
- async get(vpsId) {
213
- const res = await this.http.request("vs", { vpsid: vpsId }, {});
214
- const vps = res.vs[vpsId];
215
- if (!vps) throw new Error(`VPS ${vpsId} not found in response`);
216
- return vps;
217
- }
218
- async create(params) {
219
- return this.http.request("addvs", {}, params);
220
- }
221
- async delete(vpsId) {
222
- return this.http.request("vs", { delete: vpsId }, {});
223
- }
224
- async start(vpsId) {
225
- return this.http.request("vs", { vpsid: vpsId, action: "start" }, {});
226
- }
227
- async stop(vpsId) {
228
- return this.http.request("vs", { vpsid: vpsId, action: "stop" }, {});
229
- }
230
- async restart(vpsId) {
231
- return this.http.request("vs", { vpsid: vpsId, action: "restart" }, {});
232
- }
233
- async poweroff(vpsId) {
234
- return this.http.request("vs", { vpsid: vpsId, action: "poweroff" }, {});
235
- }
236
- async suspend(vpsId) {
237
- return this.http.request("vs", { suspend: vpsId }, {});
238
- }
239
- async unsuspend(vpsId) {
240
- return this.http.request("vs", { unsuspend: vpsId }, {});
241
- }
242
- async rebuild(vpsId, params) {
243
- return this.http.request(
244
- "rebuild",
245
- {},
246
- {
247
- vpsid: vpsId,
248
- reos: VPS_CONSTANTS.REBUILD_REOS_FLAG,
249
- ...params
250
- }
251
- );
252
- }
253
- async clone(vpsId, params) {
254
- return this.http.request(
255
- "clone",
256
- {},
257
- {
258
- vpsid: vpsId,
259
- ...params
260
- }
261
- );
262
- }
263
- async migrate(vpsId, params) {
264
- return this.http.request(
265
- "migrate",
266
- {},
267
- {
268
- vpsid: vpsId,
269
- migrate: VPS_CONSTANTS.MIGRATE_FLAG,
270
- migrate_but: VPS_CONSTANTS.MIGRATE_BUT_FLAG,
271
- ...params
272
- }
273
- );
274
- }
275
- async status(vpsId) {
276
- return this.http.request("vstatus", { vpsid: vpsId }, {});
277
- }
278
- async vnc(vpsId) {
279
- return this.http.request("vnc", { vpsid: vpsId }, {});
280
- }
281
- async stats(vpsId) {
282
- return this.http.request("vps_stats", {}, { vpsid: vpsId });
283
- }
284
- };
285
-
286
- // src/client.ts
287
- var VirtualizorClient = class {
288
- vps;
289
- users;
290
- plans;
291
- tasks;
292
- constructor(config) {
293
- const resolved = {
294
- host: config.host,
295
- apiKey: config.apiKey,
296
- apiPass: config.apiPass ?? "",
297
- port: config.port ?? DEFAULT_CONFIG.port,
298
- https: config.https ?? DEFAULT_CONFIG.https,
299
- rejectUnauthorized: config.rejectUnauthorized ?? DEFAULT_CONFIG.rejectUnauthorized,
300
- timeout: config.timeout ?? DEFAULT_CONFIG.timeout,
301
- debug: config.debug ?? DEFAULT_CONFIG.debug
302
- };
303
- const http2 = new HttpClient(resolved);
304
- this.vps = new VpsResource(http2);
305
- this.users = new UsersResource(http2);
306
- this.plans = new PlansResource(http2);
307
- this.tasks = new TasksResource(http2);
308
- }
309
- };
310
- function createVirtualizorClient(config) {
311
- return new VirtualizorClient(config);
312
- }
313
-
314
- // src/utils/format-ips.ts
315
- function formatIps(ips, options) {
316
- const as = options?.as ?? "array";
317
- const separator = options?.separator ?? ", ";
318
- if (!ips) {
319
- return as === "array" ? [] : "";
320
- }
321
- let result = [];
322
- if (Array.isArray(ips)) {
323
- result = ips.filter(Boolean);
324
- } else if (typeof ips === "string") {
325
- const str = ips.trim();
326
- if (str === "") {
327
- result = [];
328
- } else if (str.includes(",")) {
329
- result = str.split(",").map((s) => s.trim()).filter(Boolean);
330
- } else if (/\s+/.test(str)) {
331
- result = str.split(/\s+/).map((s) => s.trim()).filter(Boolean);
332
- } else {
333
- result = [str];
334
- }
335
- } else if (typeof ips === "object") {
336
- result = Object.values(ips).filter(Boolean);
337
- }
338
- return as === "array" ? result : result.join(separator);
339
- }
340
-
341
- exports.VirtualizorApiError = VirtualizorApiError;
342
- exports.VirtualizorClient = VirtualizorClient;
343
- exports.createVirtualizorClient = createVirtualizorClient;
344
- exports.formatIps = formatIps;
345
- //# sourceMappingURL=index.js.map
346
- //# sourceMappingURL=index.js.map
1
+ 'use strict';var j=require('http'),U=require('https');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var j__default=/*#__PURE__*/_interopDefault(j);var U__default=/*#__PURE__*/_interopDefault(U);var F=(s,t)=>()=>(t||s((t={exports:{}}).exports,t),t.exports);var M=F(($t,Q)=>{Q.exports={name:"virtualizorjs",version:"2.2.1",description:"TypeScript SDK for the Virtualizor server management API. Create, start, stop, restart, rebuild, and manage VPS instances with a type-safe, developer-friendly client.",main:"./dist/index.js",module:"./dist/index.mjs",types:"./dist/index.d.ts",exports:{".":{import:{types:"./dist/index.d.mts",default:"./dist/index.mjs"},require:{types:"./dist/index.d.ts",default:"./dist/index.js"}}},scripts:{build:"tsup",dev:"tsup --watch",test:"bun test","test:watch":"bun test --watch",coverage:"bun test --coverage",typecheck:"tsc --noEmit",lint:"biome check src tests","lint:fix":"biome check --write src tests",format:"biome format --write src tests",release:"bun run build && bumpp",prepublishOnly:"bun run build && bun run typecheck","check-exports":"attw --pack .",prepare:"husky"},files:["dist","README.md","LICENSE"],keywords:["virtualizor","vps","sdk","api","typescript","nodejs","bun"],author:"kkMihai",license:"MIT",repository:{type:"git",url:"git+https://github.com/kkMihai/virtualizorjs.git"},bugs:{url:"https://github.com/kkMihai/virtualizorjs/issues"},homepage:"https://github.com/kkMihai/virtualizorjs#readme",engines:{bun:">=1.3.0"},devDependencies:{"@arethetypeswrong/cli":"^0.17.0","@biomejs/biome":"^1.9.0","@commitlint/cli":"^19.0.0","@commitlint/config-conventional":"^19.0.0","@types/bun":"latest",bumpp:"^9.0.0",husky:"^9.0.0",tsup:"^8.0.0",typescript:"^5.5.0"},trustedDependencies:["@biomejs/biome"]};});var P={port:4085,https:true,rejectUnauthorized:false,timeout:3e4,debug:false},I={pollIntervalMs:2e3,timeoutMs:12e4};var n=class extends Error{code;details;constructor(t,e,o){super(t),this.name="VirtualizorApiError",this.code=e,this.details=o;}format(){return `[API Error ${this.code}] ${this.message}`}};function $(s,t,e){let o={};for(let[p,i]of Object.entries(s))i!==void 0&&(o[p]=i);let r=new URLSearchParams;r.set("api","json"),r.set("adminapikey",t),r.set("adminapipass",e);for(let[p,i]of Object.entries(o))r.set(p,String(i));return `?${r.toString()}`}var q=5e3,v=class{constructor(t){this.config=t;let e=t.https?U__default.default.Agent:j__default.default.Agent;this.agent=new e({keepAlive:true,maxSockets:50,maxFreeSockets:10,scheduling:"lifo",...t.https?{rejectUnauthorized:t.rejectUnauthorized}:{}}),this.logger=t.logger;}agent;logger;parseResponse(t){if(t.error&&t.error.length>0){let e=t.error[0];if(e)throw new n(e.msg,e.code)}return t}async request(t,e={},o={}){let r={act:t,...e},p=$(r,this.config.apiKey,this.config.apiPass);if(this.config.debug){let c=p.replace(/adminapikey=[^&]*/,"adminapikey=[REDACTED]").replace(/adminapipass=[^&]*/,"adminapipass=[REDACTED]");this.logger.debug(`Request: act=${t} path=/index.php${c}`);}let i=`/index.php${p}`,m=Object.entries(o).filter(([,c])=>c!==void 0).map(([c,R])=>`${encodeURIComponent(c)}=${encodeURIComponent(String(R))}`).join("&");try{let c=await this.rawRequest(i,m||void 0);return this.parseResponse(c)}catch(c){throw this.config.debug&&(c instanceof n?this.logger.error(`[Virtualizor] \u25CF Error: [API Error ${c.code}] ${c.message}`):this.logger.error(`[Virtualizor] \u25CF Error: ${c.message}`)),c}}validateJsonDepth(t,e=0){if(e>100)throw new n("JSON depth limit exceeded",-32e3);if(typeof t=="object"&&t!==null)if(Array.isArray(t))for(let r of t)this.validateJsonDepth(r,e+1);else for(let r of Object.values(t))this.validateJsonDepth(r,e+1);}destroy(){this.agent.destroy();}rawRequest(t,e){let o=this.config.https?U__default.default:j__default.default,r={host:this.config.host,port:this.config.port,path:t,method:e?"POST":"GET",headers:{"Content-Type":"application/x-www-form-urlencoded",...e?{"Content-Length":Buffer.byteLength(e)}:{}},agent:this.agent};return new Promise((p,i)=>{let m=o.request(r,u=>{let T=[];u.on("data",f=>{T.push(f);}),u.on("end",()=>{let f=Buffer.concat(T).toString("utf8");if(u.statusCode===302||u.statusCode===301){i(new n(`Redirect detected (status ${u.statusCode}). Authentication failed. Location: ${u.headers.location}`,u.statusCode));return}try{let d=JSON.parse(f);this.validateJsonDepth(d),p(d);}catch(d){this.config.debug&&(d instanceof n?this.logger.error(`[Virtualizor] \u25CF Error: [API Error ${d.code}] ${d.message}`):this.logger.error(`[Virtualizor] \u25CF Error: ${d.message}`)),i(new n(`Failed to parse response: ${d.message??"Invalid JSON"}`,-32700));}}),u.on("error",f=>{this.config.debug&&this.logger.error("[Virtualizor] \u25CF Error: Response stream error",f),i(new n(`Response stream error: ${f.message??"Unknown error"}`,-32e3));});}),c=setTimeout(()=>{m.destroy(new n(`Connection timeout after ${q}ms`,-32e3));},q),R=setTimeout(()=>{m.destroy(new n(`Request timed out after ${this.config.timeout}ms`,-32e3));},this.config.timeout);m.once("socket",u=>{u.connecting?u.once("connect",()=>clearTimeout(c)):clearTimeout(c);}),m.once("close",()=>{clearTimeout(c),clearTimeout(R);}),m.on("error",u=>{u instanceof n?i(u):i(new n(`Request error ${u}`,-32e3));}),e&&m.write(e),m.end();})}};var A=process.platform==="win32",G=process.env.NO_COLOR===void 0&&process.stdout.isTTY;function l(s,t){return G?`\x1B[${s}m${t}\x1B[0m`:t}var a={red:s=>l(31,s),green:s=>l(32,s),yellow:s=>l(33,s),blue:s=>l(34,s),magenta:s=>l(35,s),cyan:s=>l(36,s),white:s=>l(37,s),gray:s=>l(90,s),dim:s=>l(2,s),bold:s=>l(1,s),underline:s=>l(4,s),bgRed:s=>l(41,s),bgGreen:s=>l(42,s),bgYellow:s=>l(43,s),bgBlue:s=>l(44,s),bgCyan:s=>l(46,s)},g={success:A?"\u221A":"\u2714",error:A?"\xD7":"\u2716",warning:A?"\u203C":"\u26A0",info:A?"i":"\u2139",bullet:"\u25CF",arrow:"\u2192",chevron:"\u203A",pointer:"\u276F",star:"\u2605"},h={topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502"};var k=class{constructor(t="Virtualizor"){this.prefix=t;}timestamp(){let e=new Date().toISOString().split("T")[1];return a.dim(e?e.slice(0,8):"00:00:00")}tag(){return a.cyan(`[${this.prefix}]`)}debug(t,...e){console.log(this.timestamp(),this.tag(),a.dim(g.bullet),a.dim(t),...e);}info(t,...e){console.log(this.timestamp(),this.tag(),a.blue(g.info),t,...e);}warn(t,...e){console.log(this.timestamp(),this.tag(),a.yellow(g.warning),a.yellow(t),...e);}error(t,e){console.error(this.timestamp(),this.tag(),a.red(g.error),a.red(t)),e?.stack&&console.error(a.dim(e.stack.split(`
2
+ `).slice(1,4).join(`
3
+ `)));}success(t,...e){console.log(this.timestamp(),this.tag(),a.green(g.success),a.green(t),...e);}},w=new k;function O(s,t={}){let{padding:e=1,margin:o=0,borderColor:r="cyan"}=t,p=s.split(`
4
+ `),m=Math.max(...p.map(y=>y.length))+e*2,c=a[r]??a.cyan,R=h.horizontal.repeat(m),u=`${h.topLeft}${R}${h.topRight}`,T=`${h.bottomLeft}${R}${h.bottomRight}`,f=p.map(y=>{let z=" ".repeat(e)+y+" ".repeat(e);return `${h.vertical}${z.padEnd(m)}${h.vertical}`}),d=[c(u),...f.map(y=>c(y)),c(T)].join(`
5
+ `);if(o>0){let y=" ".repeat(o);return d.split(`
6
+ `).map(z=>y+z).join(`
7
+ `)}return d}function b(s,t){let e=["\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","\u2551 \u{1F680} UPDATE AVAILABLE \u{1F680} \u2551","\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563","\u2551 \u2551",`\u2551 Current version: ${s.padEnd(18)} \u2551`,`\u2551 Latest version: ${t.padEnd(17)} \u2551`,"\u2551 \u2551","\u2551 To update, run: \u2551","\u2551 npm install virtualizorjs@latest \u2551","\u2551 \u2551","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"].join(`
8
+ `);return a.yellow(e)}function N(s,t,e){let o=["\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","\u2551 \u274C ERROR OCCURRED \u274C \u2551","\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563","\u2551 \u2551",`\u2551 ${s.padEnd(34)}\u2551`,"\u2551 \u2551",`\u2551 ${t.padEnd(34)}\u2551`,"\u2551 \u2551",e?`\u2551 \u{1F4A1} ${e.padEnd(29)}\u2551`:"",e?"\u2551 \u2551":"","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"].filter(r=>r!==void 0).join(`
9
+ `);return a.red(o)}function B(s,t=false){if(s instanceof n){let e=s.details&&t?`
10
+ ${a.dim(JSON.stringify(s.details,null,2))}`:"";return `${g.error} ${a.red(`[API Error ${s.code}]`)} ${s.message}${e}`}return `${g.error} ${a.red(s.message)}`}var x=class{constructor(t){this.http=t;}async list(){return (await this.http.request("plans",{},{})).plans}async create(t){return this.http.request("addplan",{},t)}async delete(t){return this.http.request("plans",{},{delete:t})}};var V=class{constructor(t){this.http=t;}async get(t){return (await this.http.request("tasks",{taskid:t},{})).tasks[t]}async wait(t,e={}){let{pollIntervalMs:o=I.pollIntervalMs,timeoutMs:r=I.timeoutMs}=e,p=Date.now()+r;for(;Date.now()<p;){let i=await this.get(t);if(!i)throw new n("Task not found",404);if(i.status==="1"||i.status==="done")return i;if(i.status==="error"||i.status==="-1")throw new n("Task failed",500);await new Promise(m=>setTimeout(m,o));}throw new n(`Task timed out after ${r}ms`,408)}};var C=class{constructor(t){this.http=t;}async list(){return (await this.http.request("users",{},{})).users}async create(t){return this.http.request("adduser",{},t)}async delete(t){return this.http.request("users",{},{delete:t})}async suspend(t){return this.http.request("users",{},{suspend:t})}async unsuspend(t){return this.http.request("users",{},{unsuspend:t})}};var E={REBUILD_REOS_FLAG:1,MIGRATE_FLAG:1,MIGRATE_BUT_FLAG:1};var S=class{constructor(t){this.http=t;}async list(t={}){return (await this.http.request("vs",{},t)).vs??{}}async get(t){let e=await this.http.request("vs",{},t),o=Object.entries(e.vs??{});if(o.length===0)throw new n("VPS not found",404);let r=o[0];if(!r)throw new n("VPS not found",404);let[,p]=r;return p}async create(t){return this.http.request("addvs",{},t)}async delete(t){return this.http.request("vs",{delete:t},{})}async start(t){return this.http.request("vs",{vpsid:t,action:"start"},{})}async stop(t){return this.http.request("vs",{vpsid:t,action:"stop"},{})}async restart(t){return this.http.request("vs",{vpsid:t,action:"restart"},{})}async poweroff(t){return this.http.request("vs",{vpsid:t,action:"poweroff"},{})}async suspend(t){return this.http.request("vs",{suspend:t},{})}async unsuspend(t){return this.http.request("vs",{unsuspend:t},{})}async rebuild(t,e){return this.http.request("rebuild",{},{vpsid:t,reos:E.REBUILD_REOS_FLAG,...e})}async clone(t,e){return this.http.request("clone",{},{vpsid:t,...e})}async migrate(t,e){return this.http.request("migrate",{},{vpsid:t,migrate:E.MIGRATE_FLAG,migrate_but:E.MIGRATE_BUT_FLAG,...e})}async status(t){return this.http.request("vstatus",{vpsid:t},{})}async vnc(t){return this.http.request("vnc",{vpsid:t},{})}async stats(t){return this.http.request("vps_stats",{},{vpsid:t})}};var H="https://registry.npmjs.org/virtualizorjs/latest";async function J(s){let t=new AbortController,e=setTimeout(()=>t.abort(),s);try{let o=await fetch(H,{signal:t.signal});if(!o.ok)throw new Error(`HTTP ${o.status}`);return await o.json()}finally{clearTimeout(e);}}function K(s,t){let e=s.split(".").map(Number),o=t.split(".").map(Number);return (o[0]??0)>(e[0]??0)||(o[0]??0)===(e[0]??0)&&(o[1]??0)>(e[1]??0)||(o[0]??0)===(e[0]??0)&&(o[1]??0)===(e[1]??0)&&(o[2]??0)>(e[2]??0)}var _=false;async function D(s,t,e){if(!(_&&true)){_=true;try{let r=(await J(e?.timeout??2e3)).version;if(!K(s,r))return;t.warn(`Update available: ${s} \u2192 ${r}`),console.log(),console.log(b(s,r)),console.log();}catch{}}}var W=M().version,L=class{vps;users;plans;tasks;logger;constructor(t){let e=t.logger??w;this.logger=e;let o={host:t.host,apiKey:t.apiKey,apiPass:t.apiPass??"",port:t.port??P.port,https:t.https??P.https,rejectUnauthorized:t.rejectUnauthorized??P.rejectUnauthorized,timeout:t.timeout??P.timeout,debug:t.debug??P.debug,logger:e,disableUpdateCheck:t.disableUpdateCheck??false},r=new v(o);this.vps=new S(r),this.users=new C(r),this.plans=new x(r),this.tasks=new V(r),o.disableUpdateCheck||D(W,e).catch(()=>{});}};function Y(s){return new L(s)}function X(s,t){let e=t?.as??"array",o=t?.separator??", ";if(!s)return e==="array"?[]:"";let r=[];if(Array.isArray(s))r=s.filter(Boolean);else if(typeof s=="string"){let p=s.trim();p===""?r=[]:p.includes(",")?r=p.split(",").map(i=>i.trim()).filter(Boolean):/\s+/.test(p)?r=p.split(/\s+/).map(i=>i.trim()).filter(Boolean):r=[p];}else typeof s=="object"&&(r=Object.values(s).filter(Boolean));return e==="array"?r:r.join(o)}
11
+ exports.ConsoleLogger=k;exports.VirtualizorApiError=n;exports.VirtualizorClient=L;exports.colors=a;exports.createBox=O;exports.createErrorBox=N;exports.createUpdateBox=b;exports.createVirtualizorClient=Y;exports.defaultLogger=w;exports.formatError=B;exports.formatIps=X;exports.symbols=g;
package/dist/index.mjs CHANGED
@@ -1,336 +1,11 @@
1
- import http from 'http';
2
- import https from 'https';
3
-
4
- // src/config/defaults.ts
5
- var DEFAULT_CONFIG = {
6
- port: 4085,
7
- https: true,
8
- rejectUnauthorized: false,
9
- timeout: 3e4,
10
- debug: false
11
- };
12
- var DEFAULT_TASK_POLLING = {
13
- pollIntervalMs: 2e3,
14
- timeoutMs: 12e4
15
- };
16
-
17
- // src/auth.ts
18
- function buildQueryString(params, apiKey, apiPass) {
19
- const clean = {};
20
- for (const [key, value] of Object.entries(params)) {
21
- if (value !== void 0) {
22
- clean[key] = value;
23
- }
24
- }
25
- const urlParams = new URLSearchParams();
26
- urlParams.set("api", "json");
27
- urlParams.set("adminapikey", apiKey);
28
- urlParams.set("adminapipass", apiPass);
29
- for (const [key, value] of Object.entries(clean)) {
30
- urlParams.set(key, String(value));
31
- }
32
- return `?${urlParams.toString()}`;
33
- }
34
-
35
- // src/http.ts
36
- var VirtualizorApiError = class extends Error {
37
- code;
38
- constructor(message, code) {
39
- super(message);
40
- this.name = "VirtualizorApiError";
41
- this.code = code;
42
- }
43
- };
44
- var HttpClient = class {
45
- constructor(config) {
46
- this.config = config;
47
- }
48
- parseResponse(data) {
49
- if (data.error && data.error.length > 0) {
50
- const first = data.error[0];
51
- if (first) {
52
- throw new VirtualizorApiError(first.msg, first.code);
53
- }
54
- }
55
- return data;
56
- }
57
- async request(act, queryParams = {}, bodyParams = {}) {
58
- const allQueryParams = { act, ...queryParams };
59
- const qs = buildQueryString(allQueryParams, this.config.apiKey, this.config.apiPass);
60
- const path = `/index.php${qs}`;
61
- const bodyString = Object.entries(bodyParams).filter(([, v]) => v !== void 0).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
62
- const data = await this.rawRequest(path, bodyString || void 0);
63
- return this.parseResponse(data);
64
- }
65
- rawRequest(path, body) {
66
- const transport = this.config.https ? https : http;
67
- const options = {
68
- host: this.config.host,
69
- port: this.config.port,
70
- path,
71
- method: body ? "POST" : "GET",
72
- headers: {
73
- "Content-Type": "application/x-www-form-urlencoded",
74
- ...body ? { "Content-Length": Buffer.byteLength(body) } : {}
75
- },
76
- ...this.config.https ? { agent: new https.Agent({ rejectUnauthorized: this.config.rejectUnauthorized }) } : {}
77
- };
78
- return new Promise((resolve, reject) => {
79
- const req = transport.request(options, (res) => {
80
- let raw = "";
81
- res.on("data", (chunk) => {
82
- raw += chunk.toString();
83
- });
84
- res.on("end", () => {
85
- if (res.statusCode === 302 || res.statusCode === 301) {
86
- reject(
87
- new Error(
88
- `Redirect detected (status ${res.statusCode}). Authentication failed. Check your API credentials. Location: ${res.headers.location}`
89
- )
90
- );
91
- return;
92
- }
93
- try {
94
- resolve(JSON.parse(raw));
95
- } catch (err) {
96
- if (this.config.debug)
97
- console.debug("[Virtualizor] Raw response (first 500 chars):", raw.slice(0, 500));
98
- reject(
99
- new Error(
100
- `Failed to parse response: ${raw.slice(0, 200)}. Parse error: ${err instanceof Error ? err.message : String(err)}`
101
- )
102
- );
103
- }
104
- });
105
- });
106
- req.setTimeout(this.config.timeout, () => {
107
- req.destroy(new Error(`Request timed out after ${this.config.timeout}ms`));
108
- });
109
- req.on("error", reject);
110
- if (body) {
111
- req.write(body);
112
- }
113
- req.end();
114
- });
115
- }
116
- };
117
-
118
- // src/resources/plans.ts
119
- var PlansResource = class {
120
- constructor(http2) {
121
- this.http = http2;
122
- }
123
- async list() {
124
- const res = await this.http.request("plans", {}, {});
125
- return res.plans;
126
- }
127
- async create(params) {
128
- return this.http.request("addplan", {}, params);
129
- }
130
- async delete(planId) {
131
- return this.http.request("plans", {}, { delete: planId });
132
- }
133
- };
134
-
135
- // src/resources/tasks.ts
136
- var TasksResource = class {
137
- constructor(http2) {
138
- this.http = http2;
139
- }
140
- async get(taskId) {
141
- const res = await this.http.request("tasks", { taskid: taskId }, {});
142
- return res.tasks[taskId];
143
- }
144
- async wait(taskId, options = {}) {
145
- const {
146
- pollIntervalMs = DEFAULT_TASK_POLLING.pollIntervalMs,
147
- timeoutMs = DEFAULT_TASK_POLLING.timeoutMs
148
- } = options;
149
- const deadline = Date.now() + timeoutMs;
150
- while (Date.now() < deadline) {
151
- const task = await this.get(taskId);
152
- if (!task) throw new Error(`Task ${taskId} not found`);
153
- if (task.status === "1" || task.status === "done") return task;
154
- if (task.status === "error" || task.status === "-1") {
155
- throw new Error(`Task ${taskId} failed`);
156
- }
157
- await new Promise((r) => setTimeout(r, pollIntervalMs));
158
- }
159
- throw new Error(`Task ${taskId} timed out after ${timeoutMs}ms`);
160
- }
161
- };
162
-
163
- // src/resources/users.ts
164
- var UsersResource = class {
165
- constructor(http2) {
166
- this.http = http2;
167
- }
168
- async list() {
169
- const res = await this.http.request("users", {}, {});
170
- return res.users;
171
- }
172
- async create(params) {
173
- return this.http.request("adduser", {}, params);
174
- }
175
- async delete(uid) {
176
- return this.http.request("users", {}, { delete: uid });
177
- }
178
- async suspend(uid) {
179
- return this.http.request("users", {}, { suspend: uid });
180
- }
181
- async unsuspend(uid) {
182
- return this.http.request("users", {}, { unsuspend: uid });
183
- }
184
- };
185
-
186
- // src/constants/vps.ts
187
- var VPS_CONSTANTS = {
188
- // Rebuild operation requires reos=1 flag
189
- REBUILD_REOS_FLAG: 1,
190
- // Migrate operation requires migrate=1 flag
191
- MIGRATE_FLAG: 1,
192
- // Migrate operation requires migrate_but=1 flag
193
- MIGRATE_BUT_FLAG: 1
194
- };
195
-
196
- // src/resources/vps.ts
197
- var VpsResource = class {
198
- constructor(http2) {
199
- this.http = http2;
200
- }
201
- async list(filters = {}) {
202
- const res = await this.http.request("vs", {}, filters);
203
- return res.vs ?? {};
204
- }
205
- async get(vpsId) {
206
- const res = await this.http.request("vs", { vpsid: vpsId }, {});
207
- const vps = res.vs[vpsId];
208
- if (!vps) throw new Error(`VPS ${vpsId} not found in response`);
209
- return vps;
210
- }
211
- async create(params) {
212
- return this.http.request("addvs", {}, params);
213
- }
214
- async delete(vpsId) {
215
- return this.http.request("vs", { delete: vpsId }, {});
216
- }
217
- async start(vpsId) {
218
- return this.http.request("vs", { vpsid: vpsId, action: "start" }, {});
219
- }
220
- async stop(vpsId) {
221
- return this.http.request("vs", { vpsid: vpsId, action: "stop" }, {});
222
- }
223
- async restart(vpsId) {
224
- return this.http.request("vs", { vpsid: vpsId, action: "restart" }, {});
225
- }
226
- async poweroff(vpsId) {
227
- return this.http.request("vs", { vpsid: vpsId, action: "poweroff" }, {});
228
- }
229
- async suspend(vpsId) {
230
- return this.http.request("vs", { suspend: vpsId }, {});
231
- }
232
- async unsuspend(vpsId) {
233
- return this.http.request("vs", { unsuspend: vpsId }, {});
234
- }
235
- async rebuild(vpsId, params) {
236
- return this.http.request(
237
- "rebuild",
238
- {},
239
- {
240
- vpsid: vpsId,
241
- reos: VPS_CONSTANTS.REBUILD_REOS_FLAG,
242
- ...params
243
- }
244
- );
245
- }
246
- async clone(vpsId, params) {
247
- return this.http.request(
248
- "clone",
249
- {},
250
- {
251
- vpsid: vpsId,
252
- ...params
253
- }
254
- );
255
- }
256
- async migrate(vpsId, params) {
257
- return this.http.request(
258
- "migrate",
259
- {},
260
- {
261
- vpsid: vpsId,
262
- migrate: VPS_CONSTANTS.MIGRATE_FLAG,
263
- migrate_but: VPS_CONSTANTS.MIGRATE_BUT_FLAG,
264
- ...params
265
- }
266
- );
267
- }
268
- async status(vpsId) {
269
- return this.http.request("vstatus", { vpsid: vpsId }, {});
270
- }
271
- async vnc(vpsId) {
272
- return this.http.request("vnc", { vpsid: vpsId }, {});
273
- }
274
- async stats(vpsId) {
275
- return this.http.request("vps_stats", {}, { vpsid: vpsId });
276
- }
277
- };
278
-
279
- // src/client.ts
280
- var VirtualizorClient = class {
281
- vps;
282
- users;
283
- plans;
284
- tasks;
285
- constructor(config) {
286
- const resolved = {
287
- host: config.host,
288
- apiKey: config.apiKey,
289
- apiPass: config.apiPass ?? "",
290
- port: config.port ?? DEFAULT_CONFIG.port,
291
- https: config.https ?? DEFAULT_CONFIG.https,
292
- rejectUnauthorized: config.rejectUnauthorized ?? DEFAULT_CONFIG.rejectUnauthorized,
293
- timeout: config.timeout ?? DEFAULT_CONFIG.timeout,
294
- debug: config.debug ?? DEFAULT_CONFIG.debug
295
- };
296
- const http2 = new HttpClient(resolved);
297
- this.vps = new VpsResource(http2);
298
- this.users = new UsersResource(http2);
299
- this.plans = new PlansResource(http2);
300
- this.tasks = new TasksResource(http2);
301
- }
302
- };
303
- function createVirtualizorClient(config) {
304
- return new VirtualizorClient(config);
305
- }
306
-
307
- // src/utils/format-ips.ts
308
- function formatIps(ips, options) {
309
- const as = options?.as ?? "array";
310
- const separator = options?.separator ?? ", ";
311
- if (!ips) {
312
- return as === "array" ? [] : "";
313
- }
314
- let result = [];
315
- if (Array.isArray(ips)) {
316
- result = ips.filter(Boolean);
317
- } else if (typeof ips === "string") {
318
- const str = ips.trim();
319
- if (str === "") {
320
- result = [];
321
- } else if (str.includes(",")) {
322
- result = str.split(",").map((s) => s.trim()).filter(Boolean);
323
- } else if (/\s+/.test(str)) {
324
- result = str.split(/\s+/).map((s) => s.trim()).filter(Boolean);
325
- } else {
326
- result = [str];
327
- }
328
- } else if (typeof ips === "object") {
329
- result = Object.values(ips).filter(Boolean);
330
- }
331
- return as === "array" ? result : result.join(separator);
332
- }
333
-
334
- export { VirtualizorApiError, VirtualizorClient, createVirtualizorClient, formatIps };
335
- //# sourceMappingURL=index.mjs.map
336
- //# sourceMappingURL=index.mjs.map
1
+ import j from'http';import U from'https';var F=(s,t)=>()=>(t||s((t={exports:{}}).exports,t),t.exports);var M=F(($t,Q)=>{Q.exports={name:"virtualizorjs",version:"2.2.1",description:"TypeScript SDK for the Virtualizor server management API. Create, start, stop, restart, rebuild, and manage VPS instances with a type-safe, developer-friendly client.",main:"./dist/index.js",module:"./dist/index.mjs",types:"./dist/index.d.ts",exports:{".":{import:{types:"./dist/index.d.mts",default:"./dist/index.mjs"},require:{types:"./dist/index.d.ts",default:"./dist/index.js"}}},scripts:{build:"tsup",dev:"tsup --watch",test:"bun test","test:watch":"bun test --watch",coverage:"bun test --coverage",typecheck:"tsc --noEmit",lint:"biome check src tests","lint:fix":"biome check --write src tests",format:"biome format --write src tests",release:"bun run build && bumpp",prepublishOnly:"bun run build && bun run typecheck","check-exports":"attw --pack .",prepare:"husky"},files:["dist","README.md","LICENSE"],keywords:["virtualizor","vps","sdk","api","typescript","nodejs","bun"],author:"kkMihai",license:"MIT",repository:{type:"git",url:"git+https://github.com/kkMihai/virtualizorjs.git"},bugs:{url:"https://github.com/kkMihai/virtualizorjs/issues"},homepage:"https://github.com/kkMihai/virtualizorjs#readme",engines:{bun:">=1.3.0"},devDependencies:{"@arethetypeswrong/cli":"^0.17.0","@biomejs/biome":"^1.9.0","@commitlint/cli":"^19.0.0","@commitlint/config-conventional":"^19.0.0","@types/bun":"latest",bumpp:"^9.0.0",husky:"^9.0.0",tsup:"^8.0.0",typescript:"^5.5.0"},trustedDependencies:["@biomejs/biome"]};});var P={port:4085,https:true,rejectUnauthorized:false,timeout:3e4,debug:false},I={pollIntervalMs:2e3,timeoutMs:12e4};var n=class extends Error{code;details;constructor(t,e,o){super(t),this.name="VirtualizorApiError",this.code=e,this.details=o;}format(){return `[API Error ${this.code}] ${this.message}`}};function $(s,t,e){let o={};for(let[p,i]of Object.entries(s))i!==void 0&&(o[p]=i);let r=new URLSearchParams;r.set("api","json"),r.set("adminapikey",t),r.set("adminapipass",e);for(let[p,i]of Object.entries(o))r.set(p,String(i));return `?${r.toString()}`}var q=5e3,v=class{constructor(t){this.config=t;let e=t.https?U.Agent:j.Agent;this.agent=new e({keepAlive:true,maxSockets:50,maxFreeSockets:10,scheduling:"lifo",...t.https?{rejectUnauthorized:t.rejectUnauthorized}:{}}),this.logger=t.logger;}agent;logger;parseResponse(t){if(t.error&&t.error.length>0){let e=t.error[0];if(e)throw new n(e.msg,e.code)}return t}async request(t,e={},o={}){let r={act:t,...e},p=$(r,this.config.apiKey,this.config.apiPass);if(this.config.debug){let c=p.replace(/adminapikey=[^&]*/,"adminapikey=[REDACTED]").replace(/adminapipass=[^&]*/,"adminapipass=[REDACTED]");this.logger.debug(`Request: act=${t} path=/index.php${c}`);}let i=`/index.php${p}`,m=Object.entries(o).filter(([,c])=>c!==void 0).map(([c,R])=>`${encodeURIComponent(c)}=${encodeURIComponent(String(R))}`).join("&");try{let c=await this.rawRequest(i,m||void 0);return this.parseResponse(c)}catch(c){throw this.config.debug&&(c instanceof n?this.logger.error(`[Virtualizor] \u25CF Error: [API Error ${c.code}] ${c.message}`):this.logger.error(`[Virtualizor] \u25CF Error: ${c.message}`)),c}}validateJsonDepth(t,e=0){if(e>100)throw new n("JSON depth limit exceeded",-32e3);if(typeof t=="object"&&t!==null)if(Array.isArray(t))for(let r of t)this.validateJsonDepth(r,e+1);else for(let r of Object.values(t))this.validateJsonDepth(r,e+1);}destroy(){this.agent.destroy();}rawRequest(t,e){let o=this.config.https?U:j,r={host:this.config.host,port:this.config.port,path:t,method:e?"POST":"GET",headers:{"Content-Type":"application/x-www-form-urlencoded",...e?{"Content-Length":Buffer.byteLength(e)}:{}},agent:this.agent};return new Promise((p,i)=>{let m=o.request(r,u=>{let T=[];u.on("data",f=>{T.push(f);}),u.on("end",()=>{let f=Buffer.concat(T).toString("utf8");if(u.statusCode===302||u.statusCode===301){i(new n(`Redirect detected (status ${u.statusCode}). Authentication failed. Location: ${u.headers.location}`,u.statusCode));return}try{let d=JSON.parse(f);this.validateJsonDepth(d),p(d);}catch(d){this.config.debug&&(d instanceof n?this.logger.error(`[Virtualizor] \u25CF Error: [API Error ${d.code}] ${d.message}`):this.logger.error(`[Virtualizor] \u25CF Error: ${d.message}`)),i(new n(`Failed to parse response: ${d.message??"Invalid JSON"}`,-32700));}}),u.on("error",f=>{this.config.debug&&this.logger.error("[Virtualizor] \u25CF Error: Response stream error",f),i(new n(`Response stream error: ${f.message??"Unknown error"}`,-32e3));});}),c=setTimeout(()=>{m.destroy(new n(`Connection timeout after ${q}ms`,-32e3));},q),R=setTimeout(()=>{m.destroy(new n(`Request timed out after ${this.config.timeout}ms`,-32e3));},this.config.timeout);m.once("socket",u=>{u.connecting?u.once("connect",()=>clearTimeout(c)):clearTimeout(c);}),m.once("close",()=>{clearTimeout(c),clearTimeout(R);}),m.on("error",u=>{u instanceof n?i(u):i(new n(`Request error ${u}`,-32e3));}),e&&m.write(e),m.end();})}};var A=process.platform==="win32",G=process.env.NO_COLOR===void 0&&process.stdout.isTTY;function l(s,t){return G?`\x1B[${s}m${t}\x1B[0m`:t}var a={red:s=>l(31,s),green:s=>l(32,s),yellow:s=>l(33,s),blue:s=>l(34,s),magenta:s=>l(35,s),cyan:s=>l(36,s),white:s=>l(37,s),gray:s=>l(90,s),dim:s=>l(2,s),bold:s=>l(1,s),underline:s=>l(4,s),bgRed:s=>l(41,s),bgGreen:s=>l(42,s),bgYellow:s=>l(43,s),bgBlue:s=>l(44,s),bgCyan:s=>l(46,s)},g={success:A?"\u221A":"\u2714",error:A?"\xD7":"\u2716",warning:A?"\u203C":"\u26A0",info:A?"i":"\u2139",bullet:"\u25CF",arrow:"\u2192",chevron:"\u203A",pointer:"\u276F",star:"\u2605"},h={topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502"};var k=class{constructor(t="Virtualizor"){this.prefix=t;}timestamp(){let e=new Date().toISOString().split("T")[1];return a.dim(e?e.slice(0,8):"00:00:00")}tag(){return a.cyan(`[${this.prefix}]`)}debug(t,...e){console.log(this.timestamp(),this.tag(),a.dim(g.bullet),a.dim(t),...e);}info(t,...e){console.log(this.timestamp(),this.tag(),a.blue(g.info),t,...e);}warn(t,...e){console.log(this.timestamp(),this.tag(),a.yellow(g.warning),a.yellow(t),...e);}error(t,e){console.error(this.timestamp(),this.tag(),a.red(g.error),a.red(t)),e?.stack&&console.error(a.dim(e.stack.split(`
2
+ `).slice(1,4).join(`
3
+ `)));}success(t,...e){console.log(this.timestamp(),this.tag(),a.green(g.success),a.green(t),...e);}},w=new k;function O(s,t={}){let{padding:e=1,margin:o=0,borderColor:r="cyan"}=t,p=s.split(`
4
+ `),m=Math.max(...p.map(y=>y.length))+e*2,c=a[r]??a.cyan,R=h.horizontal.repeat(m),u=`${h.topLeft}${R}${h.topRight}`,T=`${h.bottomLeft}${R}${h.bottomRight}`,f=p.map(y=>{let z=" ".repeat(e)+y+" ".repeat(e);return `${h.vertical}${z.padEnd(m)}${h.vertical}`}),d=[c(u),...f.map(y=>c(y)),c(T)].join(`
5
+ `);if(o>0){let y=" ".repeat(o);return d.split(`
6
+ `).map(z=>y+z).join(`
7
+ `)}return d}function b(s,t){let e=["\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","\u2551 \u{1F680} UPDATE AVAILABLE \u{1F680} \u2551","\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563","\u2551 \u2551",`\u2551 Current version: ${s.padEnd(18)} \u2551`,`\u2551 Latest version: ${t.padEnd(17)} \u2551`,"\u2551 \u2551","\u2551 To update, run: \u2551","\u2551 npm install virtualizorjs@latest \u2551","\u2551 \u2551","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"].join(`
8
+ `);return a.yellow(e)}function N(s,t,e){let o=["\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","\u2551 \u274C ERROR OCCURRED \u274C \u2551","\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563","\u2551 \u2551",`\u2551 ${s.padEnd(34)}\u2551`,"\u2551 \u2551",`\u2551 ${t.padEnd(34)}\u2551`,"\u2551 \u2551",e?`\u2551 \u{1F4A1} ${e.padEnd(29)}\u2551`:"",e?"\u2551 \u2551":"","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"].filter(r=>r!==void 0).join(`
9
+ `);return a.red(o)}function B(s,t=false){if(s instanceof n){let e=s.details&&t?`
10
+ ${a.dim(JSON.stringify(s.details,null,2))}`:"";return `${g.error} ${a.red(`[API Error ${s.code}]`)} ${s.message}${e}`}return `${g.error} ${a.red(s.message)}`}var x=class{constructor(t){this.http=t;}async list(){return (await this.http.request("plans",{},{})).plans}async create(t){return this.http.request("addplan",{},t)}async delete(t){return this.http.request("plans",{},{delete:t})}};var V=class{constructor(t){this.http=t;}async get(t){return (await this.http.request("tasks",{taskid:t},{})).tasks[t]}async wait(t,e={}){let{pollIntervalMs:o=I.pollIntervalMs,timeoutMs:r=I.timeoutMs}=e,p=Date.now()+r;for(;Date.now()<p;){let i=await this.get(t);if(!i)throw new n("Task not found",404);if(i.status==="1"||i.status==="done")return i;if(i.status==="error"||i.status==="-1")throw new n("Task failed",500);await new Promise(m=>setTimeout(m,o));}throw new n(`Task timed out after ${r}ms`,408)}};var C=class{constructor(t){this.http=t;}async list(){return (await this.http.request("users",{},{})).users}async create(t){return this.http.request("adduser",{},t)}async delete(t){return this.http.request("users",{},{delete:t})}async suspend(t){return this.http.request("users",{},{suspend:t})}async unsuspend(t){return this.http.request("users",{},{unsuspend:t})}};var E={REBUILD_REOS_FLAG:1,MIGRATE_FLAG:1,MIGRATE_BUT_FLAG:1};var S=class{constructor(t){this.http=t;}async list(t={}){return (await this.http.request("vs",{},t)).vs??{}}async get(t){let e=await this.http.request("vs",{},t),o=Object.entries(e.vs??{});if(o.length===0)throw new n("VPS not found",404);let r=o[0];if(!r)throw new n("VPS not found",404);let[,p]=r;return p}async create(t){return this.http.request("addvs",{},t)}async delete(t){return this.http.request("vs",{delete:t},{})}async start(t){return this.http.request("vs",{vpsid:t,action:"start"},{})}async stop(t){return this.http.request("vs",{vpsid:t,action:"stop"},{})}async restart(t){return this.http.request("vs",{vpsid:t,action:"restart"},{})}async poweroff(t){return this.http.request("vs",{vpsid:t,action:"poweroff"},{})}async suspend(t){return this.http.request("vs",{suspend:t},{})}async unsuspend(t){return this.http.request("vs",{unsuspend:t},{})}async rebuild(t,e){return this.http.request("rebuild",{},{vpsid:t,reos:E.REBUILD_REOS_FLAG,...e})}async clone(t,e){return this.http.request("clone",{},{vpsid:t,...e})}async migrate(t,e){return this.http.request("migrate",{},{vpsid:t,migrate:E.MIGRATE_FLAG,migrate_but:E.MIGRATE_BUT_FLAG,...e})}async status(t){return this.http.request("vstatus",{vpsid:t},{})}async vnc(t){return this.http.request("vnc",{vpsid:t},{})}async stats(t){return this.http.request("vps_stats",{},{vpsid:t})}};var H="https://registry.npmjs.org/virtualizorjs/latest";async function J(s){let t=new AbortController,e=setTimeout(()=>t.abort(),s);try{let o=await fetch(H,{signal:t.signal});if(!o.ok)throw new Error(`HTTP ${o.status}`);return await o.json()}finally{clearTimeout(e);}}function K(s,t){let e=s.split(".").map(Number),o=t.split(".").map(Number);return (o[0]??0)>(e[0]??0)||(o[0]??0)===(e[0]??0)&&(o[1]??0)>(e[1]??0)||(o[0]??0)===(e[0]??0)&&(o[1]??0)===(e[1]??0)&&(o[2]??0)>(e[2]??0)}var _=false;async function D(s,t,e){if(!(_&&true)){_=true;try{let r=(await J(e?.timeout??2e3)).version;if(!K(s,r))return;t.warn(`Update available: ${s} \u2192 ${r}`),console.log(),console.log(b(s,r)),console.log();}catch{}}}var W=M().version,L=class{vps;users;plans;tasks;logger;constructor(t){let e=t.logger??w;this.logger=e;let o={host:t.host,apiKey:t.apiKey,apiPass:t.apiPass??"",port:t.port??P.port,https:t.https??P.https,rejectUnauthorized:t.rejectUnauthorized??P.rejectUnauthorized,timeout:t.timeout??P.timeout,debug:t.debug??P.debug,logger:e,disableUpdateCheck:t.disableUpdateCheck??false},r=new v(o);this.vps=new S(r),this.users=new C(r),this.plans=new x(r),this.tasks=new V(r),o.disableUpdateCheck||D(W,e).catch(()=>{});}};function Y(s){return new L(s)}function X(s,t){let e=t?.as??"array",o=t?.separator??", ";if(!s)return e==="array"?[]:"";let r=[];if(Array.isArray(s))r=s.filter(Boolean);else if(typeof s=="string"){let p=s.trim();p===""?r=[]:p.includes(",")?r=p.split(",").map(i=>i.trim()).filter(Boolean):/\s+/.test(p)?r=p.split(/\s+/).map(i=>i.trim()).filter(Boolean):r=[p];}else typeof s=="object"&&(r=Object.values(s).filter(Boolean));return e==="array"?r:r.join(o)}
11
+ export{k as ConsoleLogger,n as VirtualizorApiError,L as VirtualizorClient,a as colors,O as createBox,N as createErrorBox,b as createUpdateBox,Y as createVirtualizorClient,w as defaultLogger,B as formatError,X as formatIps,g as symbols};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "virtualizorjs",
3
- "version": "2.1.3",
3
+ "version": "2.2.1",
4
4
  "description": "TypeScript SDK for the Virtualizor server management API. Create, start, stop, restart, rebuild, and manage VPS instances with a type-safe, developer-friendly client.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/defaults.ts","../src/auth.ts","../src/http.ts","../src/resources/plans.ts","../src/resources/tasks.ts","../src/resources/users.ts","../src/constants/vps.ts","../src/resources/vps.ts","../src/client.ts","../src/utils/format-ips.ts"],"names":["https","http"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_CONFIG = {\n port: 4085,\n https: true,\n rejectUnauthorized: false,\n timeout: 30000,\n debug: false,\n} as const;\n\nexport const DEFAULT_TASK_POLLING = {\n pollIntervalMs: 2000,\n timeoutMs: 120000,\n} as const;\n","import type { ApiParams } from './types/common.js';\n\nexport function buildQueryString(params: ApiParams, apiKey: string, apiPass: string): string {\n const clean: ApiParams = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n clean[key] = value;\n }\n }\n\n const urlParams = new URLSearchParams();\n urlParams.set('api', 'json');\n urlParams.set('adminapikey', apiKey);\n urlParams.set('adminapipass', apiPass);\n\n for (const [key, value] of Object.entries(clean)) {\n urlParams.set(key, String(value));\n }\n\n return `?${urlParams.toString()}`;\n}\n","import http from 'node:http';\nimport https from 'node:https';\nimport { buildQueryString } from './auth.js';\nimport type { ApiParams } from './types/common.js';\nimport type { VirtualizorResponse } from './types/common.js';\nimport type { ResolvedConfig } from './types/config.js';\n\nexport class VirtualizorApiError extends Error {\n readonly code: number;\n\n constructor(message: string, code: number) {\n super(message);\n this.name = 'VirtualizorApiError';\n this.code = code;\n }\n}\n\nexport class HttpClient {\n constructor(private readonly config: ResolvedConfig) {}\n\n parseResponse<T extends VirtualizorResponse>(data: T): T {\n if (data.error && data.error.length > 0) {\n const first = data.error[0];\n if (first) {\n throw new VirtualizorApiError(first.msg, first.code);\n }\n }\n return data;\n }\n\n async request<T extends VirtualizorResponse>(\n act: string,\n queryParams: ApiParams = {},\n bodyParams: ApiParams = {},\n ): Promise<T> {\n const allQueryParams: ApiParams = { act, ...queryParams };\n const qs = buildQueryString(allQueryParams, this.config.apiKey, this.config.apiPass);\n\n const path = `/index.php${qs}`;\n\n const bodyString = Object.entries(bodyParams as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join('&');\n\n const data = await this.rawRequest(path, bodyString || undefined);\n return this.parseResponse(data as T);\n }\n\n private rawRequest(path: string, body?: string): Promise<VirtualizorResponse> {\n const transport = this.config.https ? https : http;\n const options: https.RequestOptions = {\n host: this.config.host,\n port: this.config.port,\n path,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n ...(body ? { 'Content-Length': Buffer.byteLength(body) } : {}),\n },\n ...(this.config.https\n ? { agent: new https.Agent({ rejectUnauthorized: this.config.rejectUnauthorized }) }\n : {}),\n };\n\n return new Promise((resolve, reject) => {\n const req = transport.request(options, (res) => {\n let raw = '';\n res.on('data', (chunk: Buffer) => {\n raw += chunk.toString();\n });\n res.on('end', () => {\n // Handle redirect (302) - usually means auth failed\n if (res.statusCode === 302 || res.statusCode === 301) {\n reject(\n new Error(\n `Redirect detected (status ${res.statusCode}). Authentication failed. ` +\n `Check your API credentials. Location: ${res.headers.location}`,\n ),\n );\n return;\n }\n\n try {\n resolve(JSON.parse(raw) as VirtualizorResponse);\n } catch (err) {\n if (this.config.debug)\n console.debug('[Virtualizor] Raw response (first 500 chars):', raw.slice(0, 500));\n reject(\n new Error(\n `Failed to parse response: ${raw.slice(0, 200)}. Parse error: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n }\n });\n });\n\n req.setTimeout(this.config.timeout, () => {\n req.destroy(new Error(`Request timed out after ${this.config.timeout}ms`));\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(body);\n }\n\n req.end();\n });\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { ApiParams } from '../types/common.js';\nimport type { AsyncTaskResult, VirtualizorResponse } from '../types/common.js';\nimport type { CreatePlanParams, Plan } from '../types/plans.js';\n\ninterface ListPlansResponse extends VirtualizorResponse {\n plans: Record<string, Plan>;\n}\nexport class PlansResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Record<string, Plan>> {\n const res = await this.http.request<ListPlansResponse>('plans', {}, {});\n return res.plans;\n }\n\n async create(params: CreatePlanParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('addplan', {}, params);\n }\n\n async delete(planId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('plans', {}, { delete: planId });\n }\n}\n","import { DEFAULT_TASK_POLLING } from '../config/defaults.js';\nimport type { HttpClient } from '../http.js';\nimport type { VirtualizorResponse } from '../types/common.js';\nimport type { Task } from '../types/tasks.js';\n\ninterface TasksResponse extends VirtualizorResponse {\n tasks: Record<string, Task>;\n}\n\nexport class TasksResource {\n constructor(private readonly http: HttpClient) {}\n\n async get(taskId: string): Promise<Task | undefined> {\n const res = await this.http.request<TasksResponse>('tasks', { taskid: taskId }, {});\n return res.tasks[taskId];\n }\n\n async wait(\n taskId: string,\n options: { pollIntervalMs?: number; timeoutMs?: number } = {},\n ): Promise<Task> {\n const {\n pollIntervalMs = DEFAULT_TASK_POLLING.pollIntervalMs,\n timeoutMs = DEFAULT_TASK_POLLING.timeoutMs,\n } = options;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const task = await this.get(taskId);\n if (!task) throw new Error(`Task ${taskId} not found`);\n if (task.status === '1' || task.status === 'done') return task;\n if (task.status === 'error' || task.status === '-1') {\n throw new Error(`Task ${taskId} failed`);\n }\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n\n throw new Error(`Task ${taskId} timed out after ${timeoutMs}ms`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { ApiParams } from '../types/common.js';\nimport type { AsyncTaskResult, VirtualizorResponse } from '../types/common.js';\nimport type { CreateUserParams, User } from '../types/users.js';\n\ninterface ListUsersResponse extends VirtualizorResponse {\n users: Record<string, User>;\n}\n\nexport class UsersResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Record<string, User>> {\n const res = await this.http.request<ListUsersResponse>('users', {}, {});\n return res.users;\n }\n\n async create(params: CreateUserParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('adduser', {}, params);\n }\n\n async delete(uid: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('users', {}, { delete: uid });\n }\n\n async suspend(uid: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('users', {}, { suspend: uid });\n }\n\n async unsuspend(uid: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('users', {}, { unsuspend: uid });\n }\n}\n","// VPS operation constants\nexport const VPS_CONSTANTS = {\n // Rebuild operation requires reos=1 flag\n REBUILD_REOS_FLAG: 1,\n // Migrate operation requires migrate=1 flag\n MIGRATE_FLAG: 1,\n // Migrate operation requires migrate_but=1 flag\n MIGRATE_BUT_FLAG: 1,\n} as const;\n","import { VPS_CONSTANTS } from '../constants/vps.js';\nimport type { HttpClient } from '../http.js';\nimport type { ApiParams } from '../types/common.js';\nimport type { AsyncTaskResult, VirtualizorResponse } from '../types/common.js';\nimport type {\n CloneVPSParams,\n CreateVPSParams,\n ListVPSParams,\n MigrateVPSParams,\n RebuildVPSParams,\n VNCInfo,\n VPS,\n VPSStatsResponse,\n} from '../types/vps.js';\n\ninterface ListVPSResponse extends VirtualizorResponse {\n vs: Record<string, VPS>;\n}\ninterface GetVPSResponse extends VirtualizorResponse {\n vs: Record<string, VPS>;\n}\n\nexport class VpsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(filters: ListVPSParams = {}): Promise<Record<string, VPS>> {\n const res = await this.http.request<ListVPSResponse>('vs', {}, filters);\n return res.vs ?? {};\n }\n\n async get(vpsId: string): Promise<VPS> {\n const res = await this.http.request<GetVPSResponse>('vs', { vpsid: vpsId }, {});\n const vps = res.vs[vpsId];\n if (!vps) throw new Error(`VPS ${vpsId} not found in response`);\n return vps;\n }\n\n async create(params: CreateVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('addvs', {}, params);\n }\n\n async delete(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { delete: vpsId }, {});\n }\n\n async start(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'start' }, {});\n }\n\n async stop(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'stop' }, {});\n }\n\n async restart(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'restart' }, {});\n }\n\n async poweroff(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'poweroff' }, {});\n }\n\n async suspend(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { suspend: vpsId }, {});\n }\n\n async unsuspend(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { unsuspend: vpsId }, {});\n }\n\n async rebuild(vpsId: string, params: RebuildVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>(\n 'rebuild',\n {},\n {\n vpsid: vpsId,\n reos: VPS_CONSTANTS.REBUILD_REOS_FLAG,\n ...params,\n },\n );\n }\n\n async clone(vpsId: string, params: CloneVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>(\n 'clone',\n {},\n {\n vpsid: vpsId,\n ...params,\n },\n );\n }\n\n async migrate(vpsId: string, params: MigrateVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>(\n 'migrate',\n {},\n {\n vpsid: vpsId,\n migrate: VPS_CONSTANTS.MIGRATE_FLAG,\n migrate_but: VPS_CONSTANTS.MIGRATE_BUT_FLAG,\n ...params,\n },\n );\n }\n\n async status(vpsId: string): Promise<unknown> {\n return this.http.request('vstatus', { vpsid: vpsId }, {});\n }\n\n async vnc(vpsId: string): Promise<VNCInfo> {\n return this.http.request<VNCInfo>('vnc', { vpsid: vpsId }, {});\n }\n\n async stats(vpsId: string): Promise<VPSStatsResponse> {\n return this.http.request<VPSStatsResponse>('vps_stats', {}, { vpsid: vpsId });\n }\n}\n","import { DEFAULT_CONFIG } from './config/defaults.js';\nimport { HttpClient } from './http.js';\nimport { PlansResource } from './resources/plans.js';\nimport { TasksResource } from './resources/tasks.js';\nimport { UsersResource } from './resources/users.js';\nimport { VpsResource } from './resources/vps.js';\nimport type { ResolvedConfig, VirtualizorConfig } from './types/config.js';\n\nexport class VirtualizorClient {\n readonly vps: VpsResource;\n readonly users: UsersResource;\n readonly plans: PlansResource;\n readonly tasks: TasksResource;\n\n constructor(config: VirtualizorConfig) {\n const resolved: ResolvedConfig = {\n host: config.host,\n apiKey: config.apiKey,\n apiPass: config.apiPass ?? '',\n port: config.port ?? DEFAULT_CONFIG.port,\n https: config.https ?? DEFAULT_CONFIG.https,\n rejectUnauthorized: config.rejectUnauthorized ?? DEFAULT_CONFIG.rejectUnauthorized,\n timeout: config.timeout ?? DEFAULT_CONFIG.timeout,\n debug: config.debug ?? DEFAULT_CONFIG.debug,\n };\n const http = new HttpClient(resolved);\n this.vps = new VpsResource(http);\n this.users = new UsersResource(http);\n this.plans = new PlansResource(http);\n this.tasks = new TasksResource(http);\n }\n}\n\nexport function createVirtualizorClient(config: VirtualizorConfig): VirtualizorClient {\n return new VirtualizorClient(config);\n}\n","export type IpsInput = string[] | Record<string, string> | string | undefined | null;\n\nexport type FormatIpsOptions = {\n /**\n * Choose the return type. Defaults to 'array'.\n * - 'array' returns string[]\n * - 'string' returns a joined string using `separator`\n */\n as?: 'array' | 'string';\n /** Separator used when returning a string. Defaults to ', '. */\n separator?: string;\n};\n\n/**\n * formatIps\n * - Default behavior: return an array of IP strings (string[])\n * - If options.as === 'string' it returns a joined string using options.separator\n */\nexport function formatIps(ips: IpsInput): string[];\nexport function formatIps(ips: IpsInput, options: FormatIpsOptions & { as: 'string' }): string;\nexport function formatIps(ips: IpsInput, options?: FormatIpsOptions): string | string[] {\n const as = options?.as ?? 'array';\n const separator = options?.separator ?? ', ';\n\n if (!ips) {\n return as === 'array' ? [] : '';\n }\n\n let result: string[] = [];\n\n if (Array.isArray(ips)) {\n result = ips.filter(Boolean);\n } else if (typeof ips === 'string') {\n const str = ips.trim();\n if (str === '') {\n result = [];\n } else if (str.includes(',')) {\n result = str\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n } else if (/\\s+/.test(str)) {\n result = str\n .split(/\\s+/)\n .map((s) => s.trim())\n .filter(Boolean);\n } else {\n result = [str];\n }\n } else if (typeof ips === 'object') {\n result = Object.values(ips).filter(Boolean);\n }\n\n return as === 'array' ? result : result.join(separator);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/defaults.ts","../src/auth.ts","../src/http.ts","../src/resources/plans.ts","../src/resources/tasks.ts","../src/resources/users.ts","../src/constants/vps.ts","../src/resources/vps.ts","../src/client.ts","../src/utils/format-ips.ts"],"names":["http"],"mappings":"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","file":"index.mjs","sourcesContent":["export const DEFAULT_CONFIG = {\n port: 4085,\n https: true,\n rejectUnauthorized: false,\n timeout: 30000,\n debug: false,\n} as const;\n\nexport const DEFAULT_TASK_POLLING = {\n pollIntervalMs: 2000,\n timeoutMs: 120000,\n} as const;\n","import type { ApiParams } from './types/common.js';\n\nexport function buildQueryString(params: ApiParams, apiKey: string, apiPass: string): string {\n const clean: ApiParams = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n clean[key] = value;\n }\n }\n\n const urlParams = new URLSearchParams();\n urlParams.set('api', 'json');\n urlParams.set('adminapikey', apiKey);\n urlParams.set('adminapipass', apiPass);\n\n for (const [key, value] of Object.entries(clean)) {\n urlParams.set(key, String(value));\n }\n\n return `?${urlParams.toString()}`;\n}\n","import http from 'node:http';\nimport https from 'node:https';\nimport { buildQueryString } from './auth.js';\nimport type { ApiParams } from './types/common.js';\nimport type { VirtualizorResponse } from './types/common.js';\nimport type { ResolvedConfig } from './types/config.js';\n\nexport class VirtualizorApiError extends Error {\n readonly code: number;\n\n constructor(message: string, code: number) {\n super(message);\n this.name = 'VirtualizorApiError';\n this.code = code;\n }\n}\n\nexport class HttpClient {\n constructor(private readonly config: ResolvedConfig) {}\n\n parseResponse<T extends VirtualizorResponse>(data: T): T {\n if (data.error && data.error.length > 0) {\n const first = data.error[0];\n if (first) {\n throw new VirtualizorApiError(first.msg, first.code);\n }\n }\n return data;\n }\n\n async request<T extends VirtualizorResponse>(\n act: string,\n queryParams: ApiParams = {},\n bodyParams: ApiParams = {},\n ): Promise<T> {\n const allQueryParams: ApiParams = { act, ...queryParams };\n const qs = buildQueryString(allQueryParams, this.config.apiKey, this.config.apiPass);\n\n const path = `/index.php${qs}`;\n\n const bodyString = Object.entries(bodyParams as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join('&');\n\n const data = await this.rawRequest(path, bodyString || undefined);\n return this.parseResponse(data as T);\n }\n\n private rawRequest(path: string, body?: string): Promise<VirtualizorResponse> {\n const transport = this.config.https ? https : http;\n const options: https.RequestOptions = {\n host: this.config.host,\n port: this.config.port,\n path,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n ...(body ? { 'Content-Length': Buffer.byteLength(body) } : {}),\n },\n ...(this.config.https\n ? { agent: new https.Agent({ rejectUnauthorized: this.config.rejectUnauthorized }) }\n : {}),\n };\n\n return new Promise((resolve, reject) => {\n const req = transport.request(options, (res) => {\n let raw = '';\n res.on('data', (chunk: Buffer) => {\n raw += chunk.toString();\n });\n res.on('end', () => {\n // Handle redirect (302) - usually means auth failed\n if (res.statusCode === 302 || res.statusCode === 301) {\n reject(\n new Error(\n `Redirect detected (status ${res.statusCode}). Authentication failed. ` +\n `Check your API credentials. Location: ${res.headers.location}`,\n ),\n );\n return;\n }\n\n try {\n resolve(JSON.parse(raw) as VirtualizorResponse);\n } catch (err) {\n if (this.config.debug)\n console.debug('[Virtualizor] Raw response (first 500 chars):', raw.slice(0, 500));\n reject(\n new Error(\n `Failed to parse response: ${raw.slice(0, 200)}. Parse error: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n }\n });\n });\n\n req.setTimeout(this.config.timeout, () => {\n req.destroy(new Error(`Request timed out after ${this.config.timeout}ms`));\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(body);\n }\n\n req.end();\n });\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { ApiParams } from '../types/common.js';\nimport type { AsyncTaskResult, VirtualizorResponse } from '../types/common.js';\nimport type { CreatePlanParams, Plan } from '../types/plans.js';\n\ninterface ListPlansResponse extends VirtualizorResponse {\n plans: Record<string, Plan>;\n}\nexport class PlansResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Record<string, Plan>> {\n const res = await this.http.request<ListPlansResponse>('plans', {}, {});\n return res.plans;\n }\n\n async create(params: CreatePlanParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('addplan', {}, params);\n }\n\n async delete(planId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('plans', {}, { delete: planId });\n }\n}\n","import { DEFAULT_TASK_POLLING } from '../config/defaults.js';\nimport type { HttpClient } from '../http.js';\nimport type { VirtualizorResponse } from '../types/common.js';\nimport type { Task } from '../types/tasks.js';\n\ninterface TasksResponse extends VirtualizorResponse {\n tasks: Record<string, Task>;\n}\n\nexport class TasksResource {\n constructor(private readonly http: HttpClient) {}\n\n async get(taskId: string): Promise<Task | undefined> {\n const res = await this.http.request<TasksResponse>('tasks', { taskid: taskId }, {});\n return res.tasks[taskId];\n }\n\n async wait(\n taskId: string,\n options: { pollIntervalMs?: number; timeoutMs?: number } = {},\n ): Promise<Task> {\n const {\n pollIntervalMs = DEFAULT_TASK_POLLING.pollIntervalMs,\n timeoutMs = DEFAULT_TASK_POLLING.timeoutMs,\n } = options;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const task = await this.get(taskId);\n if (!task) throw new Error(`Task ${taskId} not found`);\n if (task.status === '1' || task.status === 'done') return task;\n if (task.status === 'error' || task.status === '-1') {\n throw new Error(`Task ${taskId} failed`);\n }\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n\n throw new Error(`Task ${taskId} timed out after ${timeoutMs}ms`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { ApiParams } from '../types/common.js';\nimport type { AsyncTaskResult, VirtualizorResponse } from '../types/common.js';\nimport type { CreateUserParams, User } from '../types/users.js';\n\ninterface ListUsersResponse extends VirtualizorResponse {\n users: Record<string, User>;\n}\n\nexport class UsersResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Record<string, User>> {\n const res = await this.http.request<ListUsersResponse>('users', {}, {});\n return res.users;\n }\n\n async create(params: CreateUserParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('adduser', {}, params);\n }\n\n async delete(uid: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('users', {}, { delete: uid });\n }\n\n async suspend(uid: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('users', {}, { suspend: uid });\n }\n\n async unsuspend(uid: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('users', {}, { unsuspend: uid });\n }\n}\n","// VPS operation constants\nexport const VPS_CONSTANTS = {\n // Rebuild operation requires reos=1 flag\n REBUILD_REOS_FLAG: 1,\n // Migrate operation requires migrate=1 flag\n MIGRATE_FLAG: 1,\n // Migrate operation requires migrate_but=1 flag\n MIGRATE_BUT_FLAG: 1,\n} as const;\n","import { VPS_CONSTANTS } from '../constants/vps.js';\nimport type { HttpClient } from '../http.js';\nimport type { ApiParams } from '../types/common.js';\nimport type { AsyncTaskResult, VirtualizorResponse } from '../types/common.js';\nimport type {\n CloneVPSParams,\n CreateVPSParams,\n ListVPSParams,\n MigrateVPSParams,\n RebuildVPSParams,\n VNCInfo,\n VPS,\n VPSStatsResponse,\n} from '../types/vps.js';\n\ninterface ListVPSResponse extends VirtualizorResponse {\n vs: Record<string, VPS>;\n}\ninterface GetVPSResponse extends VirtualizorResponse {\n vs: Record<string, VPS>;\n}\n\nexport class VpsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(filters: ListVPSParams = {}): Promise<Record<string, VPS>> {\n const res = await this.http.request<ListVPSResponse>('vs', {}, filters);\n return res.vs ?? {};\n }\n\n async get(vpsId: string): Promise<VPS> {\n const res = await this.http.request<GetVPSResponse>('vs', { vpsid: vpsId }, {});\n const vps = res.vs[vpsId];\n if (!vps) throw new Error(`VPS ${vpsId} not found in response`);\n return vps;\n }\n\n async create(params: CreateVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('addvs', {}, params);\n }\n\n async delete(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { delete: vpsId }, {});\n }\n\n async start(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'start' }, {});\n }\n\n async stop(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'stop' }, {});\n }\n\n async restart(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'restart' }, {});\n }\n\n async poweroff(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { vpsid: vpsId, action: 'poweroff' }, {});\n }\n\n async suspend(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { suspend: vpsId }, {});\n }\n\n async unsuspend(vpsId: string): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>('vs', { unsuspend: vpsId }, {});\n }\n\n async rebuild(vpsId: string, params: RebuildVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>(\n 'rebuild',\n {},\n {\n vpsid: vpsId,\n reos: VPS_CONSTANTS.REBUILD_REOS_FLAG,\n ...params,\n },\n );\n }\n\n async clone(vpsId: string, params: CloneVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>(\n 'clone',\n {},\n {\n vpsid: vpsId,\n ...params,\n },\n );\n }\n\n async migrate(vpsId: string, params: MigrateVPSParams): Promise<AsyncTaskResult> {\n return this.http.request<AsyncTaskResult>(\n 'migrate',\n {},\n {\n vpsid: vpsId,\n migrate: VPS_CONSTANTS.MIGRATE_FLAG,\n migrate_but: VPS_CONSTANTS.MIGRATE_BUT_FLAG,\n ...params,\n },\n );\n }\n\n async status(vpsId: string): Promise<unknown> {\n return this.http.request('vstatus', { vpsid: vpsId }, {});\n }\n\n async vnc(vpsId: string): Promise<VNCInfo> {\n return this.http.request<VNCInfo>('vnc', { vpsid: vpsId }, {});\n }\n\n async stats(vpsId: string): Promise<VPSStatsResponse> {\n return this.http.request<VPSStatsResponse>('vps_stats', {}, { vpsid: vpsId });\n }\n}\n","import { DEFAULT_CONFIG } from './config/defaults.js';\nimport { HttpClient } from './http.js';\nimport { PlansResource } from './resources/plans.js';\nimport { TasksResource } from './resources/tasks.js';\nimport { UsersResource } from './resources/users.js';\nimport { VpsResource } from './resources/vps.js';\nimport type { ResolvedConfig, VirtualizorConfig } from './types/config.js';\n\nexport class VirtualizorClient {\n readonly vps: VpsResource;\n readonly users: UsersResource;\n readonly plans: PlansResource;\n readonly tasks: TasksResource;\n\n constructor(config: VirtualizorConfig) {\n const resolved: ResolvedConfig = {\n host: config.host,\n apiKey: config.apiKey,\n apiPass: config.apiPass ?? '',\n port: config.port ?? DEFAULT_CONFIG.port,\n https: config.https ?? DEFAULT_CONFIG.https,\n rejectUnauthorized: config.rejectUnauthorized ?? DEFAULT_CONFIG.rejectUnauthorized,\n timeout: config.timeout ?? DEFAULT_CONFIG.timeout,\n debug: config.debug ?? DEFAULT_CONFIG.debug,\n };\n const http = new HttpClient(resolved);\n this.vps = new VpsResource(http);\n this.users = new UsersResource(http);\n this.plans = new PlansResource(http);\n this.tasks = new TasksResource(http);\n }\n}\n\nexport function createVirtualizorClient(config: VirtualizorConfig): VirtualizorClient {\n return new VirtualizorClient(config);\n}\n","export type IpsInput = string[] | Record<string, string> | string | undefined | null;\n\nexport type FormatIpsOptions = {\n /**\n * Choose the return type. Defaults to 'array'.\n * - 'array' returns string[]\n * - 'string' returns a joined string using `separator`\n */\n as?: 'array' | 'string';\n /** Separator used when returning a string. Defaults to ', '. */\n separator?: string;\n};\n\n/**\n * formatIps\n * - Default behavior: return an array of IP strings (string[])\n * - If options.as === 'string' it returns a joined string using options.separator\n */\nexport function formatIps(ips: IpsInput): string[];\nexport function formatIps(ips: IpsInput, options: FormatIpsOptions & { as: 'string' }): string;\nexport function formatIps(ips: IpsInput, options?: FormatIpsOptions): string | string[] {\n const as = options?.as ?? 'array';\n const separator = options?.separator ?? ', ';\n\n if (!ips) {\n return as === 'array' ? [] : '';\n }\n\n let result: string[] = [];\n\n if (Array.isArray(ips)) {\n result = ips.filter(Boolean);\n } else if (typeof ips === 'string') {\n const str = ips.trim();\n if (str === '') {\n result = [];\n } else if (str.includes(',')) {\n result = str\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n } else if (/\\s+/.test(str)) {\n result = str\n .split(/\\s+/)\n .map((s) => s.trim())\n .filter(Boolean);\n } else {\n result = [str];\n }\n } else if (typeof ips === 'object') {\n result = Object.values(ips).filter(Boolean);\n }\n\n return as === 'array' ? result : result.join(separator);\n}\n"]}