future-id/mdr-cli

View on GitHub
src/commands/domain/record.ts

Summary

Maintainability
A
1 hr
Test Coverage
import ApiCommand from "../../utils/ApiCommand";
import { logger, Regex, spinner } from "../../utils/Utils";
import { command, metadata, option, Options } from "clime";
import { DNSRecord } from "src/utils/Types";
import { ColorRenderedStyledTable, border, single, color } from "styled-cli-table";
import chalk from "chalk";

const allowedProps = ["id", "type", "host", "address", "priority", "weight", "port"];

class CmdOptions extends Options {
    @option({
        name: "full-domain",
        flag: "f",
        description: "Domain name + TLD",
        required: false
    })
    full_domain!: string;

    @option({
        name: "domain",
        flag: "d",
        description: "Domain name",
        required: false
    })
    domain!: string;

    @option({
        name: "tld",
        flag: "t",
        description: "TLD extension of the domain name",
        required: false
    })
    tld!: string;

    @option({
        name: "template-id",
        flag: "i",
        description: "Template ID",
        required: false
    })
    template_id!: string;

    @option({
        name: "type",
        flag: "r",
        description: "Record type A, AAAA, TXT, MX..... (ALL to show all record types)",
        required: true
    })
    type!: string;

    @option({
        name: "host",
        flag: "h",
        description: "Record host",
        required: false
    })
    host!: string;

    @option({
        name: "property",
        flag: "p",
        description: "Get a certain property e.g. id, type, host, address, priority, weight or port",
        required: false
    })
    property!: string;

    @option({
        name: "quiet",
        flag: "q",
        description: "Disables the loading indicator",
        required: false,
        toggle: true,
        default: false
    })
    quiet!: boolean;
}

@command()
export default class extends ApiCommand {
    @metadata
    async execute(options: CmdOptions): Promise<void> {
        // At least one of these needs to be defined
        if (!options.template_id && !options.full_domain && !options.domain && !options.tld) {
            logger.error("At least one of template_id, full_domain or domain + tld needs to be defined.");
            return;
        }

        // If domain is defined tld needs to be defined and viceversa
        if ((options.domain && !options.tld) || (options.tld && !options.domain)) {
            logger.error("If domain is defined tld also needs to be defined and vice versa.");
            return;
        }

        if (!options.quiet) spinner.start();

        this.api.newRequest(options.quiet);

        // If template id is defined get template details else dns details
        if (options.template_id) {
            this.api.addParam("command", "dns_template_get_details");
            this.api.addParam("template_id", options.template_id);
        } else if (options.full_domain) { // TODO : Test (mdr domain record -f <domain.tld> -r ALL)
            if (!Regex.domain.test(options.full_domain)) {
                logger.error(`Invalid domain, valid patterns are ${chalk.bold("example.com")} and ${chalk.bold("example.co.uk")}`);
                return;
            }

            const split = options.full_domain.split(".");
            const tld = split[split.length - 1];
            const domain = options.full_domain.replace(`.${tld}`, "");
            this.api.addParam("command", "dns_get_details");
            this.api.addParam("domein", domain);
            this.api.addParam("tld", tld);
        } else {
            this.api.addParam("command", "dns_get_details");
            this.api.addParam("domein", options.domain);
            this.api.addParam("tld", options.tld);
        }

        const records: DNSRecord[] = [];
        const response = await this.api.send();

        let recordCount = 0;
        try {
            recordCount = parseInt(response.recordcount);
        } catch (e) { }

        for (let i = 0; i < recordCount; i++) {
            records.push({
                index: String(i + 1),
                id: response[`record_id[${i}]`],
                type: response[`type[${i}]`],
                host: response[`host[${i}]`],
                address: response[`address[${i}]`],
                priority: response[`priority[${i}]`],
                weight: response[`weight[${i}]`],
                port: response[`port[${i}]`]
            });
        }

        // Filter records by type
        let filtered = options.type.toUpperCase() === "ALL"
            ? records
            : records.filter((record) => record.type === options.type.toUpperCase());

        // Filter records by host name
        if (options.host) {
            filtered = filtered.filter((record) => record.host === options.host);
        }

        if (filtered.length <= 0) {
            if (options.quiet) logger.log(0);
            else logger.error(`No record found with type: ${chalk.bold(options.type)} ${options.host ? `and host: ${chalk.bold(options.host)}` : ""}`.trim());
            return;
        }

        // If a property is given log it as plain text else show table of records
        if (options.property && allowedProps.includes(options.property)) {
            if (filtered.length > 1 && !options.quiet) {
                logger.warn("Multiple records found using these filters, only selected the first one in the list.");
            }
            logger.log(filtered[0][options.property]);
        } else {
            const data = [
                ["#", "id", "type", "host", "address", "priority", "weight", "port"]
            ];

            for (const record of filtered) {
                data.push([
                    record.index,
                    record.id,
                    record.type,
                    record.host,
                    record.address,
                    record.priority || "-",
                    record.weight || "-",
                    record.port || "-"
                ]);
            }

            const table = new ColorRenderedStyledTable(data, {
                ...border(true),
                borderCharacters: single,
                paddingLeft: 1,
                paddingRight: 1,
                backgroundColor: color.brightWhite,
                rows: {
                    0: {
                        align: "center",
                        color: color.brightCyan + color.bold
                    }
                },
                columns: {
                    0: {
                        align: "center",
                        color: color.brightCyan + color.bold
                    }
                }
            });

            console.log(table.toString());
        }
    }
}