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.
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/package.json +52 -0
- package/src/commands/config.js +196 -0
- package/src/commands/contact.js +210 -0
- package/src/commands/dns.js +384 -0
- package/src/commands/domain.js +329 -0
- package/src/index.js +240 -0
- package/src/lib/config.js +72 -0
- package/src/lib/locale.js +112 -0
- package/src/lib/output.js +191 -0
- package/src/lib/ui.js +263 -0
- package/src/lib/wapi.js +323 -0
|
@@ -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
|
+
}
|