wedos-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,384 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import ora from 'ora';
4
+ import chalk from 'chalk';
5
+ import { table } from 'table';
6
+ import { WapiClient, isSuccess } from '../lib/wapi.js';
7
+ import { getCredentials } from '../lib/config.js';
8
+ import { formatResponse, printError, printSuccess, printWarning, printInfo } from '../lib/output.js';
9
+
10
+ export function createDnsCommand() {
11
+ const dns = new Command('dns')
12
+ .description('Správa DNS záznamů');
13
+
14
+ // List DNS domains
15
+ dns
16
+ .command('domains')
17
+ .alias('list')
18
+ .description('Seznam všech DNS domén')
19
+ .option('--json', 'Výstup jako JSON')
20
+ .action(async (options) => {
21
+ const spinner = ora('Načítám DNS domény...').start();
22
+ try {
23
+ const client = new WapiClient(getCredentials());
24
+ const response = await client.dnsDomainsList();
25
+ spinner.stop();
26
+ formatResponse(response, { format: options.json ? 'json' : undefined });
27
+ } catch (error) {
28
+ spinner.stop();
29
+ printError(error);
30
+ process.exit(1);
31
+ }
32
+ });
33
+
34
+ // Get DNS domain info
35
+ dns
36
+ .command('info <domain>')
37
+ .description('Informace o DNS doméně')
38
+ .option('--json', 'Výstup jako JSON')
39
+ .action(async (domain, options) => {
40
+ const spinner = ora('Načítám DNS info...').start();
41
+ try {
42
+ const client = new WapiClient(getCredentials());
43
+ const response = await client.dnsDomainInfo(domain);
44
+ spinner.stop();
45
+ formatResponse(response, { format: options.json ? 'json' : undefined });
46
+ } catch (error) {
47
+ spinner.stop();
48
+ printError(error);
49
+ process.exit(1);
50
+ }
51
+ });
52
+
53
+ // Add DNS domain
54
+ dns
55
+ .command('add <domain>')
56
+ .description('Přidání domény do WEDOS DNS')
57
+ .option('-t, --type <type>', 'Typ domény (primary/secondary)', 'primary')
58
+ .option('--axfr', 'Povolit AXFR transfery')
59
+ .option('--axfr-ips <ips>', 'Povolené IP adresy pro AXFR (oddělené čárkou)')
60
+ .option('--primary-ip <ip>', 'IP primárního DNS serveru (pro secondary typ)')
61
+ .option('--json', 'Výstup jako JSON')
62
+ .action(async (domain, options) => {
63
+ const spinner = ora('Přidávám doménu do DNS...').start();
64
+ try {
65
+ const client = new WapiClient(getCredentials());
66
+ const response = await client.dnsDomainAdd({
67
+ name: domain,
68
+ type: options.type,
69
+ axfrEnabled: options.axfr,
70
+ axfrIps: options.axfrIps,
71
+ primaryIp: options.primaryIp,
72
+ });
73
+ spinner.stop();
74
+ formatResponse(response, { format: options.json ? 'json' : undefined });
75
+ } catch (error) {
76
+ spinner.stop();
77
+ printError(error);
78
+ process.exit(1);
79
+ }
80
+ });
81
+
82
+ // Delete DNS domain
83
+ dns
84
+ .command('delete <domain>')
85
+ .alias('rm')
86
+ .description('Odebrání domény z WEDOS DNS')
87
+ .option('-y, --yes', 'Přeskočit potvrzení')
88
+ .action(async (domain, options) => {
89
+ if (!options.yes) {
90
+ const { confirm } = await inquirer.prompt([{
91
+ type: 'confirm',
92
+ name: 'confirm',
93
+ message: `Opravdu chceš smazat ${domain} a VŠECHNY její záznamy?`,
94
+ default: false,
95
+ }]);
96
+
97
+ if (!confirm) {
98
+ printInfo('Zrušeno');
99
+ return;
100
+ }
101
+ }
102
+
103
+ const spinner = ora('Mažu doménu...').start();
104
+ try {
105
+ const client = new WapiClient(getCredentials());
106
+ const response = await client.dnsDomainDelete(domain);
107
+ spinner.stop();
108
+ formatResponse(response);
109
+ } catch (error) {
110
+ spinner.stop();
111
+ printError(error);
112
+ process.exit(1);
113
+ }
114
+ });
115
+
116
+ // Commit DNS changes
117
+ dns
118
+ .command('commit <domain>')
119
+ .alias('save')
120
+ .description('Uložení a publikování DNS změn')
121
+ .action(async (domain) => {
122
+ const spinner = ora('Ukládám DNS změny...').start();
123
+ try {
124
+ const client = new WapiClient(getCredentials());
125
+ const response = await client.dnsDomainCommit(domain);
126
+ spinner.stop();
127
+ formatResponse(response);
128
+
129
+ if (isSuccess(parseInt(response.code))) {
130
+ printSuccess('DNS změny publikovány na servery');
131
+ }
132
+ } catch (error) {
133
+ spinner.stop();
134
+ printError(error);
135
+ process.exit(1);
136
+ }
137
+ });
138
+
139
+ // List DNS records
140
+ dns
141
+ .command('records <domain>')
142
+ .alias('rows')
143
+ .description('Seznam DNS záznamů domény')
144
+ .option('--json', 'Výstup jako JSON')
145
+ .action(async (domain, options) => {
146
+ const spinner = ora('Načítám DNS záznamy...').start();
147
+ try {
148
+ const client = new WapiClient(getCredentials());
149
+ const response = await client.dnsRowsList(domain);
150
+ spinner.stop();
151
+
152
+ if (options.json) {
153
+ formatResponse(response, { format: 'json' });
154
+ } else {
155
+ const code = parseInt(response.code);
156
+ if (isSuccess(code) && response.data?.row) {
157
+ console.log(chalk.bold(`\nDNS záznamy pro ${domain}:\n`));
158
+
159
+ const tableData = [
160
+ [chalk.bold('ID'), chalk.bold('Název'), chalk.bold('Typ'), chalk.bold('TTL'), chalk.bold('Data')],
161
+ ];
162
+
163
+ const records = Array.isArray(response.data.row) ? response.data.row : [response.data.row];
164
+ for (const row of records) {
165
+ tableData.push([
166
+ row.ID || row.id || '-',
167
+ row.name || '@',
168
+ row.rdtype || row.type || '-',
169
+ row.ttl || '-',
170
+ truncate(row.rdata || '-', 50),
171
+ ]);
172
+ }
173
+
174
+ console.log(table(tableData));
175
+ printInfo(`Celkem: ${records.length} záznam(ů)`);
176
+ } else {
177
+ formatResponse(response);
178
+ }
179
+ }
180
+ } catch (error) {
181
+ spinner.stop();
182
+ printError(error);
183
+ process.exit(1);
184
+ }
185
+ });
186
+
187
+ // Add DNS record
188
+ dns
189
+ .command('record-add <domain>')
190
+ .alias('add-record')
191
+ .description('Přidání DNS záznamu')
192
+ .requiredOption('-n, --name <name>', 'Název záznamu (použij @ pro root)')
193
+ .requiredOption('-t, --type <type>', 'Typ záznamu (A, AAAA, CNAME, MX, TXT, atd.)')
194
+ .requiredOption('-d, --data <data>', 'Data záznamu')
195
+ .option('--ttl <seconds>', 'TTL v sekundách', '3600')
196
+ .option('-c, --comment <comment>', 'Komentář/poznámka')
197
+ .option('--no-commit', 'Neuložit změny automaticky')
198
+ .option('--json', 'Výstup jako JSON')
199
+ .action(async (domain, options) => {
200
+ const spinner = ora('Přidávám DNS záznam...').start();
201
+ try {
202
+ const client = new WapiClient(getCredentials());
203
+ const response = await client.dnsRowAdd({
204
+ domain,
205
+ name: options.name === '@' ? '' : options.name,
206
+ type: options.type.toUpperCase(),
207
+ rdata: options.data,
208
+ ttl: parseInt(options.ttl),
209
+ comment: options.comment,
210
+ });
211
+ spinner.stop();
212
+
213
+ formatResponse(response, { format: options.json ? 'json' : undefined });
214
+
215
+ if (isSuccess(parseInt(response.code)) && options.commit !== false) {
216
+ const commitSpinner = ora('Ukládám změny...').start();
217
+ await client.dnsDomainCommit(domain);
218
+ commitSpinner.stop();
219
+ printSuccess('Změny uloženy');
220
+ }
221
+ } catch (error) {
222
+ spinner.stop();
223
+ printError(error);
224
+ process.exit(1);
225
+ }
226
+ });
227
+
228
+ // Update DNS record
229
+ dns
230
+ .command('record-update <domain> <recordId>')
231
+ .alias('update-record')
232
+ .description('Úprava DNS záznamu')
233
+ .option('-d, --data <data>', 'Nová data záznamu')
234
+ .option('--ttl <seconds>', 'Nové TTL v sekundách')
235
+ .option('--no-commit', 'Neuložit změny automaticky')
236
+ .option('--json', 'Výstup jako JSON')
237
+ .action(async (domain, recordId, options) => {
238
+ if (!options.data && !options.ttl) {
239
+ printError('Alespoň --data nebo --ttl je povinné');
240
+ process.exit(1);
241
+ }
242
+
243
+ const spinner = ora('Upravuji DNS záznam...').start();
244
+ try {
245
+ const client = new WapiClient(getCredentials());
246
+ const response = await client.dnsRowUpdate(domain, recordId, {
247
+ rdata: options.data,
248
+ ttl: options.ttl ? parseInt(options.ttl) : undefined,
249
+ });
250
+ spinner.stop();
251
+
252
+ formatResponse(response, { format: options.json ? 'json' : undefined });
253
+
254
+ if (isSuccess(parseInt(response.code)) && options.commit !== false) {
255
+ const commitSpinner = ora('Ukládám změny...').start();
256
+ await client.dnsDomainCommit(domain);
257
+ commitSpinner.stop();
258
+ printSuccess('Změny uloženy');
259
+ }
260
+ } catch (error) {
261
+ spinner.stop();
262
+ printError(error);
263
+ process.exit(1);
264
+ }
265
+ });
266
+
267
+ // Delete DNS record
268
+ dns
269
+ .command('record-delete <domain> <recordId>')
270
+ .alias('rm-record')
271
+ .description('Smazání DNS záznamu')
272
+ .option('-y, --yes', 'Přeskočit potvrzení')
273
+ .option('--no-commit', 'Neuložit změny automaticky')
274
+ .action(async (domain, recordId, options) => {
275
+ if (!options.yes) {
276
+ const { confirm } = await inquirer.prompt([{
277
+ type: 'confirm',
278
+ name: 'confirm',
279
+ message: `Opravdu chceš smazat záznam ${recordId}?`,
280
+ default: false,
281
+ }]);
282
+
283
+ if (!confirm) {
284
+ printInfo('Zrušeno');
285
+ return;
286
+ }
287
+ }
288
+
289
+ const spinner = ora('Mažu DNS záznam...').start();
290
+ try {
291
+ const client = new WapiClient(getCredentials());
292
+ const response = await client.dnsRowDelete(domain, recordId);
293
+ spinner.stop();
294
+
295
+ formatResponse(response);
296
+
297
+ if (isSuccess(parseInt(response.code)) && options.commit !== false) {
298
+ const commitSpinner = ora('Ukládám změny...').start();
299
+ await client.dnsDomainCommit(domain);
300
+ commitSpinner.stop();
301
+ printSuccess('Změny uloženy');
302
+ }
303
+ } catch (error) {
304
+ spinner.stop();
305
+ printError(error);
306
+ process.exit(1);
307
+ }
308
+ });
309
+
310
+ // Quick add common records
311
+ dns
312
+ .command('quick-add <domain>')
313
+ .description('Rychlé přidání běžných DNS záznamů')
314
+ .option('-a, --a <ip>', 'Přidat A záznam')
315
+ .option('--aaaa <ip>', 'Přidat AAAA záznam')
316
+ .option('-c, --cname <target>', 'Přidat CNAME záznam')
317
+ .option('-m, --mx <server>', 'Přidat MX záznam')
318
+ .option('--mx-priority <priority>', 'Priorita MX', '10')
319
+ .option('-t, --txt <value>', 'Přidat TXT záznam')
320
+ .option('-n, --name <name>', 'Název záznamu (výchozí: @)', '@')
321
+ .option('--ttl <seconds>', 'TTL', '3600')
322
+ .action(async (domain, options) => {
323
+ const client = new WapiClient(getCredentials());
324
+ const name = options.name === '@' ? '' : options.name;
325
+ const ttl = parseInt(options.ttl);
326
+ let added = 0;
327
+
328
+ try {
329
+ if (options.a) {
330
+ const spinner = ora(`Přidávám A záznam: ${options.a}...`).start();
331
+ await client.dnsRowAdd({ domain, name, type: 'A', rdata: options.a, ttl });
332
+ spinner.succeed(`Přidán A záznam: ${options.a}`);
333
+ added++;
334
+ }
335
+
336
+ if (options.aaaa) {
337
+ const spinner = ora(`Přidávám AAAA záznam: ${options.aaaa}...`).start();
338
+ await client.dnsRowAdd({ domain, name, type: 'AAAA', rdata: options.aaaa, ttl });
339
+ spinner.succeed(`Přidán AAAA záznam: ${options.aaaa}`);
340
+ added++;
341
+ }
342
+
343
+ if (options.cname) {
344
+ const spinner = ora(`Přidávám CNAME záznam: ${options.cname}...`).start();
345
+ await client.dnsRowAdd({ domain, name, type: 'CNAME', rdata: options.cname, ttl });
346
+ spinner.succeed(`Přidán CNAME záznam: ${options.cname}`);
347
+ added++;
348
+ }
349
+
350
+ if (options.mx) {
351
+ const mxData = `${options.mxPriority} ${options.mx}`;
352
+ const spinner = ora(`Přidávám MX záznam: ${mxData}...`).start();
353
+ await client.dnsRowAdd({ domain, name, type: 'MX', rdata: mxData, ttl });
354
+ spinner.succeed(`Přidán MX záznam: ${mxData}`);
355
+ added++;
356
+ }
357
+
358
+ if (options.txt) {
359
+ const spinner = ora(`Přidávám TXT záznam...`).start();
360
+ await client.dnsRowAdd({ domain, name, type: 'TXT', rdata: options.txt, ttl });
361
+ spinner.succeed(`Přidán TXT záznam`);
362
+ added++;
363
+ }
364
+
365
+ if (added > 0) {
366
+ const commitSpinner = ora('Ukládám změny...').start();
367
+ await client.dnsDomainCommit(domain);
368
+ commitSpinner.succeed('Změny uloženy');
369
+ } else {
370
+ printWarning('Nebyly zadány žádné záznamy. Použij -a, --aaaa, -c, -m, nebo -t.');
371
+ }
372
+ } catch (error) {
373
+ printError(error);
374
+ process.exit(1);
375
+ }
376
+ });
377
+
378
+ return dns;
379
+ }
380
+
381
+ function truncate(str, len) {
382
+ if (!str) return '-';
383
+ return str.length > len ? str.substring(0, len - 3) + '...' : str;
384
+ }