#!/usr/bin/env node
//@ts-nocheck
import { exec } from "child_process";
import { Command } from "commander";
const program = new Command();
import { Fs } from "@timeax/utilities";
import { createSassCompilerCommand } from "./sass-to-lightening";
import csr from "./csr";
function restartServer() {
exec('httpd -k restart -n "Apache2.4"', (err) => {
if (err) return console.log(err.message);
console.log("Apache restarted");
});
}
const attrs = {
domain: "",
path: "",
};
const manager = {
get _hosts() {
let def = process.env.HOSTS || "C:/Windows/System32/drivers/etc/hosts";
const drive = process.env.HOSTS ? null : process.env.DRIVE;
///---
if (drive) def = drive + def.substring(1);
//---
return def;
},
get _vhosts() {
let def = process.env.VP || "D:/xampp/apache/conf/extra/httpd-vhosts.conf";
const drive = process.env.VP ? null : process.env.VD;
///---
if (drive) def = drive + def.substring(1);
return def;
},
get hosts() {
return Fs.content(this._hosts) || "";
},
get vhosts() {
return Fs.content(this._vhosts) || "";
},
set hosts(value: string) {
Fs.writeSync(this._hosts, value);
},
set vhosts(value: string) {
Fs.writeSync(this._vhosts, value);
},
};
function write() {
writeVHost();
addHost();
console.log("Created successfully");
}
function createId() {
let id = `## domain: ${attrs.domain}----`;
return {
start: id,
end: id + "####",
};
}
function writeVHost() {
let content = manager.vhosts;
const { start: id } = createId();
console.log(content);
//---
if (!content?.includes(id)) {
content += append(createVirtualHost());
manager.vhosts = content;
console.log(content);
} else console.log("Virtual host already exists");
}
function addHost() {
let content = manager.hosts;
const id = createId();
//---
if (!content?.includes(id.start)) {
content += append(`127.0.0.1 ${attrs.domain}`);
manager.hosts = content;
console.log("Written to path: " + manager._hosts);
console.log("Content: " + content);
} else console.log("Virtual host already exists");
}
function createVirtualHost() {
return `
DocumentRoot "${attrs.path}"
ServerName ${attrs.domain}
ServerAlias *.${attrs.domain}
Require local
`;
}
function append(content: string) {
const id = createId();
return `\n\n${id.start}\n${content}\n${id.end}`;
}
function deleteHost() {
let { start: id, end: idEnd } = createId();
const list = [manager._hosts, manager._vhosts];
list.forEach((item) => {
let content = Fs.content(item);
const a = new RegExp(id),
b = new RegExp(idEnd);
console.log(a.exec(content), id);
const [start, end] = [a.exec(content).index, b.exec(content).index];
if (start > -1 && end > start) {
console.log(
"Deleted content: " + content.slice(start, end + idEnd.length)
);
content = content.replace(
content.slice(start, end + idEnd.length),
""
);
Fs.writeSync(item, content);
}
});
}
function createDomain(name: string, domain?: string) {
if (domain) return domain;
if (name.match(/^(?:https?:\/\/)?(?:[^.]+\.)?example\.com(\/.*)?$/))
return name;
return name + ".test";
}
function set(domain: string, path: string) {
attrs.domain = domain;
attrs.path = path;
}
function install(props) {
// write(domain);
let path = props.path || process.cwd();
set(createDomain(Fs.dirname(path), props.domain), path);
write();
restartServer();
}
function update(props) {
let path = props.path || process.cwd();
set(createDomain(Fs.dirname(path), props.domain), path);
//---------
let { start: id, end: idEnd } = createId();
const host = manager.hosts,
vhosts = manager.vhosts;
(
[
{ path: manager._hosts, content: host, name: "hosts" },
{ path: manager._vhosts, content: vhosts, name: "vhosts" },
] as const
).forEach(({ content, path, name }) => {
if (content.includes(id)) {
const [start, end] = [
content.indexOf(id),
content.indexOf(idEnd) + idEnd.length,
];
const scrape = content.slice(start, end);
//--------
manager[name] = content.replace(
scrape,
append(
name === "vhosts"
? createVirtualHost()
: `127.0.0.1 ${attrs.domain}`
)
);
} else install(props);
});
restartServer();
}
function del(props: { domain: string[]; path: string }) {
if (props) {
let path = props.path || process.cwd(),
domain = createDomain(Fs.name(path), props.domain.join(" "));
attrs.domain = domain;
attrs.path = path;
deleteHost();
restartServer();
console.log("deleted sucessfully");
}
}
function parse(num: string[]) {
return num
.map((item) => parseInt(item.trim()))
.filter((item) => typeof item == "number");
}
function getNumbers(num: string) {
num = num.trim();
if (num.includes(",")) {
return parse(num.split(","));
}
return parse([num]);
}
interface Modify {
domain: string;
path: string;
dns: string;
port: string;
alias: string;
}
async function listDomains(props: ListDomains) {
const {
default: { prompt },
} = await import("inquirer");
let deleteIndex: number[] = [];
let formatIndex: number[] = [];
if (props.remove)
props.remove.forEach((item) => deleteIndex.push(...getNumbers(item)));
if (props.format)
props.format.forEach((item) => formatIndex.push(...getNumbers(item)));
let table = getTable();
if (table) {
if (formatIndex.length > 0) {
for (let item of formatIndex) {
if (item < 0) item = table.length + item;
//-----------
const row = table[item];
if (!row) continue;
const modal = await prompt([
{
name: "modify",
message: `Are you sure you want to modify ${row.Name} in ${row.Directory}`,
type: "confirm",
},
]);
if (modal.modify) {
const modal: Modify = await prompt([
{
name: "domain",
message: `Enter Domain name`,
type: "input",
default: row.Name,
},
{
name: "alias",
message: `Enter Server Alias`,
type: "input",
default: row.ServerAlias,
},
{
name: "path",
message: `Root Directory (relative paths are valid)`,
type: "input",
default: row.Directory,
},
{
name: "dns",
message: `Enter new DNS`,
type: "input",
default: row.DNS,
},
{
name: "port",
message: `Enter Port`,
type: "input",
default: row.Port,
},
]);
modify(modal);
table = getTable();
}
}
}
if (deleteIndex.length > 0) {
for (let item of deleteIndex) {
if (item < 0) item = table.length + item;
const row = table[item];
if (!row) continue;
const modal = await prompt([
{
name: "delete",
message: `Are you sure you want to delete ${row.Name} in ${row.Directory}`,
type: "confirm",
},
]);
if (modal.delete) del({ domain: [row.Name], path: row.Directory });
}
table = getTable();
}
console.log("\n\nList Of Installed Domains");
console.table(table);
} else console.log("No records found");
console.log(`\nSee hosts file at -> ${manager._hosts}`);
console.log(`\nSee vhosts file at -> ${manager._vhosts}`);
}
interface DomainProps {
directory: string;
alias: string;
serverPort: string;
dns: string;
}
interface ListDomains {
format?: string[];
remove?: string[];
}
function extract(
hosts: string,
content: string,
name: string
): { alias: any; directory: any; serverPort: any; dns: any } {
let port = content.match(/]*>/gm)?.[0];
if (port) port = port.replace(/", "");
let alias = content.match(/ServerAlias\s+[^\n]*/gm)?.[0];
if (alias) alias = alias.replace(/ServerAlias\s+?/, "")?.trim();
let path = content.match(/DocumentRoot\s+[^\n]*/gm)?.[0];
if (path)
path = path
.replace(/DocumentRoot\s+?[^"]*"/gm, "")
.replace('"', "")
.trim();
let dns = hosts.replace(new RegExp(`\\s+?${name}[^\n]*`), "")?.trim();
return { alias, directory: path, serverPort: port, dns };
}
function modify(modal: Modify) {
// throw new Error("Function not implemented.");
}
function getTable() {
let { hosts, vhosts } = manager;
let matches = vhosts.match(/\#\#\s+?domain:\s+?[^\n]*---(-(?!\#))/gm);
let domains: { [x: string]: DomainProps } = {};
if (Array.isArray(matches)) {
matches.forEach((item) => {
const name = item
.match(/(?<=(\#\#\sdomain:))\s([^\n]*(?=(----)))/gm)?.[0]
?.trim();
if (name) {
attrs.domain = name;
const { start: id, end: closingID } = createId();
//---
const content = vhosts.slice(
vhosts.indexOf(id),
vhosts.indexOf(closingID) + closingID.length
);
const { alias, directory, serverPort, dns } = extract(
hosts.indexOf(id) > -1
? hosts.slice(
hosts.indexOf(id) + id.length,
hosts.indexOf(closingID)
)
: "",
content,
name
);
domains[name] = {
alias,
directory,
serverPort,
dns,
};
}
});
return Object.keys(domains).map((item) => {
return {
Name: item,
ServerAlias: domains[item].alias,
Directory: domains[item].directory,
DNS: domains[item].dns,
Port: domains[item].serverPort,
Url: `http://${item}/`,
};
});
}
}
(async () => {
const { default: chalk } = await import("chalk");
function getTimestamp() {
return chalk.gray(`[${new Date().toISOString()}]`);
}
const originalLog = console.log;
const originalError = console.error;
const originalWarn = console.warn;
const originalInfo = console.info;
console.log = (...args) => originalLog(getTimestamp(), chalk.white(...args));
console.error = (...args) => originalError(getTimestamp(), chalk.red("ERROR:"), chalk.red(...args));
console.warn = (...args) => originalWarn(getTimestamp(), chalk.yellow("WARNING:"), chalk.yellow(...args));
console.info = (...args) => originalInfo(getTimestamp(), chalk.blue("INFO:"), chalk.blue(...args));
program.name("web").version("0.0.2").description("Web Development Utility CMD Interface");
createSassCompilerCommand(program);
program
.command("list")
.description("Get a full list of a installed domains")
.option("-f, --format ")
.option("-rm, --remove ")
.action(listDomains);
program
.command("l")
.description("Get a full list of a installed domains")
.option("-f, --format ")
.option("-rm, --remove ")
.action(listDomains);
program
.command("install")
.description("Install a local domain on your system")
.option("-d, --domain ")
.option("-p, --path ")
.action(install);
program
.command("update")
.description("update a local domain on your system")
.option("-d, --domain ")
.option("-p, --path ")
.action(update);
program
.command("i")
.description("Install a local domain on your system")
.option("-d, --domain ")
.option("-p, --path ")
.action(install);
program
.command("del")
.description("Deletes virtual host")
.option("-d, --domain ", "-p, --path ")
.action(del);
csr(program);
program.parse(process.argv);
})();