@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.
- package/README.md +285 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.js +274 -0
- package/dist/config.js.map +1 -0
- package/dist/domain-map.d.ts +4 -0
- package/dist/domain-map.js +73 -0
- package/dist/domain-map.js.map +1 -0
- package/dist/hosts.d.ts +30 -0
- package/dist/hosts.js +220 -0
- package/dist/hosts.js.map +1 -0
- package/dist/platform.d.ts +30 -0
- package/dist/platform.js +212 -0
- package/dist/platform.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# @luxmargos/ensure-hosts
|
|
2
|
+
|
|
3
|
+
Manage local hosts-file entries on macOS, Linux, and Windows from small YAML profiles.
|
|
4
|
+
|
|
5
|
+
`ensure-hosts` expands a YAML file into hosts-file records, removes stale records for the same domains when requested, and appends the current records. It is useful for local development domains such as `api.myapp.test`, `admin.myapp.test`, and other repeatable project setup.
|
|
6
|
+
|
|
7
|
+
## Why use it?
|
|
8
|
+
|
|
9
|
+
- Keep project hostnames in versioned YAML instead of editing `/etc/hosts` by hand.
|
|
10
|
+
- Re-run the same command safely when project IPs or domains change.
|
|
11
|
+
- Preview changes before writing with `--dry-run`.
|
|
12
|
+
- Remove a profile's entries when you no longer need them.
|
|
13
|
+
- Share one base config plus project-specific configs.
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Node.js 20 or newer
|
|
18
|
+
- Permission to write the system hosts file when not using `--dry-run`
|
|
19
|
+
|
|
20
|
+
Default hosts-file locations:
|
|
21
|
+
|
|
22
|
+
- Linux/macOS: `/etc/hosts`
|
|
23
|
+
- Windows: `%SystemRoot%\System32\drivers\etc\hosts`
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm install -g @luxmargos/ensure-hosts
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then check the CLI is available:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
ensure-hosts --version
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
38
|
+
|
|
39
|
+
1. Create a config file, for example `hosts.local.yaml`:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
profile: MYAPP_LOCAL
|
|
43
|
+
hosts:
|
|
44
|
+
- domain: myapp.test
|
|
45
|
+
address: 127.0.0.1
|
|
46
|
+
children:
|
|
47
|
+
- api
|
|
48
|
+
- admin
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Preview what would be written:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
ensure-hosts --config ./hosts.local.yaml --dry-run
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
3. Apply the changes:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
ensure-hosts --config ./hosts.local.yaml
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
On macOS and Windows, the CLI can prompt for administrator permission when needed. On Linux, run with `sudo` if your user cannot write `/etc/hosts`:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
sudo ensure-hosts --config ./hosts.local.yaml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The example above writes records like:
|
|
70
|
+
|
|
71
|
+
```txt
|
|
72
|
+
# MYAPP_LOCAL
|
|
73
|
+
127.0.0.1 myapp.test
|
|
74
|
+
# MYAPP_LOCAL
|
|
75
|
+
127.0.0.1 api.myapp.test
|
|
76
|
+
# MYAPP_LOCAL
|
|
77
|
+
127.0.0.1 admin.myapp.test
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Common commands
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
# Use one config
|
|
84
|
+
ensure-hosts --config ./hosts.local.yaml
|
|
85
|
+
|
|
86
|
+
# Layer multiple configs
|
|
87
|
+
ensure-hosts --config ./base.yaml --config ./project.yaml
|
|
88
|
+
|
|
89
|
+
# Preview the final hosts file without writing
|
|
90
|
+
ensure-hosts --config ./hosts.local.yaml --dry-run
|
|
91
|
+
|
|
92
|
+
# Print the expanded records only
|
|
93
|
+
ensure-hosts --config ./hosts.local.yaml --print-records
|
|
94
|
+
|
|
95
|
+
# Remove entries managed by rewrite:true records
|
|
96
|
+
ensure-hosts --config ./hosts.local.yaml --remove
|
|
97
|
+
|
|
98
|
+
# Remove every domain listed by the config, including rewrite:false records
|
|
99
|
+
ensure-hosts --config ./hosts.local.yaml --remove-force
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Configuration reference
|
|
103
|
+
|
|
104
|
+
A config file must be `.yaml` or `.yml` and contain:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
profile: PROFILE_NAME
|
|
108
|
+
hosts:
|
|
109
|
+
- domain: some.domain.test
|
|
110
|
+
address: 192.168.1.111
|
|
111
|
+
rewrite: true
|
|
112
|
+
skipSelf: false
|
|
113
|
+
children:
|
|
114
|
+
- sitea
|
|
115
|
+
- domain: siteb
|
|
116
|
+
address: ::1
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Fields:
|
|
120
|
+
|
|
121
|
+
| Field | Required? | Description |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `profile` | Yes | Label written as a comment above generated entries, for example `# MYAPP_LOCAL`. |
|
|
124
|
+
| `hosts` | Yes | Array of host entries. |
|
|
125
|
+
| `domain` | Yes | Domain name. Inside `children`, this can be a relative subdomain such as `api`. |
|
|
126
|
+
| `address` | For records you want written | IPv4 or IPv6 address. Children inherit the parent address unless they set their own. |
|
|
127
|
+
| `rewrite` | No | Whether existing entries for the same domain may be cleaned before appending. Defaults to `true`. Children inherit the parent value. |
|
|
128
|
+
| `skipSelf` | No | Skip writing this node while still processing its children. Defaults to `false`. |
|
|
129
|
+
| `children` | No | Nested subdomains as strings or full objects. |
|
|
130
|
+
|
|
131
|
+
### Child domains
|
|
132
|
+
|
|
133
|
+
Child strings inherit the parent address and `rewrite` value:
|
|
134
|
+
|
|
135
|
+
```yaml
|
|
136
|
+
profile: LOCAL
|
|
137
|
+
hosts:
|
|
138
|
+
- domain: example.test
|
|
139
|
+
address: 127.0.0.1
|
|
140
|
+
children:
|
|
141
|
+
- api
|
|
142
|
+
- admin
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
This writes:
|
|
146
|
+
|
|
147
|
+
- `example.test`
|
|
148
|
+
- `api.example.test`
|
|
149
|
+
- `admin.example.test`
|
|
150
|
+
|
|
151
|
+
If a child already contains the full parent domain, it is not duplicated. For example, `api.example.test` stays `api.example.test`.
|
|
152
|
+
|
|
153
|
+
### `skipSelf` example
|
|
154
|
+
|
|
155
|
+
Use `skipSelf: true` when you only want child records:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
profile: LOCAL
|
|
159
|
+
hosts:
|
|
160
|
+
- domain: example.test
|
|
161
|
+
address: 127.0.0.1
|
|
162
|
+
skipSelf: true
|
|
163
|
+
children:
|
|
164
|
+
- api
|
|
165
|
+
- admin
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
This writes `api.example.test` and `admin.example.test`, but not `example.test`.
|
|
169
|
+
|
|
170
|
+
## How rewriting works
|
|
171
|
+
|
|
172
|
+
By default, `rewrite` is `true`.
|
|
173
|
+
|
|
174
|
+
With `rewrite: true`, `ensure-hosts`:
|
|
175
|
+
|
|
176
|
+
1. Removes existing hosts entries for the same domain.
|
|
177
|
+
2. Removes stale adjacent `# PROFILE_NAME` comments left by previous runs.
|
|
178
|
+
3. Appends the current generated entry when an address is available.
|
|
179
|
+
|
|
180
|
+
With `rewrite: false`, `ensure-hosts`:
|
|
181
|
+
|
|
182
|
+
1. Leaves existing entries for the same domain untouched.
|
|
183
|
+
2. Appends the generated entry only if that domain is not already present.
|
|
184
|
+
|
|
185
|
+
Entries without an effective `address` are not written. If their effective `rewrite` value is `true`, matching existing entries can still be cleaned.
|
|
186
|
+
|
|
187
|
+
## Remove mode
|
|
188
|
+
|
|
189
|
+
Use remove mode when you want to uninstall entries from a profile instead of ensuring them.
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
ensure-hosts --config ./hosts.local.yaml --remove
|
|
193
|
+
ensure-hosts --config ./hosts.local.yaml --remove-force
|
|
194
|
+
ensure-hosts --config ./hosts.local.yaml --remove --dry-run
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- `--remove` removes domains whose effective `rewrite` value is `true`. Domains marked `rewrite: false` are left untouched.
|
|
198
|
+
- `--remove-force` removes every domain listed by the config, including `rewrite: false` domains.
|
|
199
|
+
|
|
200
|
+
`--remove` and `--remove-force` cannot be used together, and neither can be combined with `--print-records`.
|
|
201
|
+
|
|
202
|
+
## Environment variables
|
|
203
|
+
|
|
204
|
+
The CLI automatically loads `.env` from the current working directory. Missing `.env` files and missing environment variables are ignored.
|
|
205
|
+
|
|
206
|
+
You can provide config paths with `ENSURE_HOSTS_CONFIG` instead of `--config`:
|
|
207
|
+
|
|
208
|
+
```dotenv
|
|
209
|
+
ENSURE_HOSTS_CONFIG=./hosts.local.yaml,./another.yaml
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
You can also override the hosts file path, which is useful for tests or custom workflows:
|
|
213
|
+
|
|
214
|
+
```dotenv
|
|
215
|
+
ENSURE_HOSTS_HOSTS_FILE=./tmp-hosts
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
To disable macOS/Windows elevation prompts:
|
|
219
|
+
|
|
220
|
+
```dotenv
|
|
221
|
+
ENSURE_HOSTS_NO_ELEVATE=true
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Use `--env-file <path>` if your dotenv file is not named `.env`.
|
|
225
|
+
|
|
226
|
+
## CLI options
|
|
227
|
+
|
|
228
|
+
```txt
|
|
229
|
+
--config <path> YAML/YML config file path (repeatable)
|
|
230
|
+
--env-file <path> dotenv file path (default: .env)
|
|
231
|
+
--hosts-file <path> override hosts file path
|
|
232
|
+
--dry-run print rewritten hosts content without writing
|
|
233
|
+
--print-records print expanded records and exit
|
|
234
|
+
--remove remove rewrite:true domains (respects rewrite:false)
|
|
235
|
+
--remove-force remove all listed domains, including rewrite:false
|
|
236
|
+
--no-elevate disable macOS/Windows privilege prompt
|
|
237
|
+
--help show help
|
|
238
|
+
--version show version
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Notes:
|
|
242
|
+
|
|
243
|
+
- On Linux, `--no-elevate` is effectively a no-op because Linux does not use an in-process elevation prompt. Run the command with `sudo` when needed.
|
|
244
|
+
- Use `--hosts-file` or `ENSURE_HOSTS_HOSTS_FILE` to test against a temporary file instead of the real hosts file.
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
Install dependencies:
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
npm install
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Run checks:
|
|
255
|
+
|
|
256
|
+
```sh
|
|
257
|
+
npm test
|
|
258
|
+
npm run typecheck
|
|
259
|
+
npm run build
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The repository also includes a Docker-based Linux test harness (`Dockerfile.linux-test` and `compose.linux-test.yaml`). These files are for testing only, not production.
|
|
263
|
+
|
|
264
|
+
```sh
|
|
265
|
+
# Run the unit test suite in a Linux container
|
|
266
|
+
docker compose -f compose.linux-test.yaml run --rm test
|
|
267
|
+
|
|
268
|
+
# Typecheck and build
|
|
269
|
+
docker compose -f compose.linux-test.yaml run --rm typecheck
|
|
270
|
+
docker compose -f compose.linux-test.yaml run --rm build
|
|
271
|
+
|
|
272
|
+
# Exercise CLI scenarios
|
|
273
|
+
docker compose -f compose.linux-test.yaml run --rm dry-run
|
|
274
|
+
docker compose -f compose.linux-test.yaml run --rm print-records
|
|
275
|
+
docker compose -f compose.linux-test.yaml run --rm root-write
|
|
276
|
+
docker compose -f compose.linux-test.yaml run --rm etc-hosts-write
|
|
277
|
+
docker compose -f compose.linux-test.yaml run --rm non-root-fail
|
|
278
|
+
docker compose -f compose.linux-test.yaml run --rm remove
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The `root-write`, `non-root-fail`, and `remove` services use `--hosts-file /tmp/test-hosts`, so the real `/etc/hosts` is not modified. The `etc-hosts-write` service writes to the container's ephemeral `/etc/hosts`, not your host machine.
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
MIT
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { appendFileSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { buildElevationArgs, loadDefaultEnv, loadProfiles, parseCliOptions, resolveConfigPaths, resolveHostsFileOverride, resolveNoElevate, } from './config.js';
|
|
5
|
+
import { expandProfiles } from './domain-map.js';
|
|
6
|
+
import { removeHostsContent, rewriteHostsContent } from './hosts.js';
|
|
7
|
+
import { elevatedCommandHint, elevationHandled, notifyRootWrite, resolveDefaultHostsPath, tryElevate } from './platform.js';
|
|
8
|
+
async function main() {
|
|
9
|
+
const options = parseCliOptions(process.argv.slice(2));
|
|
10
|
+
if (options.outputFile) {
|
|
11
|
+
redirectConsoleToFile(options.outputFile);
|
|
12
|
+
}
|
|
13
|
+
loadDefaultEnv(options.envFile);
|
|
14
|
+
const configPaths = resolveConfigPaths(options);
|
|
15
|
+
const profiles = loadProfiles(configPaths);
|
|
16
|
+
const expandedProfiles = expandProfiles(profiles);
|
|
17
|
+
if (options.printRecords) {
|
|
18
|
+
printRecords(expandedProfiles);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (options.remove || options.removeForce) {
|
|
22
|
+
return runRemove(options, configPaths, expandedProfiles);
|
|
23
|
+
}
|
|
24
|
+
const hostsFile = resolveHostsFileOverride(options) ?? resolveDefaultHostsPath();
|
|
25
|
+
const hostsContent = readFileSync(hostsFile, 'utf8');
|
|
26
|
+
const result = rewriteHostsContent(hostsContent, expandedProfiles);
|
|
27
|
+
if (options.dryRun) {
|
|
28
|
+
process.stdout.write(result.content);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (result.content === hostsContent) {
|
|
32
|
+
console.log('[ensure-hosts] hosts file is already up to date.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
notifyRootWrite(hostsFile);
|
|
37
|
+
writeFileSync(hostsFile, result.content, 'utf8');
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (isPermissionError(error)) {
|
|
41
|
+
const elevated = tryElevate({
|
|
42
|
+
scriptPath: fileURLToPath(import.meta.url),
|
|
43
|
+
args: buildElevationArgs(options, configPaths),
|
|
44
|
+
cwd: process.cwd(),
|
|
45
|
+
noElevate: resolveNoElevate(options),
|
|
46
|
+
elevated: options.elevated,
|
|
47
|
+
dryRun: options.dryRun,
|
|
48
|
+
printRecords: options.printRecords,
|
|
49
|
+
filePath: hostsFile,
|
|
50
|
+
content: result.content,
|
|
51
|
+
});
|
|
52
|
+
if (elevationHandled(elevated)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw new Error([
|
|
56
|
+
`Permission denied while writing hosts file: ${hostsFile}`,
|
|
57
|
+
'Run again with administrator/root privileges.',
|
|
58
|
+
elevatedCommandHint(`ensure-hosts --config ${configPaths.join(' --config ')}`),
|
|
59
|
+
].join('\n'));
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
console.log(`[ensure-hosts] updated ${hostsFile}: appended ${result.appended.length}, cleaned ${result.removedDomains.length}.`);
|
|
64
|
+
}
|
|
65
|
+
function runRemove(options, configPaths, expandedProfiles) {
|
|
66
|
+
const force = options.removeForce;
|
|
67
|
+
const hostsFile = resolveHostsFileOverride(options) ?? resolveDefaultHostsPath();
|
|
68
|
+
const hostsContent = readFileSync(hostsFile, 'utf8');
|
|
69
|
+
const result = removeHostsContent(hostsContent, expandedProfiles, { force });
|
|
70
|
+
if (options.dryRun) {
|
|
71
|
+
process.stdout.write(result.content);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (result.content === hostsContent) {
|
|
75
|
+
console.log('[ensure-hosts] hosts file has no matching entries to remove.');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
notifyRootWrite(hostsFile);
|
|
80
|
+
writeFileSync(hostsFile, result.content, 'utf8');
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (isPermissionError(error)) {
|
|
84
|
+
const elevated = tryElevate({
|
|
85
|
+
scriptPath: fileURLToPath(import.meta.url),
|
|
86
|
+
args: buildElevationArgs(options, configPaths),
|
|
87
|
+
cwd: process.cwd(),
|
|
88
|
+
noElevate: resolveNoElevate(options),
|
|
89
|
+
elevated: options.elevated,
|
|
90
|
+
dryRun: options.dryRun,
|
|
91
|
+
printRecords: options.printRecords,
|
|
92
|
+
filePath: hostsFile,
|
|
93
|
+
content: result.content,
|
|
94
|
+
});
|
|
95
|
+
if (elevationHandled(elevated)) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const modeFlag = force ? '--remove-force' : '--remove';
|
|
99
|
+
throw new Error([
|
|
100
|
+
`Permission denied while writing hosts file: ${hostsFile}`,
|
|
101
|
+
'Run again with administrator/root privileges.',
|
|
102
|
+
elevatedCommandHint(`ensure-hosts --config ${configPaths.join(' --config ')} ${modeFlag}`),
|
|
103
|
+
].join('\n'));
|
|
104
|
+
}
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
const modeLabel = force ? ' (force)' : '';
|
|
108
|
+
console.log(`[ensure-hosts] removed ${result.removedDomains.length} domain(s) from ${hostsFile}${modeLabel}.`);
|
|
109
|
+
}
|
|
110
|
+
function printRecords(expandedProfiles) {
|
|
111
|
+
for (const profile of expandedProfiles) {
|
|
112
|
+
for (const record of profile.records) {
|
|
113
|
+
console.log(`${record.address}\t${record.domain}\t# ${record.profile}\trewrite=${record.rewrite}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function redirectConsoleToFile(filePath) {
|
|
118
|
+
const write = (text) => appendFileSync(filePath, text);
|
|
119
|
+
const line = (args) => `${args.map(arg => (typeof arg === 'string' ? arg : String(arg))).join(' ')}\n`;
|
|
120
|
+
console.log = (...args) => write(line(args));
|
|
121
|
+
console.info = console.log;
|
|
122
|
+
console.warn = (...args) => write(line(args));
|
|
123
|
+
console.error = (...args) => write(line(args));
|
|
124
|
+
process.stdout.write = ((chunk) => {
|
|
125
|
+
write(typeof chunk === 'string' ? chunk : chunk.toString());
|
|
126
|
+
return true;
|
|
127
|
+
});
|
|
128
|
+
process.stderr.write = ((chunk) => {
|
|
129
|
+
write(typeof chunk === 'string' ? chunk : chunk.toString());
|
|
130
|
+
return true;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function isPermissionError(error) {
|
|
134
|
+
return (typeof error === 'object' &&
|
|
135
|
+
error !== null &&
|
|
136
|
+
'code' in error &&
|
|
137
|
+
(error.code === 'EACCES' || error.code === 'EPERM'));
|
|
138
|
+
}
|
|
139
|
+
main().catch(error => {
|
|
140
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
141
|
+
console.error(`[ensure-hosts] ${message}`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CliOptions, ProfileConfig } from './types.js';
|
|
2
|
+
export declare function parseCliOptions(argv: string[]): CliOptions;
|
|
3
|
+
export declare function loadDefaultEnv(envFile: string): void;
|
|
4
|
+
export declare function resolveConfigPaths(options: CliOptions, env?: NodeJS.ProcessEnv): string[];
|
|
5
|
+
export declare function resolveHostsFileOverride(options: CliOptions, env?: NodeJS.ProcessEnv): string | undefined;
|
|
6
|
+
export declare function resolveNoElevate(options: CliOptions, env?: NodeJS.ProcessEnv): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Rebuild the CLI args for an elevated child process from already-resolved
|
|
9
|
+
* (absolute) paths. The elevated re-spawn runs in a different working
|
|
10
|
+
* directory than the parent (osascript's `do shell script` starts in `/`),
|
|
11
|
+
* so any relative path the user passed would fail to resolve in the child.
|
|
12
|
+
* Passing absolute paths fixes that without changing the public CLI surface.
|
|
13
|
+
*
|
|
14
|
+
* Elevation-only flags (`--no-elevate`, `--elevated`) and `--output-file`
|
|
15
|
+
* (Windows elevated-output plumbing) are intentionally omitted: the child is
|
|
16
|
+
* re-elevated/redirected by the elevation layer itself, not by these flags.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildElevationArgs(options: CliOptions, configPaths: string[]): string[];
|
|
19
|
+
export declare function loadProfiles(configPaths: string[]): ProfileConfig[];
|
|
20
|
+
export declare function loadProfile(configPath: string): ProfileConfig;
|
|
21
|
+
export declare function usage(): string;
|