@luxmargos/ensure-hosts 0.1.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.
@@ -0,0 +1,212 @@
1
+ import { readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { join, win32 } from 'node:path';
3
+ import { platform } from 'node:os';
4
+ import { spawnSync } from 'node:child_process';
5
+ export function resolveDefaultHostsPath(currentPlatform = platform(), env = process.env) {
6
+ if (currentPlatform === 'win32') {
7
+ return win32.join(env.SystemRoot ?? 'C:\\Windows', 'System32', 'drivers', 'etc', 'hosts');
8
+ }
9
+ return '/etc/hosts';
10
+ }
11
+ export function tryElevate(options) {
12
+ if (options.noElevate || options.elevated || options.dryRun || options.printRecords) {
13
+ return false;
14
+ }
15
+ if (platform() === 'darwin') {
16
+ // Try sudo (mkcert-style) first — works in terminal contexts and avoids
17
+ // the noowners EPERM that osascript hits on external APFS volumes.
18
+ const sudoResult = tryMacOsSudoWrite(options.filePath, options.content);
19
+ if (sudoResult) {
20
+ return sudoResult;
21
+ }
22
+ // Fall back to osascript GUI prompt for non-terminal contexts.
23
+ return tryMacOsPrivilegePrompt(options);
24
+ }
25
+ if (platform() === 'linux') {
26
+ // Linux: no in-process elevation. The user pre-elevates
27
+ // (sudo ensure-hosts) or the process is already root.
28
+ return false;
29
+ }
30
+ if (platform() === 'win32') {
31
+ return tryWindowsPrivilegePrompt(options);
32
+ }
33
+ return false;
34
+ }
35
+ /**
36
+ * Returns true when an elevation attempt succeeded and the caller should
37
+ * exit cleanly (no Permission denied error). Any truthy ElevationResult
38
+ * (`'written'` from sudo tee / already-root, or `'spawned'` from the
39
+ * osascript/Windows GUI re-spawn) counts as success. `false` means no
40
+ * elevation happened and the caller should throw the sudo hint.
41
+ */
42
+ export function elevationHandled(elevated) {
43
+ return elevated !== false;
44
+ }
45
+ /**
46
+ * Prints a notification when the process is running as root (uid 0),
47
+ * so the user knows the hosts file will be written directly without
48
+ * any elevation prompt. Called before the direct writeFileSync in cli.ts.
49
+ */
50
+ export function notifyRootWrite(filePath) {
51
+ if (typeof process.getuid === 'function' && process.getuid() === 0) {
52
+ console.log(`[ensure-hosts] Running as root; writing ${filePath} directly.`);
53
+ }
54
+ }
55
+ export function elevatedCommandHint(command = 'ensure-hosts') {
56
+ if (platform() === 'win32') {
57
+ return `Windows: if the privilege prompt does not appear, run \`${command}\` in an elevated PowerShell.`;
58
+ }
59
+ if (platform() === 'darwin') {
60
+ return `macOS: if the privilege prompt does not appear, run \`sudo ${command}\`.`;
61
+ }
62
+ return `Linux: run \`sudo ${command}\`.`;
63
+ }
64
+ function tryMacOsSudoWrite(filePath, content) {
65
+ // Already root → write directly, no sudo needed.
66
+ if (typeof process.getuid === 'function' && process.getuid() === 0) {
67
+ console.log(`[ensure-hosts] Already running as root; writing ${filePath} directly.`);
68
+ writeFileSync(filePath, content, 'utf8');
69
+ console.log(`[ensure-hosts] Updated ${filePath} as root.`);
70
+ return 'written';
71
+ }
72
+ // Check if sudo is available before attempting to prompt.
73
+ const which = spawnSync('which', ['sudo'], { stdio: 'ignore' });
74
+ if (which.status !== 0) {
75
+ return false;
76
+ }
77
+ // Run: sudo -- tee <filePath> with content piped via stdin.
78
+ // sudo reads the password from /dev/tty (the controlling terminal),
79
+ // so the user sees a terminal password prompt. Only tee runs as root;
80
+ // node stays as the normal user, avoiding noowners EPERM on external volumes.
81
+ console.log(`[ensure-hosts] sudo password required to update ${filePath}.`);
82
+ console.log('[ensure-hosts] Only `tee` runs as root; this process stays as the current user.');
83
+ const result = spawnSync('sudo', ['--', 'tee', filePath], {
84
+ input: content,
85
+ encoding: 'utf8',
86
+ stdio: ['pipe', 'ignore', 'inherit'],
87
+ });
88
+ if (result.status === 0) {
89
+ console.log(`[ensure-hosts] sudo tee updated ${filePath}.`);
90
+ return 'written';
91
+ }
92
+ console.log('[ensure-hosts] sudo elevation failed or was cancelled; falling back to GUI prompt...');
93
+ return false;
94
+ }
95
+ function tryMacOsPrivilegePrompt(options) {
96
+ console.log('[ensure-hosts] Requesting macOS administrator privileges via osascript.');
97
+ console.log('[ensure-hosts] A GUI administrator password dialog will appear; re-running ensure-hosts as root.');
98
+ const rerunArgs = [...withoutElevationArgs(options.args), '--elevated'];
99
+ const command = [shellQuote(process.execPath), shellQuote(options.scriptPath), ...rerunArgs.map(shellQuote)].join(' ');
100
+ const script = `do shell script ${appleScriptString(command)} with administrator privileges`;
101
+ const result = spawnSync('osascript', ['-e', script], {
102
+ cwd: options.cwd,
103
+ encoding: 'utf8',
104
+ stdio: ['ignore', 'pipe', 'pipe'],
105
+ });
106
+ if (result.stdout) {
107
+ process.stdout.write(result.stdout);
108
+ }
109
+ if (result.stderr) {
110
+ process.stderr.write(result.stderr);
111
+ }
112
+ if (result.status === 0) {
113
+ console.log('[ensure-hosts] macOS administrator privileges granted; elevated child completed.');
114
+ return 'spawned';
115
+ }
116
+ const childError = result.stderr?.trim() ?? '';
117
+ // osascript returns exit status 1 both when the user cancels the prompt and
118
+ // when the elevated child exits non-zero. A cancelled prompt produces no
119
+ // child stderr; a failed child leaves our own `[ensure-hosts]` error line.
120
+ // Distinguish them so a real failure isn't misreported as "cancelled".
121
+ const childFailed = /\[ensure-hosts\]|Error/i.test(childError);
122
+ if (result.status === 1 && !childFailed) {
123
+ console.log('[ensure-hosts] macOS administrator privilege request was cancelled.');
124
+ return false;
125
+ }
126
+ const detail = childError ? `\n${childError}` : '';
127
+ console.log(`[ensure-hosts] macOS administrator privilege request failed: osascript exit=${result.status}.${detail}`);
128
+ return false;
129
+ }
130
+ function tryWindowsPrivilegePrompt(options) {
131
+ console.log('[ensure-hosts] Requesting Windows administrator privileges.');
132
+ const outputPath = join(process.env.TEMP ?? process.env.TMP ?? 'C:\\Windows\\Temp', `ensure-hosts-${process.pid}.log`);
133
+ const rerunArgs = [...withoutElevationArgs(options.args), '--elevated', '--output-file', outputPath];
134
+ const command = [
135
+ 'try {',
136
+ `$proc = Start-Process -FilePath ${powerShellString(process.execPath)} -ArgumentList @(${[
137
+ options.scriptPath,
138
+ ...rerunArgs,
139
+ ]
140
+ .map(powerShellString)
141
+ .join(', ')}) -WorkingDirectory ${powerShellString(options.cwd)} -Verb RunAs -Wait -PassThru`,
142
+ 'if (Test-Path $env:OUT) { Get-Content $env:OUT -Raw | Write-Output }',
143
+ 'exit $proc.ExitCode',
144
+ '} catch {',
145
+ 'Write-Error $_',
146
+ 'exit 1',
147
+ '}',
148
+ ].join(' ; ');
149
+ const result = spawnSync('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', `$env:OUT = ${powerShellString(outputPath)} ; ${command}`], {
150
+ cwd: options.cwd,
151
+ encoding: 'utf8',
152
+ stdio: ['ignore', 'pipe', 'pipe'],
153
+ });
154
+ let capturedOutput = '';
155
+ try {
156
+ capturedOutput = readFileSync(outputPath, 'utf8');
157
+ }
158
+ catch {
159
+ // ignore missing elevated output file
160
+ }
161
+ try {
162
+ unlinkSync(outputPath);
163
+ }
164
+ catch {
165
+ // ignore cleanup errors
166
+ }
167
+ if (capturedOutput) {
168
+ process.stdout.write(capturedOutput);
169
+ }
170
+ if (result.stdout) {
171
+ process.stdout.write(result.stdout);
172
+ }
173
+ if (result.stderr) {
174
+ process.stderr.write(result.stderr);
175
+ }
176
+ if (result.status === 0) {
177
+ console.log('[ensure-hosts] Windows elevated hosts update completed.');
178
+ return 'spawned';
179
+ }
180
+ const detail = [capturedOutput.trim(), result.stderr?.trim() ?? ''].filter(Boolean).join('\n');
181
+ const suffix = detail ? `\n${detail}` : '';
182
+ console.log(`[ensure-hosts] Windows administrator privilege request failed or was cancelled: powershell exit=${result.status}.${suffix}`);
183
+ return false;
184
+ }
185
+ export function withoutElevationArgs(args) {
186
+ const output = [];
187
+ for (let index = 0; index < args.length; index += 1) {
188
+ const arg = args[index];
189
+ if (arg === '--elevated' || arg === '--no-elevate') {
190
+ continue;
191
+ }
192
+ if (arg === '--output-file') {
193
+ index += 1;
194
+ continue;
195
+ }
196
+ if (arg.startsWith('--output-file=')) {
197
+ continue;
198
+ }
199
+ output.push(arg);
200
+ }
201
+ return output;
202
+ }
203
+ function shellQuote(value) {
204
+ return `'${value.replaceAll("'", "'\\''")}'`;
205
+ }
206
+ function appleScriptString(value) {
207
+ return `"${value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"`;
208
+ }
209
+ function powerShellString(value) {
210
+ return `'${value.replaceAll("'", "''")}'`;
211
+ }
212
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export interface HostNodeConfig {
2
+ domain: string;
3
+ address?: string;
4
+ rewrite?: boolean;
5
+ skipSelf?: boolean;
6
+ children?: Array<string | HostNodeConfig>;
7
+ }
8
+ export interface ProfileConfig {
9
+ profile: string;
10
+ hosts: HostNodeConfig[];
11
+ }
12
+ export interface HostRecord {
13
+ profile: string;
14
+ domain: string;
15
+ address: string;
16
+ rewrite: boolean;
17
+ }
18
+ export interface ExpandedProfile {
19
+ profile: string;
20
+ records: HostRecord[];
21
+ cleanupDomains: string[];
22
+ }
23
+ export interface CliOptions {
24
+ configPaths: string[];
25
+ envFile: string;
26
+ envFileExplicit: boolean;
27
+ hostsFile?: string;
28
+ dryRun: boolean;
29
+ printRecords: boolean;
30
+ remove: boolean;
31
+ removeForce: boolean;
32
+ noElevate: boolean;
33
+ elevated: boolean;
34
+ outputFile?: string;
35
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@luxmargos/ensure-hosts",
3
+ "version": "0.1.0",
4
+ "description": "CLI for managing hosts file entries from YAML profiles.",
5
+ "type": "module",
6
+ "bin": {
7
+ "ensure-hosts": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc -p tsconfig.json",
15
+ "typecheck": "tsc -p tsconfig.json --noEmit",
16
+ "test": "vitest run",
17
+ "demo": "node dist/cli.js --config fixtures/simple.yaml",
18
+ "demo-remove": "node dist/cli.js --config fixtures/simple.yaml --remove",
19
+ "prepack": "npm run build",
20
+ "prepublishOnly": "npm run typecheck && npm test",
21
+ "dev": "tsx src/cli.ts"
22
+ },
23
+ "dependencies": {
24
+ "dotenv": "^16.4.7",
25
+ "yaml": "^2.6.1"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.10.2",
29
+ "tsx": "^4.19.2",
30
+ "typescript": "^5.7.2",
31
+ "vitest": "^2.1.8"
32
+ },
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "license": "MIT"
40
+ }