@cloud-cli/dns 2.0.3 → 2.2.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { init } from '@cloud-cli/cli';
1
+ import { init, help } from "@cloud-cli/cli";
2
2
  interface DomainAndTarget {
3
3
  domain: string;
4
4
  target?: string;
@@ -19,5 +19,6 @@ declare const _default: {
19
19
  reload: typeof reload;
20
20
  get: typeof get;
21
21
  [init]: typeof addDnsConfig;
22
+ [help]: () => string;
22
23
  };
23
24
  export default _default;
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import fs from 'node:fs';
2
- import { join } from 'node:path';
3
- import { exec } from '@cloud-cli/exec';
4
- import { getConfig, init } from '@cloud-cli/cli';
5
- const filePath = join(process.cwd(), 'configuration', 'hosts.conf');
1
+ import fs from "node:fs";
2
+ import { join } from "node:path";
3
+ import { exec } from "@cloud-cli/exec";
4
+ import { getConfig, init, help } from "@cloud-cli/cli";
5
+ const filePath = join(process.cwd(), "configuration", "hosts.conf");
6
6
  const dnsConfig = {
7
- defaultTarget: '127.0.0.1',
7
+ defaultTarget: "127.0.0.1",
8
8
  };
9
9
  function add(input) {
10
10
  let current = list();
@@ -26,27 +26,46 @@ function list() {
26
26
  if (!fs.existsSync(filePath)) {
27
27
  return [];
28
28
  }
29
- const input = fs.readFileSync(filePath, 'utf8');
30
- const entries = input.trim().split('\n').filter(Boolean).flatMap(parseDNSLine);
29
+ const input = fs.readFileSync(filePath, "utf8");
30
+ const entries = input.trim().split("\n").filter(Boolean).flatMap(parseDNSLine);
31
31
  return entries;
32
32
  }
33
33
  function get(options) {
34
34
  return list().filter((d) => d.domain === options.domain)[0] || null;
35
35
  }
36
36
  async function reload() {
37
- const getPid = await exec('pidof', ['dnsmasq']);
38
- const cmd = await exec('kill', ['-s', 'HUP', getPid.stdout.trim()]);
39
- return cmd.ok || Promise.reject(new Error('Failed to reload'));
37
+ const getPid = await exec("pidof", ["dnsmasq"]);
38
+ const cmd = await exec("kill", ["-s", "HUP", getPid.stdout.trim()]);
39
+ return cmd.ok || Promise.reject(new Error("Failed to reload"));
40
40
  }
41
41
  function addDnsConfig() {
42
- Object.assign(dnsConfig, getConfig('dns'));
42
+ Object.assign(dnsConfig, getConfig("dns"));
43
43
  }
44
44
  function save(list) {
45
- let lines = list.map(next => next.target + ' ' + next.domain);
46
- fs.writeFileSync(filePath, lines.join('\n').trim());
45
+ const lines = list.map((next) => next.target + " " + next.domain);
46
+ fs.writeFileSync(filePath, lines.join("\n").trim());
47
47
  }
48
48
  export function parseDNSLine(line) {
49
49
  const [ip, ...domains] = line.split(/\s+/);
50
50
  return domains.map((d) => ({ domain: d, target: ip }));
51
51
  }
52
- export default { add, remove, list, reload, get, [init]: addDnsConfig };
52
+ export default {
53
+ add,
54
+ remove,
55
+ list,
56
+ reload,
57
+ get,
58
+ [init]: addDnsConfig,
59
+ [help]: () => `Manage DNS host entries
60
+
61
+ Available commands:
62
+ dns.add --domain <domain> [--target <ip>] - Add a DNS entry (target defaults to 127.0.0.1)
63
+ dns.remove --domain <domain> - Remove a DNS entry
64
+ dns.list - List all DNS entries
65
+ dns.reload - Reload the DNS service
66
+ dns.get --domain <domain> - Get a DNS entry
67
+
68
+ Options:
69
+ domain - Domain name
70
+ target - IP address (defaults to 127.0.0.1)`,
71
+ };
@@ -1,90 +1,109 @@
1
- import dns, { parseDNSLine } from './index';
2
- import fs from 'fs';
3
- import { init } from '@cloud-cli/cli';
4
- import { describe, it, expect, vi, beforeEach } from 'vitest';
1
+ import dns, { parseDNSLine } from "./index";
2
+ import fs from "fs";
3
+ import { init, help } from "@cloud-cli/cli";
4
+ import { describe, it, expect, vi, beforeEach } from "vitest";
5
5
  const execMocks = vi.hoisted(() => ({
6
6
  exec: vi.fn(),
7
7
  getConfig: vi.fn(),
8
8
  }));
9
- vi.mock('get-port', () => ({ default: vi.fn().mockReturnValue(1234) }));
10
- vi.mock('@cloud-cli/exec', () => ({ exec: execMocks.exec }));
11
- vi.mock('@cloud-cli/cli', async (original) => {
9
+ vi.mock("get-port", () => ({ default: vi.fn().mockReturnValue(1234) }));
10
+ vi.mock("@cloud-cli/exec", () => ({ exec: execMocks.exec }));
11
+ vi.mock("@cloud-cli/cli", async (original) => {
12
12
  const mod = await original();
13
13
  return {
14
14
  ...mod,
15
15
  getConfig: execMocks.getConfig,
16
+ help: mod.help,
16
17
  };
17
18
  });
18
19
  beforeEach(() => {
19
- vi.spyOn(fs, 'writeFileSync').mockImplementation(() => { });
20
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => '');
20
+ vi.spyOn(fs, "writeFileSync").mockImplementation(() => { });
21
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => "");
21
22
  });
22
- describe('dns', () => {
23
- it('should parse a DNS configuration line', () => {
24
- const line = '1.2.3.4 foo bar';
23
+ describe("dns", () => {
24
+ it("should have a [help] Symbol export that is a function", () => {
25
+ expect(dns[help]).toBeDefined();
26
+ expect(typeof dns[help]).toBe("function");
27
+ });
28
+ it("should return a string help text", () => {
29
+ const helpText = dns[help]();
30
+ expect(typeof help).toBe("symbol");
31
+ expect(typeof helpText).toBe("string");
32
+ expect(helpText).toContain("DNS");
33
+ expect(helpText).toContain("dns.add --domain <domain>");
34
+ expect(helpText).toContain("dns.remove --domain <domain>");
35
+ expect(helpText).toContain("dns.list");
36
+ expect(helpText).toContain("dns.reload");
37
+ expect(helpText).toContain("dns.get --domain <domain>");
38
+ });
39
+ it('should not expose "help" as a normal command key', () => {
40
+ expect(Object.hasOwn(dns, "help")).toBe(false);
41
+ });
42
+ it("should parse a DNS configuration line", () => {
43
+ const line = "1.2.3.4 foo bar";
25
44
  const output = parseDNSLine(line);
26
45
  expect(output).toEqual([
27
- { target: '1.2.3.4', domain: 'foo' },
28
- { target: '1.2.3.4', domain: 'bar' },
46
+ { target: "1.2.3.4", domain: "foo" },
47
+ { target: "1.2.3.4", domain: "bar" },
29
48
  ]);
30
49
  });
31
- it('should load entries from file', () => {
50
+ it("should load entries from file", () => {
32
51
  let fileExists = false;
33
52
  const buffer = `1.2.3.4 test\n5.6.7.8 foo`;
34
- vi.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
35
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
53
+ vi.spyOn(fs, "existsSync").mockImplementation(() => fileExists);
54
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => buffer);
36
55
  expect(dns.list()).toEqual([]);
37
56
  fileExists = true;
38
57
  const list = dns.list();
39
58
  expect(list).toEqual([
40
- { domain: 'test', target: '1.2.3.4' },
41
- { domain: 'foo', target: '5.6.7.8' },
59
+ { domain: "test", target: "1.2.3.4" },
60
+ { domain: "foo", target: "5.6.7.8" },
42
61
  ]);
43
62
  });
44
- it('should get a DNS entry by domain', () => {
63
+ it("should get a DNS entry by domain", () => {
45
64
  let fileExists = false;
46
65
  const buffer = `1.2.3.4 test.com\n5.6.7.8 foo.com`;
47
- vi.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
48
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
49
- expect(dns.get({ domain: 'foo.com' })).toBe(null);
66
+ vi.spyOn(fs, "existsSync").mockImplementation(() => fileExists);
67
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => buffer);
68
+ expect(dns.get({ domain: "foo.com" })).toBe(null);
50
69
  fileExists = true;
51
- expect(dns.get({ domain: 'foo.com' })).toEqual({ domain: 'foo.com', target: '5.6.7.8' });
70
+ expect(dns.get({ domain: "foo.com" })).toEqual({ domain: "foo.com", target: "5.6.7.8" });
52
71
  });
53
- it('should add and remove local DNS entries', () => {
54
- let text = '';
55
- vi.spyOn(fs, 'writeFileSync').mockImplementation((_file, value) => {
72
+ it("should add and remove local DNS entries", () => {
73
+ let text = "";
74
+ vi.spyOn(fs, "writeFileSync").mockImplementation((_file, value) => {
56
75
  text = value;
57
76
  });
58
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => text);
59
- dns.add({ domain: 'foo', target: '2.3.4.5' });
60
- dns.add({ domain: 'bar', target: '2.3.4.5' });
61
- dns.add({ domain: 'baz' });
62
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo');
63
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo\n2.3.4.5 bar');
64
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo\n2.3.4.5 bar\n127.0.0.1 baz');
65
- dns.remove({ domain: 'baz' });
66
- expect(text).toBe('2.3.4.5 foo\n2.3.4.5 bar');
77
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => text);
78
+ dns.add({ domain: "foo", target: "2.3.4.5" });
79
+ dns.add({ domain: "bar", target: "2.3.4.5" });
80
+ dns.add({ domain: "baz" });
81
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "2.3.4.5 foo");
82
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "2.3.4.5 foo\n2.3.4.5 bar");
83
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "2.3.4.5 foo\n2.3.4.5 bar\n127.0.0.1 baz");
84
+ dns.remove({ domain: "baz" });
85
+ expect(text).toBe("2.3.4.5 foo\n2.3.4.5 bar");
67
86
  });
68
- describe('reload', () => {
69
- it('should reload the DNS service', async () => {
70
- execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: '123' });
87
+ describe("reload", () => {
88
+ it("should reload the DNS service", async () => {
89
+ execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: "123" });
71
90
  execMocks.exec.mockResolvedValueOnce({ ok: true });
72
91
  await expect(dns.reload()).resolves.toBe(true);
73
- expect(execMocks.exec).toHaveBeenCalledWith('pidof', ['dnsmasq']);
74
- expect(execMocks.exec).toHaveBeenCalledWith('kill', ['-s', 'HUP', '123']);
92
+ expect(execMocks.exec).toHaveBeenCalledWith("pidof", ["dnsmasq"]);
93
+ expect(execMocks.exec).toHaveBeenCalledWith("kill", ["-s", "HUP", "123"]);
75
94
  });
76
- it('should show error on reload', async () => {
77
- execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: '123' });
78
- execMocks.exec.mockResolvedValueOnce({ ok: false, stderr: 'error' });
79
- await expect(dns.reload()).rejects.toEqual(new Error('Failed to reload'));
95
+ it("should show error on reload", async () => {
96
+ execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: "123" });
97
+ execMocks.exec.mockResolvedValueOnce({ ok: false, stderr: "error" });
98
+ await expect(dns.reload()).rejects.toEqual(new Error("Failed to reload"));
80
99
  });
81
100
  });
82
- describe('dns configuration', () => {
83
- it('should configure the default target', () => {
84
- execMocks.getConfig.mockReturnValue({ defaultTarget: '1.1.2.2' });
101
+ describe("dns configuration", () => {
102
+ it("should configure the default target", () => {
103
+ execMocks.getConfig.mockReturnValue({ defaultTarget: "1.1.2.2" });
85
104
  dns[init]();
86
- dns.add({ domain: 'bar' });
87
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '1.1.2.2 bar');
105
+ dns.add({ domain: "bar" });
106
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "1.1.2.2 bar");
88
107
  });
89
108
  });
90
109
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud-cli/dns",
3
- "version": "2.0.3",
3
+ "version": "2.2.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",
@@ -27,6 +27,6 @@
27
27
  "@cloud-cli/exec": "^1.0.4"
28
28
  },
29
29
  "peerDependencies": {
30
- "@cloud-cli/cli": "^2.0.0"
30
+ "@cloud-cli/cli": "^2.2.0"
31
31
  }
32
32
  }
package/src/index.spec.ts CHANGED
@@ -1,111 +1,133 @@
1
- import dns, { parseDNSLine } from './index';
2
- import fs from 'fs';
3
- import { init } from '@cloud-cli/cli';
4
- import { describe, it, expect, vi, beforeEach } from 'vitest';
1
+ import dns, { parseDNSLine } from "./index";
2
+ import fs from "fs";
3
+ import { init, help } from "@cloud-cli/cli";
4
+ import { describe, it, expect, vi, beforeEach } from "vitest";
5
5
 
6
6
  const execMocks = vi.hoisted(() => ({
7
7
  exec: vi.fn(),
8
8
  getConfig: vi.fn(),
9
9
  }));
10
10
 
11
- vi.mock('get-port', () => ({ default: vi.fn().mockReturnValue(1234) }));
12
- vi.mock('@cloud-cli/exec', () => ({ exec: execMocks.exec }));
13
- vi.mock('@cloud-cli/cli', async (original) => {
11
+ vi.mock("get-port", () => ({ default: vi.fn().mockReturnValue(1234) }));
12
+ vi.mock("@cloud-cli/exec", () => ({ exec: execMocks.exec }));
13
+ vi.mock("@cloud-cli/cli", async (original) => {
14
14
  const mod: any = await original();
15
15
  return {
16
16
  ...mod,
17
17
  getConfig: execMocks.getConfig,
18
+ help: mod.help,
18
19
  };
19
20
  });
20
21
 
21
22
  beforeEach(() => {
22
- vi.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
23
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => '');
23
+ vi.spyOn(fs, "writeFileSync").mockImplementation(() => {});
24
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => "");
24
25
  });
25
26
 
26
- describe('dns', () => {
27
- it('should parse a DNS configuration line', () => {
28
- const line = '1.2.3.4 foo bar';
27
+ describe("dns", () => {
28
+ it("should have a [help] Symbol export that is a function", () => {
29
+ expect(dns[help]).toBeDefined();
30
+ expect(typeof dns[help]).toBe("function");
31
+ });
32
+
33
+ it("should return a string help text", () => {
34
+ const helpText = dns[help]();
35
+ expect(typeof help).toBe("symbol");
36
+ expect(typeof helpText).toBe("string");
37
+ expect(helpText).toContain("DNS");
38
+ expect(helpText).toContain("dns.add --domain <domain>");
39
+ expect(helpText).toContain("dns.remove --domain <domain>");
40
+ expect(helpText).toContain("dns.list");
41
+ expect(helpText).toContain("dns.reload");
42
+ expect(helpText).toContain("dns.get --domain <domain>");
43
+ });
44
+
45
+ it('should not expose "help" as a normal command key', () => {
46
+ expect(Object.hasOwn(dns, "help")).toBe(false);
47
+ });
48
+
49
+ it("should parse a DNS configuration line", () => {
50
+ const line = "1.2.3.4 foo bar";
29
51
  const output = parseDNSLine(line);
30
52
 
31
53
  expect(output).toEqual([
32
- { target: '1.2.3.4', domain: 'foo' },
33
- { target: '1.2.3.4', domain: 'bar' },
54
+ { target: "1.2.3.4", domain: "foo" },
55
+ { target: "1.2.3.4", domain: "bar" },
34
56
  ]);
35
57
  });
36
58
 
37
- it('should load entries from file', () => {
59
+ it("should load entries from file", () => {
38
60
  let fileExists = false;
39
61
  const buffer = `1.2.3.4 test\n5.6.7.8 foo`;
40
- vi.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
41
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
62
+ vi.spyOn(fs, "existsSync").mockImplementation(() => fileExists);
63
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => buffer);
42
64
 
43
65
  expect(dns.list()).toEqual([]);
44
66
 
45
67
  fileExists = true;
46
68
  const list = dns.list();
47
69
  expect(list).toEqual([
48
- { domain: 'test', target: '1.2.3.4' },
49
- { domain: 'foo', target: '5.6.7.8' },
70
+ { domain: "test", target: "1.2.3.4" },
71
+ { domain: "foo", target: "5.6.7.8" },
50
72
  ]);
51
73
  });
52
74
 
53
- it('should get a DNS entry by domain', () => {
75
+ it("should get a DNS entry by domain", () => {
54
76
  let fileExists = false;
55
77
  const buffer = `1.2.3.4 test.com\n5.6.7.8 foo.com`;
56
- vi.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
57
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
78
+ vi.spyOn(fs, "existsSync").mockImplementation(() => fileExists);
79
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => buffer);
58
80
 
59
- expect(dns.get({ domain: 'foo.com' })).toBe(null);
81
+ expect(dns.get({ domain: "foo.com" })).toBe(null);
60
82
 
61
83
  fileExists = true;
62
- expect(dns.get({ domain: 'foo.com' })).toEqual({ domain: 'foo.com', target: '5.6.7.8' });
84
+ expect(dns.get({ domain: "foo.com" })).toEqual({ domain: "foo.com", target: "5.6.7.8" });
63
85
  });
64
86
 
65
- it('should add and remove local DNS entries', () => {
66
- let text = '';
67
- vi.spyOn(fs, 'writeFileSync').mockImplementation((_file, value: string) => {
87
+ it("should add and remove local DNS entries", () => {
88
+ let text = "";
89
+ vi.spyOn(fs, "writeFileSync").mockImplementation((_file, value: string) => {
68
90
  text = value;
69
91
  });
70
- vi.spyOn(fs, 'readFileSync').mockImplementation(() => text);
92
+ vi.spyOn(fs, "readFileSync").mockImplementation(() => text);
71
93
 
72
- dns.add({ domain: 'foo', target: '2.3.4.5' });
73
- dns.add({ domain: 'bar', target: '2.3.4.5' });
74
- dns.add({ domain: 'baz' });
94
+ dns.add({ domain: "foo", target: "2.3.4.5" });
95
+ dns.add({ domain: "bar", target: "2.3.4.5" });
96
+ dns.add({ domain: "baz" });
75
97
 
76
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo');
77
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo\n2.3.4.5 bar');
78
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo\n2.3.4.5 bar\n127.0.0.1 baz');
98
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "2.3.4.5 foo");
99
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "2.3.4.5 foo\n2.3.4.5 bar");
100
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "2.3.4.5 foo\n2.3.4.5 bar\n127.0.0.1 baz");
79
101
 
80
- dns.remove({ domain: 'baz' });
81
- expect(text).toBe('2.3.4.5 foo\n2.3.4.5 bar');
102
+ dns.remove({ domain: "baz" });
103
+ expect(text).toBe("2.3.4.5 foo\n2.3.4.5 bar");
82
104
  });
83
105
 
84
- describe('reload', () => {
85
- it('should reload the DNS service', async () => {
86
- execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: '123' } as any);
106
+ describe("reload", () => {
107
+ it("should reload the DNS service", async () => {
108
+ execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: "123" } as any);
87
109
  execMocks.exec.mockResolvedValueOnce({ ok: true } as any);
88
110
 
89
111
  await expect(dns.reload()).resolves.toBe(true);
90
- expect(execMocks.exec).toHaveBeenCalledWith('pidof', ['dnsmasq']);
91
- expect(execMocks.exec).toHaveBeenCalledWith('kill', ['-s', 'HUP', '123']);
112
+ expect(execMocks.exec).toHaveBeenCalledWith("pidof", ["dnsmasq"]);
113
+ expect(execMocks.exec).toHaveBeenCalledWith("kill", ["-s", "HUP", "123"]);
92
114
  });
93
115
 
94
- it('should show error on reload', async () => {
95
- execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: '123' } as any);
96
- execMocks.exec.mockResolvedValueOnce({ ok: false, stderr: 'error' } as any);
116
+ it("should show error on reload", async () => {
117
+ execMocks.exec.mockResolvedValueOnce({ ok: true, stdout: "123" } as any);
118
+ execMocks.exec.mockResolvedValueOnce({ ok: false, stderr: "error" } as any);
97
119
 
98
- await expect(dns.reload()).rejects.toEqual(new Error('Failed to reload'));
120
+ await expect(dns.reload()).rejects.toEqual(new Error("Failed to reload"));
99
121
  });
100
122
  });
101
123
 
102
- describe('dns configuration', () => {
103
- it('should configure the default target', () => {
104
- execMocks.getConfig.mockReturnValue({ defaultTarget: '1.1.2.2' });
124
+ describe("dns configuration", () => {
125
+ it("should configure the default target", () => {
126
+ execMocks.getConfig.mockReturnValue({ defaultTarget: "1.1.2.2" });
105
127
  dns[init]();
106
- dns.add({ domain: 'bar' });
128
+ dns.add({ domain: "bar" });
107
129
 
108
- expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '1.1.2.2 bar');
130
+ expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), "1.1.2.2 bar");
109
131
  });
110
132
  });
111
133
  });
package/src/index.ts CHANGED
@@ -1,15 +1,15 @@
1
- import fs from 'node:fs';
2
- import { join } from 'node:path';
3
- import { exec } from '@cloud-cli/exec';
4
- import { getConfig, init } from '@cloud-cli/cli';
1
+ import fs from "node:fs";
2
+ import { join } from "node:path";
3
+ import { exec } from "@cloud-cli/exec";
4
+ import { getConfig, init, help } from "@cloud-cli/cli";
5
5
 
6
6
  interface DNSConfig {
7
7
  defaultTarget?: string;
8
8
  }
9
9
 
10
- const filePath = join(process.cwd(), 'configuration', 'hosts.conf');
10
+ const filePath = join(process.cwd(), "configuration", "hosts.conf");
11
11
  const dnsConfig: DNSConfig = {
12
- defaultTarget: '127.0.0.1',
12
+ defaultTarget: "127.0.0.1",
13
13
  };
14
14
 
15
15
  interface DomainAndTarget {
@@ -43,8 +43,8 @@ function list(): DomainAndTarget[] {
43
43
  return [];
44
44
  }
45
45
 
46
- const input = fs.readFileSync(filePath, 'utf8');
47
- const entries = input.trim().split('\n').filter(Boolean).flatMap(parseDNSLine);
46
+ const input = fs.readFileSync(filePath, "utf8");
47
+ const entries = input.trim().split("\n").filter(Boolean).flatMap(parseDNSLine);
48
48
 
49
49
  return entries;
50
50
  }
@@ -54,18 +54,18 @@ function get(options: { domain: string }): DomainAndTarget | null {
54
54
  }
55
55
 
56
56
  async function reload() {
57
- const getPid = await exec('pidof', ['dnsmasq']);
58
- const cmd = await exec('kill', ['-s', 'HUP', getPid.stdout.trim()]);
59
- return cmd.ok || Promise.reject(new Error('Failed to reload'));
57
+ const getPid = await exec("pidof", ["dnsmasq"]);
58
+ const cmd = await exec("kill", ["-s", "HUP", getPid.stdout.trim()]);
59
+ return cmd.ok || Promise.reject(new Error("Failed to reload"));
60
60
  }
61
61
 
62
62
  function addDnsConfig() {
63
- Object.assign(dnsConfig, getConfig('dns'));
63
+ Object.assign(dnsConfig, getConfig("dns"));
64
64
  }
65
65
 
66
66
  function save(list: DomainAndTarget[]) {
67
- let lines = list.map(next => next.target + ' ' + next.domain);
68
- fs.writeFileSync(filePath, lines.join('\n').trim());
67
+ const lines = list.map((next) => next.target + " " + next.domain);
68
+ fs.writeFileSync(filePath, lines.join("\n").trim());
69
69
  }
70
70
 
71
71
  export function parseDNSLine(line: string): DomainAndTarget[] {
@@ -73,4 +73,23 @@ export function parseDNSLine(line: string): DomainAndTarget[] {
73
73
  return domains.map((d) => ({ domain: d, target: ip }));
74
74
  }
75
75
 
76
- export default { add, remove, list, reload, get, [init]: addDnsConfig };
76
+ export default {
77
+ add,
78
+ remove,
79
+ list,
80
+ reload,
81
+ get,
82
+ [init]: addDnsConfig,
83
+ [help]: () => `Manage DNS host entries
84
+
85
+ Available commands:
86
+ dns.add --domain <domain> [--target <ip>] - Add a DNS entry (target defaults to 127.0.0.1)
87
+ dns.remove --domain <domain> - Remove a DNS entry
88
+ dns.list - List all DNS entries
89
+ dns.reload - Reload the DNS service
90
+ dns.get --domain <domain> - Get a DNS entry
91
+
92
+ Options:
93
+ domain - Domain name
94
+ target - IP address (defaults to 127.0.0.1)`,
95
+ };