porkbun-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.
Files changed (3) hide show
  1. package/README.md +225 -0
  2. package/dist/cli.js +1418 -0
  3. package/package.json +56 -0
package/dist/cli.js ADDED
@@ -0,0 +1,1418 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli/index.ts
4
+ import "dotenv/config";
5
+ import { defineCommand as defineCommand8, runMain } from "citty";
6
+
7
+ // src/cli/commands/dns.ts
8
+ import { defineCommand } from "citty";
9
+
10
+ // src/cli/config.ts
11
+ import { PorkbunClient } from "porkbun-sdk";
12
+ var getClient = () => {
13
+ const apikey = process.env.PORKBUN_API_KEY;
14
+ const secretapikey = process.env.PORKBUN_API_SECRET;
15
+ if (!apikey || !secretapikey) {
16
+ console.error(
17
+ JSON.stringify({
18
+ error: "Missing credentials",
19
+ message: "Set PORKBUN_API_KEY and PORKBUN_API_SECRET environment variables"
20
+ })
21
+ );
22
+ process.exit(1);
23
+ }
24
+ return new PorkbunClient({ apikey, secretapikey });
25
+ };
26
+
27
+ // src/cli/output.ts
28
+ import Table from "cli-table3";
29
+ import consola from "consola";
30
+ var resolveValue = (row, col) => {
31
+ const val = col.get ? col.get(row) : row[col.key];
32
+ if (val === null || val === void 0) return "";
33
+ return String(val);
34
+ };
35
+ var autoColumns = (data) => {
36
+ const keys = /* @__PURE__ */ new Set();
37
+ for (const row of data) {
38
+ for (const key of Object.keys(row)) {
39
+ keys.add(key);
40
+ }
41
+ }
42
+ return [...keys].map((key) => ({ key, header: key }));
43
+ };
44
+ var unwrapData = (data) => {
45
+ if (Array.isArray(data)) return data;
46
+ if (data && typeof data === "object") {
47
+ const obj = data;
48
+ let bestKey = "";
49
+ let bestLen = 0;
50
+ for (const [key, val] of Object.entries(obj)) {
51
+ if (Array.isArray(val) && val.length > bestLen) {
52
+ bestKey = key;
53
+ bestLen = val.length;
54
+ }
55
+ }
56
+ if (bestKey) return obj[bestKey];
57
+ }
58
+ return [data];
59
+ };
60
+ var outputTable = (data, columns) => {
61
+ const rows = unwrapData(data);
62
+ if (rows.length === 0) {
63
+ consola.info("No data to display");
64
+ return;
65
+ }
66
+ const cols = columns ?? autoColumns(rows);
67
+ const table = new Table({
68
+ head: cols.map((c) => c.header),
69
+ style: { head: ["cyan"], border: ["gray"] }
70
+ });
71
+ for (const row of rows) {
72
+ table.push(cols.map((col) => resolveValue(row, col)));
73
+ }
74
+ console.log(table.toString());
75
+ };
76
+ var escapeCsv = (val) => {
77
+ if (val.includes(",") || val.includes('"') || val.includes("\n")) {
78
+ return `"${val.replace(/"/g, '""')}"`;
79
+ }
80
+ return val;
81
+ };
82
+ var outputCsv = (data, columns) => {
83
+ const rows = unwrapData(data);
84
+ if (rows.length === 0) return;
85
+ const cols = columns ?? autoColumns(rows);
86
+ console.log(cols.map((c) => escapeCsv(c.header)).join(","));
87
+ for (const row of rows) {
88
+ console.log(cols.map((col) => escapeCsv(resolveValue(row, col))).join(","));
89
+ }
90
+ };
91
+ var output = (data, options) => {
92
+ const format = options?.format ?? "json";
93
+ switch (format) {
94
+ case "table":
95
+ outputTable(data, options?.columns);
96
+ break;
97
+ case "csv":
98
+ outputCsv(data, options?.columns);
99
+ break;
100
+ default:
101
+ console.log(JSON.stringify(data, null, 2));
102
+ }
103
+ };
104
+ var outputError = (error) => {
105
+ if (error && typeof error === "object" && "toJSON" in error) {
106
+ console.error(
107
+ JSON.stringify(error.toJSON(), null, 2)
108
+ );
109
+ } else {
110
+ console.error(
111
+ JSON.stringify(
112
+ {
113
+ error: "UnknownError",
114
+ message: error instanceof Error ? error.message : String(error)
115
+ },
116
+ null,
117
+ 2
118
+ )
119
+ );
120
+ }
121
+ process.exit(1);
122
+ };
123
+
124
+ // src/cli/table-columns.ts
125
+ var domainColumns = [
126
+ { key: "domain", header: "Domain" },
127
+ { key: "status", header: "Status" },
128
+ { key: "tld", header: "TLD" },
129
+ { key: "createDate", header: "Created" },
130
+ { key: "expireDate", header: "Expires" },
131
+ {
132
+ key: "autoRenew",
133
+ header: "Auto-Renew",
134
+ get: (r) => String(r.autoRenew) === "1" ? "on" : "off"
135
+ },
136
+ { key: "securityLock", header: "Lock" }
137
+ ];
138
+ var dnsColumns = [
139
+ { key: "id", header: "ID" },
140
+ { key: "name", header: "Name" },
141
+ { key: "type", header: "Type" },
142
+ { key: "content", header: "Content" },
143
+ { key: "ttl", header: "TTL" },
144
+ { key: "prio", header: "Priority" },
145
+ { key: "notes", header: "Notes" }
146
+ ];
147
+ var urlForwardColumns = [
148
+ { key: "id", header: "ID" },
149
+ { key: "subdomain", header: "Subdomain" },
150
+ { key: "location", header: "Location" },
151
+ { key: "type", header: "Type" },
152
+ { key: "includePath", header: "Include Path" },
153
+ { key: "wildcard", header: "Wildcard" }
154
+ ];
155
+ var glueColumns = [
156
+ { key: "hostname", header: "Hostname" },
157
+ {
158
+ key: "ips",
159
+ header: "IPs",
160
+ get: (r) => Array.isArray(r.ips) ? r.ips.join(", ") : String(r.ips ?? "")
161
+ }
162
+ ];
163
+ var dnssecColumns = [
164
+ { key: "keyTag", header: "Key Tag" },
165
+ { key: "alg", header: "Algorithm" },
166
+ { key: "digestType", header: "Digest Type" },
167
+ { key: "digest", header: "Digest" }
168
+ ];
169
+
170
+ // src/cli/commands/dns.ts
171
+ var list = defineCommand({
172
+ meta: { name: "list", description: "List DNS records for a domain" },
173
+ args: {
174
+ domain: {
175
+ type: "positional",
176
+ description: "Domain name",
177
+ required: true
178
+ },
179
+ id: {
180
+ type: "string",
181
+ description: "Filter by record ID"
182
+ },
183
+ type: {
184
+ type: "string",
185
+ description: "Filter by record type (A, CNAME, MX, etc.)"
186
+ },
187
+ subdomain: {
188
+ type: "string",
189
+ description: "Filter by subdomain (used with --type)"
190
+ },
191
+ format: {
192
+ type: "string",
193
+ description: "Output format: json, table, csv",
194
+ default: "json"
195
+ }
196
+ },
197
+ async run({ args }) {
198
+ try {
199
+ const client = getClient();
200
+ const records = args.type ? await client.dns.retrieveByNameType(
201
+ args.domain,
202
+ args.type,
203
+ args.subdomain
204
+ ) : await client.dns.retrieve(args.domain, args.id);
205
+ output(records, {
206
+ format: args.format,
207
+ columns: dnsColumns
208
+ });
209
+ } catch (e) {
210
+ outputError(e);
211
+ }
212
+ }
213
+ });
214
+ var create = defineCommand({
215
+ meta: { name: "create", description: "Create a DNS record" },
216
+ args: {
217
+ domain: {
218
+ type: "positional",
219
+ description: "Domain name",
220
+ required: true
221
+ },
222
+ type: {
223
+ type: "string",
224
+ description: "Record type (A, CNAME, MX, TXT, AAAA, etc.)",
225
+ required: true
226
+ },
227
+ content: {
228
+ type: "string",
229
+ description: "Record content/value",
230
+ required: true
231
+ },
232
+ name: {
233
+ type: "string",
234
+ description: "Subdomain (empty for root, * for wildcard)"
235
+ },
236
+ ttl: {
237
+ type: "string",
238
+ description: "TTL in seconds (min 600)"
239
+ },
240
+ prio: {
241
+ type: "string",
242
+ description: "Priority (for MX, SRV records)"
243
+ },
244
+ notes: {
245
+ type: "string",
246
+ description: "Notes for this record"
247
+ },
248
+ "dry-run": {
249
+ type: "boolean",
250
+ description: "Preview the request without executing",
251
+ default: false
252
+ },
253
+ format: {
254
+ type: "string",
255
+ description: "Output format: json, table, csv",
256
+ default: "json"
257
+ }
258
+ },
259
+ async run({ args }) {
260
+ try {
261
+ const params = {
262
+ type: args.type,
263
+ content: args.content,
264
+ ...args.name && { name: args.name },
265
+ ...args.ttl && { ttl: Number(args.ttl) },
266
+ ...args.prio && { prio: Number(args.prio) },
267
+ ...args.notes && { notes: args.notes }
268
+ };
269
+ if (args["dry-run"]) {
270
+ output({
271
+ dry_run: true,
272
+ domain: args.domain,
273
+ payload: params
274
+ });
275
+ return;
276
+ }
277
+ const client = getClient();
278
+ const result = await client.dns.create(args.domain, params);
279
+ output(result, { format: args.format });
280
+ } catch (e) {
281
+ outputError(e);
282
+ }
283
+ }
284
+ });
285
+ var edit = defineCommand({
286
+ meta: { name: "edit", description: "Edit a DNS record by ID" },
287
+ args: {
288
+ domain: {
289
+ type: "positional",
290
+ description: "Domain name",
291
+ required: true
292
+ },
293
+ id: {
294
+ type: "string",
295
+ description: "Record ID to edit",
296
+ required: true
297
+ },
298
+ type: {
299
+ type: "string",
300
+ description: "Record type",
301
+ required: true
302
+ },
303
+ content: {
304
+ type: "string",
305
+ description: "Record content/value",
306
+ required: true
307
+ },
308
+ name: {
309
+ type: "string",
310
+ description: "Subdomain"
311
+ },
312
+ ttl: {
313
+ type: "string",
314
+ description: "TTL in seconds"
315
+ },
316
+ prio: {
317
+ type: "string",
318
+ description: "Priority"
319
+ },
320
+ notes: {
321
+ type: "string",
322
+ description: "Notes"
323
+ },
324
+ "dry-run": {
325
+ type: "boolean",
326
+ description: "Preview the request without executing",
327
+ default: false
328
+ },
329
+ format: {
330
+ type: "string",
331
+ description: "Output format: json, table, csv",
332
+ default: "json"
333
+ }
334
+ },
335
+ async run({ args }) {
336
+ try {
337
+ const params = {
338
+ type: args.type,
339
+ content: args.content,
340
+ ...args.name && { name: args.name },
341
+ ...args.ttl && { ttl: Number(args.ttl) },
342
+ ...args.prio && { prio: Number(args.prio) },
343
+ ...args.notes !== void 0 && { notes: args.notes }
344
+ };
345
+ if (args["dry-run"]) {
346
+ output({
347
+ dry_run: true,
348
+ domain: args.domain,
349
+ recordId: args.id,
350
+ payload: params
351
+ });
352
+ return;
353
+ }
354
+ const client = getClient();
355
+ const result = await client.dns.edit(args.domain, args.id, params);
356
+ output(result, { format: args.format });
357
+ } catch (e) {
358
+ outputError(e);
359
+ }
360
+ }
361
+ });
362
+ var editByNameType = defineCommand({
363
+ meta: {
364
+ name: "edit-by-name-type",
365
+ description: "Edit DNS records by domain, type and subdomain"
366
+ },
367
+ args: {
368
+ domain: {
369
+ type: "positional",
370
+ description: "Domain name",
371
+ required: true
372
+ },
373
+ type: {
374
+ type: "string",
375
+ description: "Record type",
376
+ required: true
377
+ },
378
+ content: {
379
+ type: "string",
380
+ description: "Record content/value",
381
+ required: true
382
+ },
383
+ subdomain: {
384
+ type: "string",
385
+ description: "Subdomain"
386
+ },
387
+ ttl: {
388
+ type: "string",
389
+ description: "TTL in seconds"
390
+ },
391
+ prio: {
392
+ type: "string",
393
+ description: "Priority"
394
+ },
395
+ notes: {
396
+ type: "string",
397
+ description: "Notes"
398
+ },
399
+ "dry-run": {
400
+ type: "boolean",
401
+ description: "Preview the request without executing",
402
+ default: false
403
+ },
404
+ format: {
405
+ type: "string",
406
+ description: "Output format: json, table, csv",
407
+ default: "json"
408
+ }
409
+ },
410
+ async run({ args }) {
411
+ try {
412
+ const params = {
413
+ content: args.content,
414
+ ...args.ttl && { ttl: Number(args.ttl) },
415
+ ...args.prio && { prio: Number(args.prio) },
416
+ ...args.notes !== void 0 && { notes: args.notes }
417
+ };
418
+ if (args["dry-run"]) {
419
+ output({
420
+ dry_run: true,
421
+ domain: args.domain,
422
+ type: args.type,
423
+ subdomain: args.subdomain ?? "(root)",
424
+ payload: params
425
+ });
426
+ return;
427
+ }
428
+ const client = getClient();
429
+ const result = await client.dns.editByNameType(
430
+ args.domain,
431
+ args.type,
432
+ args.subdomain,
433
+ params
434
+ );
435
+ output(result, { format: args.format });
436
+ } catch (e) {
437
+ outputError(e);
438
+ }
439
+ }
440
+ });
441
+ var deleteRecord = defineCommand({
442
+ meta: { name: "delete", description: "Delete a DNS record by ID" },
443
+ args: {
444
+ domain: {
445
+ type: "positional",
446
+ description: "Domain name",
447
+ required: true
448
+ },
449
+ id: {
450
+ type: "string",
451
+ description: "Record ID to delete",
452
+ required: true
453
+ },
454
+ "dry-run": {
455
+ type: "boolean",
456
+ description: "Preview the request without executing",
457
+ default: false
458
+ },
459
+ format: {
460
+ type: "string",
461
+ description: "Output format: json, table, csv",
462
+ default: "json"
463
+ }
464
+ },
465
+ async run({ args }) {
466
+ try {
467
+ if (args["dry-run"]) {
468
+ output({
469
+ dry_run: true,
470
+ domain: args.domain,
471
+ action: "delete_dns_record",
472
+ recordId: args.id
473
+ });
474
+ return;
475
+ }
476
+ const client = getClient();
477
+ const result = await client.dns.delete(args.domain, args.id);
478
+ output(result, { format: args.format });
479
+ } catch (e) {
480
+ outputError(e);
481
+ }
482
+ }
483
+ });
484
+ var deleteByNameType = defineCommand({
485
+ meta: {
486
+ name: "delete-by-name-type",
487
+ description: "Delete DNS records by domain, type and subdomain"
488
+ },
489
+ args: {
490
+ domain: {
491
+ type: "positional",
492
+ description: "Domain name",
493
+ required: true
494
+ },
495
+ type: {
496
+ type: "string",
497
+ description: "Record type",
498
+ required: true
499
+ },
500
+ subdomain: {
501
+ type: "string",
502
+ description: "Subdomain"
503
+ },
504
+ "dry-run": {
505
+ type: "boolean",
506
+ description: "Preview the request without executing",
507
+ default: false
508
+ },
509
+ format: {
510
+ type: "string",
511
+ description: "Output format: json, table, csv",
512
+ default: "json"
513
+ }
514
+ },
515
+ async run({ args }) {
516
+ try {
517
+ if (args["dry-run"]) {
518
+ output({
519
+ dry_run: true,
520
+ domain: args.domain,
521
+ action: "delete_dns_by_name_type",
522
+ type: args.type,
523
+ subdomain: args.subdomain ?? "(root)"
524
+ });
525
+ return;
526
+ }
527
+ const client = getClient();
528
+ const result = await client.dns.deleteByNameType(
529
+ args.domain,
530
+ args.type,
531
+ args.subdomain
532
+ );
533
+ output(result, { format: args.format });
534
+ } catch (e) {
535
+ outputError(e);
536
+ }
537
+ }
538
+ });
539
+ var dns = defineCommand({
540
+ meta: { name: "dns", description: "Manage DNS records" },
541
+ subCommands: {
542
+ list,
543
+ create,
544
+ edit,
545
+ "edit-by-name-type": editByNameType,
546
+ delete: deleteRecord,
547
+ "delete-by-name-type": deleteByNameType
548
+ }
549
+ });
550
+
551
+ // src/cli/commands/dnssec.ts
552
+ import { defineCommand as defineCommand2 } from "citty";
553
+ var list2 = defineCommand2({
554
+ meta: { name: "list", description: "List DNSSEC records" },
555
+ args: {
556
+ domain: {
557
+ type: "positional",
558
+ description: "Domain name",
559
+ required: true
560
+ },
561
+ format: {
562
+ type: "string",
563
+ description: "Output format: json, table, csv",
564
+ default: "json"
565
+ }
566
+ },
567
+ async run({ args }) {
568
+ try {
569
+ const client = getClient();
570
+ const records = await client.dnssec.get(args.domain);
571
+ if (args.format === "table" || args.format === "csv") {
572
+ const rows = Object.values(records);
573
+ output(rows, {
574
+ format: args.format,
575
+ columns: dnssecColumns
576
+ });
577
+ } else {
578
+ output(records);
579
+ }
580
+ } catch (e) {
581
+ outputError(e);
582
+ }
583
+ }
584
+ });
585
+ var create2 = defineCommand2({
586
+ meta: { name: "create", description: "Create a DNSSEC record" },
587
+ args: {
588
+ domain: {
589
+ type: "positional",
590
+ description: "Domain name",
591
+ required: true
592
+ },
593
+ "key-tag": {
594
+ type: "string",
595
+ description: "Key tag",
596
+ required: true
597
+ },
598
+ alg: {
599
+ type: "string",
600
+ description: "DS Data algorithm",
601
+ required: true
602
+ },
603
+ "digest-type": {
604
+ type: "string",
605
+ description: "Digest type",
606
+ required: true
607
+ },
608
+ digest: {
609
+ type: "string",
610
+ description: "Digest",
611
+ required: true
612
+ },
613
+ "dry-run": {
614
+ type: "boolean",
615
+ description: "Preview the request without executing",
616
+ default: false
617
+ },
618
+ format: {
619
+ type: "string",
620
+ description: "Output format: json, table, csv",
621
+ default: "json"
622
+ }
623
+ },
624
+ async run({ args }) {
625
+ try {
626
+ const params = {
627
+ keyTag: args["key-tag"],
628
+ alg: args.alg,
629
+ digestType: args["digest-type"],
630
+ digest: args.digest
631
+ };
632
+ if (args["dry-run"]) {
633
+ output({
634
+ dry_run: true,
635
+ domain: args.domain,
636
+ payload: params
637
+ });
638
+ return;
639
+ }
640
+ const client = getClient();
641
+ const result = await client.dnssec.create(args.domain, params);
642
+ output(result, { format: args.format });
643
+ } catch (e) {
644
+ outputError(e);
645
+ }
646
+ }
647
+ });
648
+ var deleteRecord2 = defineCommand2({
649
+ meta: { name: "delete", description: "Delete a DNSSEC record" },
650
+ args: {
651
+ domain: {
652
+ type: "positional",
653
+ description: "Domain name",
654
+ required: true
655
+ },
656
+ "key-tag": {
657
+ type: "string",
658
+ description: "Key tag to delete",
659
+ required: true
660
+ },
661
+ "dry-run": {
662
+ type: "boolean",
663
+ description: "Preview the request without executing",
664
+ default: false
665
+ },
666
+ format: {
667
+ type: "string",
668
+ description: "Output format: json, table, csv",
669
+ default: "json"
670
+ }
671
+ },
672
+ async run({ args }) {
673
+ try {
674
+ if (args["dry-run"]) {
675
+ output({
676
+ dry_run: true,
677
+ domain: args.domain,
678
+ action: "delete_dnssec",
679
+ keyTag: args["key-tag"]
680
+ });
681
+ return;
682
+ }
683
+ const client = getClient();
684
+ const result = await client.dnssec.delete(args.domain, args["key-tag"]);
685
+ output(result, { format: args.format });
686
+ } catch (e) {
687
+ outputError(e);
688
+ }
689
+ }
690
+ });
691
+ var dnssec = defineCommand2({
692
+ meta: { name: "dnssec", description: "Manage DNSSEC records" },
693
+ subCommands: { list: list2, create: create2, delete: deleteRecord2 }
694
+ });
695
+
696
+ // src/cli/commands/domain.ts
697
+ import { defineCommand as defineCommand3 } from "citty";
698
+ var list3 = defineCommand3({
699
+ meta: { name: "list", description: "List all domains" },
700
+ args: {
701
+ format: {
702
+ type: "string",
703
+ description: "Output format: json, table, csv",
704
+ default: "json"
705
+ },
706
+ start: {
707
+ type: "string",
708
+ description: "Pagination start index (increments of 1000)"
709
+ },
710
+ labels: {
711
+ type: "boolean",
712
+ description: "Include domain labels",
713
+ default: false
714
+ }
715
+ },
716
+ async run({ args }) {
717
+ try {
718
+ const client = getClient();
719
+ const result = await client.domain.listAll({
720
+ start: args.start ? Number(args.start) : void 0,
721
+ includeLabels: args.labels
722
+ });
723
+ output(result.domains, {
724
+ format: args.format,
725
+ columns: domainColumns
726
+ });
727
+ } catch (e) {
728
+ outputError(e);
729
+ }
730
+ }
731
+ });
732
+ var check = defineCommand3({
733
+ meta: { name: "check", description: "Check domain availability" },
734
+ args: {
735
+ domain: {
736
+ type: "positional",
737
+ description: "Domain name to check (e.g. example.com)",
738
+ required: true
739
+ },
740
+ format: {
741
+ type: "string",
742
+ description: "Output format: json, table, csv",
743
+ default: "json"
744
+ }
745
+ },
746
+ async run({ args }) {
747
+ try {
748
+ const client = getClient();
749
+ const result = await client.domain.check(args.domain);
750
+ output(result, { format: args.format });
751
+ } catch (e) {
752
+ outputError(e);
753
+ }
754
+ }
755
+ });
756
+ var create3 = defineCommand3({
757
+ meta: { name: "create", description: "Register a new domain" },
758
+ args: {
759
+ domain: {
760
+ type: "positional",
761
+ description: "Domain name to register",
762
+ required: true
763
+ },
764
+ cost: {
765
+ type: "string",
766
+ description: "Cost in cents (integer)",
767
+ required: true
768
+ },
769
+ "dry-run": {
770
+ type: "boolean",
771
+ description: "Preview the request without executing",
772
+ default: false
773
+ },
774
+ format: {
775
+ type: "string",
776
+ description: "Output format: json, table, csv",
777
+ default: "json"
778
+ }
779
+ },
780
+ async run({ args }) {
781
+ try {
782
+ const params = {
783
+ cost: Number(args.cost),
784
+ agreeToTerms: "yes"
785
+ };
786
+ if (args["dry-run"]) {
787
+ output({ dry_run: true, domain: args.domain, payload: params });
788
+ return;
789
+ }
790
+ const client = getClient();
791
+ const result = await client.domain.create(args.domain, params);
792
+ output(result, { format: args.format });
793
+ } catch (e) {
794
+ outputError(e);
795
+ }
796
+ }
797
+ });
798
+ var nsGet = defineCommand3({
799
+ meta: { name: "get", description: "Get name servers for a domain" },
800
+ args: {
801
+ domain: {
802
+ type: "positional",
803
+ description: "Domain name",
804
+ required: true
805
+ },
806
+ format: {
807
+ type: "string",
808
+ description: "Output format: json, table, csv",
809
+ default: "json"
810
+ }
811
+ },
812
+ async run({ args }) {
813
+ try {
814
+ const client = getClient();
815
+ const result = await client.domain.getNameServers(args.domain);
816
+ if (args.format === "table" || args.format === "csv") {
817
+ output(
818
+ result.ns.map((ns2, i) => ({ index: i + 1, nameserver: ns2 })),
819
+ {
820
+ format: args.format,
821
+ columns: [
822
+ { key: "index", header: "#" },
823
+ { key: "nameserver", header: "Name Server" }
824
+ ]
825
+ }
826
+ );
827
+ } else {
828
+ output(result);
829
+ }
830
+ } catch (e) {
831
+ outputError(e);
832
+ }
833
+ }
834
+ });
835
+ var nsUpdate = defineCommand3({
836
+ meta: { name: "update", description: "Update name servers for a domain" },
837
+ args: {
838
+ domain: {
839
+ type: "positional",
840
+ description: "Domain name",
841
+ required: true
842
+ },
843
+ ns: {
844
+ type: "string",
845
+ description: "Name servers (comma-separated)",
846
+ required: true
847
+ },
848
+ "dry-run": {
849
+ type: "boolean",
850
+ description: "Preview the request without executing",
851
+ default: false
852
+ },
853
+ format: {
854
+ type: "string",
855
+ description: "Output format: json, table, csv",
856
+ default: "json"
857
+ }
858
+ },
859
+ async run({ args }) {
860
+ try {
861
+ const nameservers = args.ns.split(",").map((s) => s.trim());
862
+ if (args["dry-run"]) {
863
+ output({
864
+ dry_run: true,
865
+ domain: args.domain,
866
+ payload: { ns: nameservers }
867
+ });
868
+ return;
869
+ }
870
+ const client = getClient();
871
+ const result = await client.domain.updateNameServers(
872
+ args.domain,
873
+ nameservers
874
+ );
875
+ output(result, { format: args.format });
876
+ } catch (e) {
877
+ outputError(e);
878
+ }
879
+ }
880
+ });
881
+ var ns = defineCommand3({
882
+ meta: { name: "ns", description: "Manage domain name servers" },
883
+ subCommands: { get: nsGet, update: nsUpdate }
884
+ });
885
+ var autoRenew = defineCommand3({
886
+ meta: { name: "auto-renew", description: "Update auto-renew status" },
887
+ args: {
888
+ domain: {
889
+ type: "positional",
890
+ description: "Domain name",
891
+ required: true
892
+ },
893
+ status: {
894
+ type: "string",
895
+ description: "Auto-renew status: on or off",
896
+ required: true
897
+ },
898
+ "dry-run": {
899
+ type: "boolean",
900
+ description: "Preview the request without executing",
901
+ default: false
902
+ },
903
+ format: {
904
+ type: "string",
905
+ description: "Output format: json, table, csv",
906
+ default: "json"
907
+ }
908
+ },
909
+ async run({ args }) {
910
+ try {
911
+ const status = args.status;
912
+ if (status !== "on" && status !== "off") {
913
+ outputError(new Error("Status must be 'on' or 'off'"));
914
+ return;
915
+ }
916
+ if (args["dry-run"]) {
917
+ output({
918
+ dry_run: true,
919
+ domain: args.domain,
920
+ payload: { status }
921
+ });
922
+ return;
923
+ }
924
+ const client = getClient();
925
+ const result = await client.domain.updateAutoRenew(
926
+ { status },
927
+ args.domain
928
+ );
929
+ output(result, { format: args.format });
930
+ } catch (e) {
931
+ outputError(e);
932
+ }
933
+ }
934
+ });
935
+ var forwardList = defineCommand3({
936
+ meta: { name: "list", description: "List URL forwards for a domain" },
937
+ args: {
938
+ domain: {
939
+ type: "positional",
940
+ description: "Domain name",
941
+ required: true
942
+ },
943
+ format: {
944
+ type: "string",
945
+ description: "Output format: json, table, csv",
946
+ default: "json"
947
+ }
948
+ },
949
+ async run({ args }) {
950
+ try {
951
+ const client = getClient();
952
+ const result = await client.domain.getUrlForwarding(args.domain);
953
+ output(result, {
954
+ format: args.format,
955
+ columns: urlForwardColumns
956
+ });
957
+ } catch (e) {
958
+ outputError(e);
959
+ }
960
+ }
961
+ });
962
+ var forwardAdd = defineCommand3({
963
+ meta: { name: "add", description: "Add a URL forward" },
964
+ args: {
965
+ domain: {
966
+ type: "positional",
967
+ description: "Domain name",
968
+ required: true
969
+ },
970
+ location: {
971
+ type: "string",
972
+ description: "Destination URL",
973
+ required: true
974
+ },
975
+ subdomain: {
976
+ type: "string",
977
+ description: "Subdomain (empty for root)"
978
+ },
979
+ type: {
980
+ type: "string",
981
+ description: "Redirect type: temporary or permanent",
982
+ default: "permanent"
983
+ },
984
+ "include-path": {
985
+ type: "string",
986
+ description: "Include path: yes or no",
987
+ default: "no"
988
+ },
989
+ wildcard: {
990
+ type: "string",
991
+ description: "Wildcard: yes or no",
992
+ default: "no"
993
+ },
994
+ "dry-run": {
995
+ type: "boolean",
996
+ description: "Preview the request without executing",
997
+ default: false
998
+ },
999
+ format: {
1000
+ type: "string",
1001
+ description: "Output format: json, table, csv",
1002
+ default: "json"
1003
+ }
1004
+ },
1005
+ async run({ args }) {
1006
+ try {
1007
+ const params = {
1008
+ location: args.location,
1009
+ type: args.type,
1010
+ includePath: args["include-path"],
1011
+ wildcard: args.wildcard,
1012
+ ...args.subdomain && { subdomain: args.subdomain }
1013
+ };
1014
+ if (args["dry-run"]) {
1015
+ output({
1016
+ dry_run: true,
1017
+ domain: args.domain,
1018
+ payload: params
1019
+ });
1020
+ return;
1021
+ }
1022
+ const client = getClient();
1023
+ const result = await client.domain.addUrlForward(args.domain, params);
1024
+ output(result, { format: args.format });
1025
+ } catch (e) {
1026
+ outputError(e);
1027
+ }
1028
+ }
1029
+ });
1030
+ var forwardDelete = defineCommand3({
1031
+ meta: { name: "delete", description: "Delete a URL forward" },
1032
+ args: {
1033
+ domain: {
1034
+ type: "positional",
1035
+ description: "Domain name",
1036
+ required: true
1037
+ },
1038
+ id: {
1039
+ type: "string",
1040
+ description: "Forward record ID",
1041
+ required: true
1042
+ },
1043
+ "dry-run": {
1044
+ type: "boolean",
1045
+ description: "Preview the request without executing",
1046
+ default: false
1047
+ },
1048
+ format: {
1049
+ type: "string",
1050
+ description: "Output format: json, table, csv",
1051
+ default: "json"
1052
+ }
1053
+ },
1054
+ async run({ args }) {
1055
+ try {
1056
+ if (args["dry-run"]) {
1057
+ output({
1058
+ dry_run: true,
1059
+ domain: args.domain,
1060
+ action: "delete_url_forward",
1061
+ recordId: args.id
1062
+ });
1063
+ return;
1064
+ }
1065
+ const client = getClient();
1066
+ const result = await client.domain.deleteUrlForward(args.domain, args.id);
1067
+ output(result, { format: args.format });
1068
+ } catch (e) {
1069
+ outputError(e);
1070
+ }
1071
+ }
1072
+ });
1073
+ var forward = defineCommand3({
1074
+ meta: { name: "forward", description: "Manage URL forwarding" },
1075
+ subCommands: { list: forwardList, add: forwardAdd, delete: forwardDelete }
1076
+ });
1077
+ var glueList = defineCommand3({
1078
+ meta: { name: "list", description: "List glue records" },
1079
+ args: {
1080
+ domain: {
1081
+ type: "positional",
1082
+ description: "Domain name",
1083
+ required: true
1084
+ },
1085
+ format: {
1086
+ type: "string",
1087
+ description: "Output format: json, table, csv",
1088
+ default: "json"
1089
+ }
1090
+ },
1091
+ async run({ args }) {
1092
+ try {
1093
+ const client = getClient();
1094
+ const result = await client.domain.getGlueRecords(args.domain);
1095
+ output(result.hosts ?? [], {
1096
+ format: args.format,
1097
+ columns: glueColumns
1098
+ });
1099
+ } catch (e) {
1100
+ outputError(e);
1101
+ }
1102
+ }
1103
+ });
1104
+ var glueCreate = defineCommand3({
1105
+ meta: { name: "create", description: "Create a glue record" },
1106
+ args: {
1107
+ domain: {
1108
+ type: "positional",
1109
+ description: "Domain name",
1110
+ required: true
1111
+ },
1112
+ subdomain: {
1113
+ type: "string",
1114
+ description: "Glue host subdomain",
1115
+ required: true
1116
+ },
1117
+ ips: {
1118
+ type: "string",
1119
+ description: "IP addresses (comma-separated)",
1120
+ required: true
1121
+ },
1122
+ "dry-run": {
1123
+ type: "boolean",
1124
+ description: "Preview the request without executing",
1125
+ default: false
1126
+ },
1127
+ format: {
1128
+ type: "string",
1129
+ description: "Output format: json, table, csv",
1130
+ default: "json"
1131
+ }
1132
+ },
1133
+ async run({ args }) {
1134
+ try {
1135
+ const ips = args.ips.split(",").map((s) => s.trim());
1136
+ if (args["dry-run"]) {
1137
+ output({
1138
+ dry_run: true,
1139
+ domain: args.domain,
1140
+ subdomain: args.subdomain,
1141
+ payload: { ips }
1142
+ });
1143
+ return;
1144
+ }
1145
+ const client = getClient();
1146
+ const result = await client.domain.createGlueRecord(
1147
+ args.domain,
1148
+ args.subdomain,
1149
+ ips
1150
+ );
1151
+ output(result, { format: args.format });
1152
+ } catch (e) {
1153
+ outputError(e);
1154
+ }
1155
+ }
1156
+ });
1157
+ var glueUpdate = defineCommand3({
1158
+ meta: { name: "update", description: "Update a glue record" },
1159
+ args: {
1160
+ domain: {
1161
+ type: "positional",
1162
+ description: "Domain name",
1163
+ required: true
1164
+ },
1165
+ subdomain: {
1166
+ type: "string",
1167
+ description: "Glue host subdomain",
1168
+ required: true
1169
+ },
1170
+ ips: {
1171
+ type: "string",
1172
+ description: "IP addresses (comma-separated)",
1173
+ required: true
1174
+ },
1175
+ "dry-run": {
1176
+ type: "boolean",
1177
+ description: "Preview the request without executing",
1178
+ default: false
1179
+ },
1180
+ format: {
1181
+ type: "string",
1182
+ description: "Output format: json, table, csv",
1183
+ default: "json"
1184
+ }
1185
+ },
1186
+ async run({ args }) {
1187
+ try {
1188
+ const ips = args.ips.split(",").map((s) => s.trim());
1189
+ if (args["dry-run"]) {
1190
+ output({
1191
+ dry_run: true,
1192
+ domain: args.domain,
1193
+ subdomain: args.subdomain,
1194
+ payload: { ips }
1195
+ });
1196
+ return;
1197
+ }
1198
+ const client = getClient();
1199
+ const result = await client.domain.updateGlueRecord(
1200
+ args.domain,
1201
+ args.subdomain,
1202
+ ips
1203
+ );
1204
+ output(result, { format: args.format });
1205
+ } catch (e) {
1206
+ outputError(e);
1207
+ }
1208
+ }
1209
+ });
1210
+ var glueDelete = defineCommand3({
1211
+ meta: { name: "delete", description: "Delete a glue record" },
1212
+ args: {
1213
+ domain: {
1214
+ type: "positional",
1215
+ description: "Domain name",
1216
+ required: true
1217
+ },
1218
+ subdomain: {
1219
+ type: "string",
1220
+ description: "Glue host subdomain",
1221
+ required: true
1222
+ },
1223
+ "dry-run": {
1224
+ type: "boolean",
1225
+ description: "Preview the request without executing",
1226
+ default: false
1227
+ },
1228
+ format: {
1229
+ type: "string",
1230
+ description: "Output format: json, table, csv",
1231
+ default: "json"
1232
+ }
1233
+ },
1234
+ async run({ args }) {
1235
+ try {
1236
+ if (args["dry-run"]) {
1237
+ output({
1238
+ dry_run: true,
1239
+ domain: args.domain,
1240
+ action: "delete_glue_record",
1241
+ subdomain: args.subdomain
1242
+ });
1243
+ return;
1244
+ }
1245
+ const client = getClient();
1246
+ const result = await client.domain.deleteGlueRecord(
1247
+ args.domain,
1248
+ args.subdomain
1249
+ );
1250
+ output(result, { format: args.format });
1251
+ } catch (e) {
1252
+ outputError(e);
1253
+ }
1254
+ }
1255
+ });
1256
+ var glue = defineCommand3({
1257
+ meta: { name: "glue", description: "Manage glue records" },
1258
+ subCommands: {
1259
+ list: glueList,
1260
+ create: glueCreate,
1261
+ update: glueUpdate,
1262
+ delete: glueDelete
1263
+ }
1264
+ });
1265
+ var domain = defineCommand3({
1266
+ meta: { name: "domain", description: "Manage domains" },
1267
+ subCommands: {
1268
+ list: list3,
1269
+ check,
1270
+ create: create3,
1271
+ ns,
1272
+ "auto-renew": autoRenew,
1273
+ forward,
1274
+ glue
1275
+ }
1276
+ });
1277
+
1278
+ // src/cli/commands/ping.ts
1279
+ import { defineCommand as defineCommand4 } from "citty";
1280
+ var ping = defineCommand4({
1281
+ meta: { name: "ping", description: "Test API authentication" },
1282
+ args: {
1283
+ format: {
1284
+ type: "string",
1285
+ description: "Output format: json, table, csv",
1286
+ default: "json"
1287
+ }
1288
+ },
1289
+ async run({ args }) {
1290
+ try {
1291
+ const client = getClient();
1292
+ const result = await client.ping();
1293
+ output(result, { format: args.format });
1294
+ } catch (e) {
1295
+ outputError(e);
1296
+ }
1297
+ }
1298
+ });
1299
+
1300
+ // src/cli/commands/pricing.ts
1301
+ import { defineCommand as defineCommand5 } from "citty";
1302
+ var pricing = defineCommand5({
1303
+ meta: { name: "pricing", description: "Get domain pricing for all TLDs" },
1304
+ args: {
1305
+ format: {
1306
+ type: "string",
1307
+ description: "Output format: json, table, csv",
1308
+ default: "json"
1309
+ },
1310
+ tld: {
1311
+ type: "string",
1312
+ description: "Filter by specific TLD (e.g. com, net, dev)"
1313
+ }
1314
+ },
1315
+ async run({ args }) {
1316
+ try {
1317
+ const client = getClient();
1318
+ const result = await client.pricing.get();
1319
+ if (args.tld) {
1320
+ const tld = args.tld.replace(/^\./, "");
1321
+ const pricing2 = result.pricing[tld];
1322
+ if (!pricing2) {
1323
+ outputError(new Error(`TLD ".${tld}" not found`));
1324
+ return;
1325
+ }
1326
+ output(
1327
+ { tld, ...pricing2 },
1328
+ {
1329
+ format: args.format,
1330
+ columns: [
1331
+ { key: "tld", header: "TLD" },
1332
+ { key: "registration", header: "Registration" },
1333
+ { key: "renewal", header: "Renewal" },
1334
+ { key: "transfer", header: "Transfer" }
1335
+ ]
1336
+ }
1337
+ );
1338
+ return;
1339
+ }
1340
+ if (args.format === "table" || args.format === "csv") {
1341
+ const rows = Object.entries(result.pricing).map(([tld, p]) => ({
1342
+ tld,
1343
+ registration: p.registration,
1344
+ renewal: p.renewal,
1345
+ transfer: p.transfer
1346
+ }));
1347
+ output(rows, {
1348
+ format: args.format,
1349
+ columns: [
1350
+ { key: "tld", header: "TLD" },
1351
+ { key: "registration", header: "Registration" },
1352
+ { key: "renewal", header: "Renewal" },
1353
+ { key: "transfer", header: "Transfer" }
1354
+ ]
1355
+ });
1356
+ } else {
1357
+ output(result);
1358
+ }
1359
+ } catch (e) {
1360
+ outputError(e);
1361
+ }
1362
+ }
1363
+ });
1364
+
1365
+ // src/cli/commands/ssl.ts
1366
+ import { defineCommand as defineCommand6 } from "citty";
1367
+ var ssl = defineCommand6({
1368
+ meta: { name: "ssl", description: "Retrieve SSL certificate bundle" },
1369
+ args: {
1370
+ domain: {
1371
+ type: "positional",
1372
+ description: "Domain name",
1373
+ required: true
1374
+ },
1375
+ format: {
1376
+ type: "string",
1377
+ description: "Output format: json, table, csv",
1378
+ default: "json"
1379
+ }
1380
+ },
1381
+ async run({ args }) {
1382
+ try {
1383
+ const client = getClient();
1384
+ const result = await client.ssl.retrieve(args.domain);
1385
+ output(result, { format: args.format });
1386
+ } catch (e) {
1387
+ outputError(e);
1388
+ }
1389
+ }
1390
+ });
1391
+
1392
+ // src/cli/commands/version.ts
1393
+ import { defineCommand as defineCommand7 } from "citty";
1394
+ var version = defineCommand7({
1395
+ meta: { name: "version", description: "Show CLI version" },
1396
+ run() {
1397
+ console.log("1.0.0");
1398
+ }
1399
+ });
1400
+
1401
+ // src/cli/index.ts
1402
+ var main = defineCommand8({
1403
+ meta: {
1404
+ name: "porkbun",
1405
+ version: "1.0.0",
1406
+ description: "Porkbun CLI \u2014 manage domains, DNS, SSL and more"
1407
+ },
1408
+ subCommands: {
1409
+ ping,
1410
+ pricing,
1411
+ domain,
1412
+ dns,
1413
+ dnssec,
1414
+ ssl,
1415
+ version
1416
+ }
1417
+ });
1418
+ runMain(main);